94 lines
3.4 KiB
Python
94 lines
3.4 KiB
Python
import folium
|
|
import geopandas as gpd
|
|
from pathlib import Path
|
|
import json
|
|
|
|
# Load the GeoJSON file and ensure the 'id' field is included
|
|
geojson_path = Path(__file__).parent / 'input_files' / 'buildings_to_map.geojson'
|
|
with open(geojson_path, 'r') as f:
|
|
geojson_data = json.load(f)
|
|
|
|
# Convert GeoJSON to GeoDataFrame, explicitly adding 'id' as a column
|
|
geo_data = gpd.GeoDataFrame.from_features(geojson_data["features"])
|
|
geo_data["id"] = [feature["id"] for feature in geojson_data["features"]]
|
|
|
|
# Ensure the GeoDataFrame has a CRS (assuming WGS84 if not already defined)
|
|
if geo_data.crs is None:
|
|
geo_data.set_crs(epsg=4326, inplace=True)
|
|
|
|
|
|
# Function to assign colors based on building function
|
|
def get_color(building_function):
|
|
color_map = {
|
|
"residential": "lightblue", # Changed from blue to lightblue for better text visibility
|
|
"secondary school": "green",
|
|
"medium office": "red",
|
|
"sports location": "orange", # Example for your data
|
|
"stand alone retail": "purple"
|
|
}
|
|
return color_map.get(building_function, "gray") # Default color is gray
|
|
|
|
|
|
# Create a style function for the GeoJson layer
|
|
def style_function(feature):
|
|
building_function = feature["properties"].get("function", "unknown")
|
|
return {
|
|
"fillColor": get_color(building_function),
|
|
"color": "black", # Outline color
|
|
"weight": 1,
|
|
"fillOpacity": 0.6
|
|
}
|
|
|
|
|
|
# Get the centroid coordinates for the map center
|
|
centroid = geo_data.geometry.centroid.iloc[0]
|
|
center = (centroid.y, centroid.x) # lat, lon
|
|
|
|
# Create a Folium map with CartoDB Positron tiles
|
|
m = folium.Map(location=center, zoom_start=50, tiles="CartoDB positron")
|
|
|
|
# Add the GeoJSON layer with color-coded styles
|
|
folium.GeoJson(
|
|
geojson_data,
|
|
name="Buildings",
|
|
style_function=style_function
|
|
).add_to(m)
|
|
|
|
# Add labels for each building
|
|
for _, row in geo_data.iterrows():
|
|
feature_id = row['id'] # Access the 'id' attribute
|
|
feature_centroid = row['geometry'].centroid # Get the centroid of the feature
|
|
|
|
# Create a rotated label
|
|
folium.Marker(
|
|
location=(feature_centroid.y, feature_centroid.x),
|
|
icon=folium.DivIcon(html=f'<div style="transform: rotate(90deg); font-size: 14px;">{feature_id}</div>')
|
|
).add_to(m)
|
|
|
|
# Add a legend to the map
|
|
legend_html = '''
|
|
<div style="
|
|
position: fixed;
|
|
bottom: 30px; left: 30px; width: 250px; height: 200px;
|
|
background-color: white;
|
|
border:2px solid grey; z-index:9999; font-size:14px;
|
|
padding: 10px; box-shadow: 2px 2px 5px rgba(0,0,0,0.3);">
|
|
<b>Legend</b><br>
|
|
<i style="background: lightblue; width: 10px; height: 10px; display: inline-block; margin-right: 5px;"></i> Residential<br>
|
|
<i style="background: green; width: 10px; height: 10px; display: inline-block; margin-right: 5px;"></i> Secondary School<br>
|
|
<i style="background: red; width: 10px; height: 10px; display: inline-block; margin-right: 5px;"></i> Medium Office<br>
|
|
<i style="background: orange; width: 10px; height: 10px; display: inline-block; margin-right: 5px;"></i> Sports Location<br>
|
|
<i style="background: purple; width: 10px; height: 10px; display: inline-block; margin-right: 5px;"></i> Stand Alone Retail<br>
|
|
</div>
|
|
'''
|
|
m.get_root().html.add_child(folium.Element(legend_html))
|
|
|
|
# Add a layer control to toggle layers
|
|
folium.LayerControl().add_to(m)
|
|
|
|
# Save the map as an HTML file
|
|
map_output_path = 'buildings_map_colored_with_legend.html'
|
|
m.save(map_output_path)
|
|
|
|
print(f"Map saved as {map_output_path}")
|