Release v2.5 - POI markers op interactieve kaart
- Supermarkt en school markers als gekleurde cirkels op de Leaflet kaart - Popups met hemelsbreed/fiets/auto afstanden per voorziening - Legenda uitgebreid met POI categorieën - voorzieningen.py: format_afstand/format_duur exports toegevoegd
This commit is contained in:
+69
-5
@@ -21,7 +21,7 @@ try:
|
||||
except ImportError:
|
||||
HAS_PIL = False
|
||||
|
||||
from voorzieningen import analyse_voorzieningen, format_voorzieningen_markdown
|
||||
from voorzieningen import analyse_voorzieningen, format_voorzieningen_markdown, format_afstand, format_duur
|
||||
|
||||
# Config
|
||||
ORS_BASE = "http://192.168.1.71:9080/ors/v2"
|
||||
@@ -105,8 +105,25 @@ def schrijf_naar_mkdocs(content, adres, nummer, ext=".md"):
|
||||
|
||||
return filepath, filename
|
||||
|
||||
def genereer_isochroon_html(adres_naam, lat, lon, auto_iso, fiets_iso):
|
||||
"""Genereer een zelf-contained HTML kaart met Leaflet"""
|
||||
def genereer_isochroon_html(adres_naam, lat, lon, auto_iso, fiets_iso, voorzieningen=None):
|
||||
"""Genereer een zelf-contained HTML kaart met Leaflet + POI markers"""
|
||||
# Bouw JSON voor POI markers
|
||||
poi_json = {"supermarkten": [], "scholen": []}
|
||||
if voorzieningen:
|
||||
for s in voorzieningen.get("supermarkten", []):
|
||||
poi_json["supermarkten"].append({
|
||||
"naam": s.naam, "lat": s.lat, "lon": s.lon,
|
||||
"hemelsbreed": round(s.hemelsbreed_m),
|
||||
"fiets": f"{format_afstand(s.fiets_afstand_m)} / {format_duur(s.fiets_duur_s)}" if s.fiets_afstand_m else "n.b.",
|
||||
"auto": f"{format_afstand(s.auto_afstand_m)} / {format_duur(s.auto_duur_s)}" if s.auto_afstand_m else "n.b.",
|
||||
})
|
||||
for s in voorzieningen.get("scholen", []):
|
||||
poi_json["scholen"].append({
|
||||
"naam": s.naam, "lat": s.lat, "lon": s.lon,
|
||||
"hemelsbreed": round(s.hemelsbreed_m),
|
||||
"fiets": f"{format_afstand(s.fiets_afstand_m)} / {format_duur(s.fiets_duur_s)}" if s.fiets_afstand_m else "n.b.",
|
||||
"auto": f"{format_afstand(s.auto_afstand_m)} / {format_duur(s.auto_duur_s)}" if s.auto_afstand_m else "n.b.",
|
||||
})
|
||||
html = f'''<!DOCTYPE html>
|
||||
<html lang="nl">
|
||||
<head>
|
||||
@@ -127,6 +144,7 @@ def genereer_isochroon_html(adres_naam, lat, lon, auto_iso, fiets_iso):
|
||||
<script>
|
||||
var autoGeojson = {json.dumps(auto_iso, ensure_ascii=False)};
|
||||
var fietsGeojson = {json.dumps(fiets_iso, ensure_ascii=False)};
|
||||
var voorzieningen = {json.dumps(poi_json, ensure_ascii=False)};
|
||||
|
||||
var map = L.map('map').setView([{lat}, {lon}], 11);
|
||||
|
||||
@@ -150,16 +168,61 @@ var fietsLayer = L.geoJSON(fietsGeojson, {{
|
||||
}}
|
||||
}}).addTo(map);
|
||||
|
||||
// Adres marker
|
||||
L.marker([{lat}, {lon}]).addTo(map)
|
||||
.bindPopup('<b>{adres_naam}</b>').openPopup();
|
||||
|
||||
// POI markers
|
||||
var supermarktIcon = L.divIcon({{
|
||||
className: 'poi-marker-supermarkt',
|
||||
html: '<div style="background:#2563eb;color:white;width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:bold;border:2px solid white;box-shadow:0 1px 4px rgba(0,0,0,0.3)">S</div>',
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [12, 12],
|
||||
popupAnchor: [0, -14]
|
||||
}});
|
||||
var schoolIcon = L.divIcon({{
|
||||
className: 'poi-marker-school',
|
||||
html: '<div style="background:#ea580c;color:white;width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:bold;border:2px solid white;box-shadow:0 1px 4px rgba(0,0,0,0.3)">S</div>',
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [12, 12],
|
||||
popupAnchor: [0, -14]
|
||||
}});
|
||||
|
||||
// Supermarkten
|
||||
if (voorzieningen.supermarkten) {{
|
||||
voorzieningen.supermarkten.forEach(function(p) {{
|
||||
L.marker([p.lat, p.lon], {{icon: supermarktIcon}}).addTo(map)
|
||||
.bindPopup(
|
||||
'<b>🛒 ' + p.naam + '</b><br>' +
|
||||
'Hemelsbreed: ' + p.hemelsbreed + ' m<br>' +
|
||||
'Fiets: ' + p.fiets + '<br>' +
|
||||
'Auto: ' + p.auto
|
||||
);
|
||||
}});
|
||||
}}
|
||||
|
||||
// Scholen
|
||||
if (voorzieningen.scholen) {{
|
||||
voorzieningen.scholen.forEach(function(p) {{
|
||||
L.marker([p.lat, p.lon], {{icon: schoolIcon}}).addTo(map)
|
||||
.bindPopup(
|
||||
'<b>🏫 ' + p.naam + '</b><br>' +
|
||||
'Hemelsbreed: ' + p.hemelsbreed + ' m<br>' +
|
||||
'Fiets: ' + p.fiets + '<br>' +
|
||||
'Auto: ' + p.auto
|
||||
);
|
||||
}});
|
||||
}}
|
||||
|
||||
var legend = L.control({{position: 'bottomright'}});
|
||||
legend.onAdd = function(map) {{
|
||||
var div = L.DomUtil.create('div', 'legend');
|
||||
div.innerHTML += '<h4 style="margin:0 0 5px 0">Isochronen</h4>';
|
||||
div.innerHTML += '<i style="background:#3b82f6"></i> Auto 20 min<br>';
|
||||
div.innerHTML += '<i style="background:#22c55e"></i> Fiets 30 min<br>';
|
||||
div.innerHTML += '<i style="background:#ef4444"></i> Adres';
|
||||
div.innerHTML += '<i style="background:#ef4444"></i> Adres<br>';
|
||||
div.innerHTML += '<i style="background:#2563eb;border-radius:50%;width:12px;height:12px;border:1px solid #999"></i> Supermarkt<br>';
|
||||
div.innerHTML += '<i style="background:#ea580c;border-radius:50%;width:12px;height:12px;border:1px solid #999"></i> School';
|
||||
return div;
|
||||
}};
|
||||
legend.addTo(map);
|
||||
@@ -224,7 +287,8 @@ def genereer_rapport(adres_input):
|
||||
|
||||
# Genereer interactieve HTML kaart en sla op in MkDocs
|
||||
html_content = genereer_isochroon_html(
|
||||
locatie['adres'], locatie['lat'], locatie['lon'], auto_iso, fiets_iso
|
||||
locatie['adres'], locatie['lat'], locatie['lon'], auto_iso, fiets_iso,
|
||||
voorzieningen=voorzieningen
|
||||
)
|
||||
html_filepath, html_filename = schrijf_naar_mkdocs(html_content, locatie['adres'], nummer, ext=".html")
|
||||
|
||||
|
||||
+7
-7
@@ -136,13 +136,13 @@ def format_voorzieningen_markdown(titel, pois):
|
||||
if not pois:
|
||||
lines.append("Geen voorzieningen gevonden in zoekradius.")
|
||||
return "\n".join(lines)
|
||||
for i, p in enumerate(pois, 1):
|
||||
lines.extend([
|
||||
f"{i}. **{p.naam}**",
|
||||
f" Hemelsbreed: {format_afstand(p.hemelsbreed_m)}",
|
||||
f" Fiets: {format_afstand(p.fiets_afstand_m)} / {format_duur(p.fiets_duur_s)}",
|
||||
f" Auto: {format_afstand(p.auto_afstand_m)} / {format_duur(p.auto_duur_s)}",
|
||||
])
|
||||
for p in pois:
|
||||
lines.append(
|
||||
f"• **{p.naam}** — "
|
||||
f"Hemelsbreed: {format_afstand(p.hemelsbreed_m)} | "
|
||||
f"Fiets: {format_afstand(p.fiets_afstand_m)} / {format_duur(p.fiets_duur_s)} | "
|
||||
f"Auto: {format_afstand(p.auto_afstand_m)} / {format_duur(p.auto_duur_s)}"
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user