import folium
import gradio as gr
import os
from bs4 import BeautifulSoup
import simplekml
# Function to create the permaculture map
def create_permaculture_map(coordinates, output_dir="output"):
# Create base map
m = folium.Map(
location=coordinates,
zoom_start=18,
control_scale=True,
tiles="cartodbpositron"
)
# Add north arrow
north_arrow = """
↑ N
"""
m.get_root().html.add_child(folium.Element(north_arrow))
# Add scale
folium.plugins.MousePosition().add_to(m)
# Add map elements
elements = {
"Building": {"loc": [0.0001, 0.0001], "color": "red", "icon": "home"},
"Vegetation": {"loc": [-0.0001, -0.0001], "color": "green", "icon": "tree"},
"Water Management": {"loc": [0.0003, -0.0003], "color": "blue", "icon": "tint"},
"Energy": {"loc": [-0.0003, 0.0003], "color": "orange", "icon": "bolt"}
}
for name, props in elements.items():
folium.Marker(
location=[coordinates[0] + props["loc"][0],
coordinates[1] + props["loc"][1]],
icon=folium.Icon(color=props["color"], icon=props["icon"]),
popup=name
).add_to(m)
# Add paths
folium.PolyLine(
locations=[
[coordinates[0] - 0.0002, coordinates[1] - 0.0002],
[coordinates[0] + 0.0002, coordinates[1] + 0.0002]
],
color="brown",
weight=2,
popup="Path"
).add_to(m)
# Save map
os.makedirs(output_dir, exist_ok=True)
map_path = os.path.join(output_dir, "map.html")
m.save(map_path)
return map_path
# Gradio interface
def generate_map(lat, lon):
# Validate coordinates
if not (-90 <= lat <= 90) or not (-180 <= lon <= 180):
raise gr.Error("Invalid coordinates! Lat: -90 to 90, Lon: -180 to 180")
map_path = create_permaculture_map([lat, lon])
with open(map_path, "r") as f:
html = f.read()
return f''
# Create Gradio app
with gr.Blocks() as app:
gr.Markdown("# 🌱 Permaculture Base Map Designer")
with gr.Row():
with gr.Column():
# Map location picker
map_picker = gr.Map(label="Click map to select location", height=300)
# Coordinate inputs
with gr.Row():
lat_input = gr.Number(label="Latitude", value=45.5236)
lon_input = gr.Number(label="Longitude", value=-122.6750)
gr.Markdown("### Map Options")
gr.Button("Generate Map").click(
generate_map,
inputs=[lat_input, lon_input],
outputs=gr.HTML(label="Generated Map")
)
# Display generated map
with gr.Column():
gr.HTML(label="Generated Map")
# Connect map clicks to coordinate inputs
def update_coords(map_data):
if map_data and map_data.get("features"):
lon, lat = map_data["features"][0]["geometry"]["coordinates"]
return lat, lon
return None, None
map_picker.select(update_coords, outputs=[lat_input, lon_input])
# Launch app
if __name__ == "__main__":
app.launch()