Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import folium | |
| import networkx as nx | |
| from folium import Map, Marker, PolyLine, Popup, IFrame | |
| from math import radians, cos, sin, sqrt, atan2 | |
| from branca.element import MacroElement | |
| from jinja2 import Template | |
| # 1. Districts and Coordinates (Harimo Kigali) | |
| places = { | |
| "Kigali": (-1.9441, 30.0619), | |
| "Nyarugenge": (-1.9577, 30.0619), | |
| "Gasabo": (-1.9400, 30.0861), | |
| "Kicukiro": (-1.9781, 30.0597), | |
| "Burera": (-1.4800, 29.7300), | |
| "Gakenke": (-1.5700, 29.7561), | |
| "Rulindo": (-1.8333, 30.0833), | |
| "Musanze": (-1.5014, 29.6344), | |
| "Gicumbi": (-1.5794, 30.0542), | |
| "Nyagatare": (-1.3100, 30.3000), | |
| "Gatsibo": (-1.6800, 30.3900), | |
| "Kayonza": (-2.0000, 30.5667), | |
| "Kirehe": (-2.3553, 30.7767), | |
| "Ngoma": (-2.1600, 30.4700), | |
| "Rwamagana": (-1.9491, 30.4349), | |
| "Bugesera": (-2.2083, 30.2576), | |
| "Kamonyi": (-2.0833, 29.9000), | |
| "Muhanga": (-2.1200, 29.7561), | |
| "Ruhango": (-2.2136, 29.7628), | |
| "Nyamagabe": (-2.4978, 29.4897), | |
| "Nyaruguru": (-2.5806, 29.4306), | |
| "Huye": (-2.5921, 29.7408), | |
| "Gisagara": (-2.6283, 29.6820), | |
| "Nyanza": (-2.3566, 29.7507), | |
| "Rutsiro": (-2.0986, 29.3269), | |
| "Karongi": (-2.0667, 29.4677), | |
| "Rubavu": (-1.7481, 29.2730), | |
| "Rusizi": (-2.5406, 29.3737), | |
| "Nyamasheke": (-2.4700, 29.3222), | |
| "Ngororero": (-1.8733, 29.5811) | |
| } | |
| # 2. Place images URLs | |
| place_images = { | |
| "Kigali": "https://upload.wikimedia.org/wikipedia/commons/8/89/Kigali_city_view.jpg", | |
| "Nyarugenge": "https://upload.wikimedia.org/wikipedia/commons/f/f8/Nyarugenge_district.jpg", | |
| "Gasabo": "https://upload.wikimedia.org/wikipedia/commons/a/a5/Gasabo_district.jpg", | |
| "Kicukiro": "https://upload.wikimedia.org/wikipedia/commons/1/10/Kicukiro_District_-_Rwanda.jpg", | |
| "Burera": "https://upload.wikimedia.org/wikipedia/commons/3/33/Burera_Lake_Muhazi.jpg", | |
| "Gakenke": "https://upload.wikimedia.org/wikipedia/commons/c/c4/Gakenke_landscape.jpg", | |
| "Rulindo": "https://upload.wikimedia.org/wikipedia/commons/0/01/Rulindo_landscape.jpg", | |
| "Musanze": "https://upload.wikimedia.org/wikipedia/commons/6/6c/Musanze_scenery.jpg", | |
| "Gicumbi": "https://upload.wikimedia.org/wikipedia/commons/7/7e/Gicumbi_landscape.jpg", | |
| "Nyagatare": "https://upload.wikimedia.org/wikipedia/commons/9/98/Nyagatare_landscape.jpg", | |
| "Gatsibo": "https://upload.wikimedia.org/wikipedia/commons/f/f0/Gatsibo_landscape.jpg", | |
| "Kayonza": "https://upload.wikimedia.org/wikipedia/commons/b/b6/Kayonza_landscape.jpg", | |
| "Kirehe": "https://upload.wikimedia.org/wikipedia/commons/3/3f/Kirehe_landscape.jpg", | |
| "Ngoma": "https://upload.wikimedia.org/wikipedia/commons/4/49/Ngoma_landscape.jpg", | |
| "Rwamagana": "https://upload.wikimedia.org/wikipedia/commons/0/00/Rwamagana_landscape.jpg", | |
| "Bugesera": "https://upload.wikimedia.org/wikipedia/commons/1/12/Bugesera_landscape.jpg", | |
| "Kamonyi": "https://upload.wikimedia.org/wikipedia/commons/d/d4/Kamonyi_landscape.jpg", | |
| "Muhanga": "https://upload.wikimedia.org/wikipedia/commons/2/2a/Muhanga_landscape.jpg", | |
| "Ruhango": "https://upload.wikimedia.org/wikipedia/commons/9/96/Ruhango_landscape.jpg", | |
| "Nyamagabe": "https://upload.wikimedia.org/wikipedia/commons/8/80/Nyamagabe_landscape.jpg", | |
| "Nyaruguru": "https://upload.wikimedia.org/wikipedia/commons/6/63/Nyaruguru_landscape.jpg", | |
| "Huye": "https://upload.wikimedia.org/wikipedia/commons/7/7a/Huye_landscape.jpg", | |
| "Gisagara": "https://upload.wikimedia.org/wikipedia/commons/8/8c/Gisagara_landscape.jpg", | |
| "Nyanza": "https://upload.wikimedia.org/wikipedia/commons/3/3a/Nyanza_landscape.jpg", | |
| "Rutsiro": "https://upload.wikimedia.org/wikipedia/commons/5/5f/Rutsiro_landscape.jpg", | |
| "Karongi": "https://upload.wikimedia.org/wikipedia/commons/f/f5/Karongi_landscape.jpg", | |
| "Rubavu": "https://upload.wikimedia.org/wikipedia/commons/6/68/Rubavu_landscape.jpg", | |
| "Rusizi": "https://upload.wikimedia.org/wikipedia/commons/3/30/Rusizi_landscape.jpg", | |
| "Nyamasheke": "https://upload.wikimedia.org/wikipedia/commons/1/17/Nyamasheke_landscape.jpg", | |
| "Ngororero": "https://upload.wikimedia.org/wikipedia/commons/7/7d/Ngororero_landscape.jpg" | |
| } | |
| # 3. Distance calculator (Haversine Formula) | |
| def haversine(coord1, coord2): | |
| R = 6371 # Earth radius in km | |
| lat1, lon1 = coord1 | |
| lat2, lon2 = coord2 | |
| dlat = radians(lat2 - lat1) | |
| dlon = radians(lon2 - lon1) | |
| a = sin(dlat / 2)**2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon / 2)**2 | |
| c = 2 * atan2(sqrt(a), sqrt(1 - a)) | |
| return R * c | |
| # 4. Edges (connect Kigali and other districts) | |
| edges = [ | |
| ("Nyarugenge", "Gasabo"), ("Gasabo", "Kicukiro"), ("Kicukiro", "Bugesera"), ("Bugesera", "Rwamagana"), | |
| ("Rwamagana", "Kayonza"), ("Kayonza", "Kirehe"), ("Kirehe", "Ngoma"), ("Ngoma", "Gatsibo"), | |
| ("Gatsibo", "Nyagatare"), ("Gatsibo", "Gicumbi"), ("Gicumbi", "Rulindo"), ("Rulindo", "Gakenke"), | |
| ("Gakenke", "Burera"), ("Burera", "Musanze"), ("Musanze", "Rubavu"), ("Rubavu", "Rutsiro"), | |
| ("Rutsiro", "Karongi"), ("Karongi", "Nyamasheke"), ("Nyamasheke", "Rusizi"), ("Rutsiro", "Ngororero"), | |
| ("Ngororero", "Muhanga"), ("Muhanga", "Kamonyi"), ("Kamonyi", "Nyarugenge"), ("Muhanga", "Ruhango"), | |
| ("Ruhango", "Nyanza"), ("Nyanza", "Huye"), ("Huye", "Gisagara"), ("Gisagara", "Nyaruguru"), | |
| ("Nyaruguru", "Nyamagabe"), ("Nyamagabe", "Karongi"), ("Ngororero", "Ruhango"), | |
| ("Gicumbi", "Gasabo"), ("Bugesera", "Ngoma"), | |
| ("Kigali", "Nyarugenge"), ("Kigali", "Gasabo"), ("Kigali", "Kicukiro") | |
| ] | |
| # 5. Create Graph | |
| G = nx.Graph() | |
| for u, v in edges: | |
| G.add_edge(u, v, weight=haversine(places[u], places[v])) | |
| # 6. Animation class for marker movement | |
| class AnimateMarker(MacroElement): | |
| _template = Template(""" | |
| {% macro script(this, kwargs) %} | |
| var marker = L.marker({{this.locations[0]}}).addTo({{this._parent.get_name()}}); | |
| var latlngs = {{this.locations}}; | |
| var index = 0; | |
| function moveMarker(){ | |
| index++; | |
| if(index >= latlngs.length){ | |
| return; | |
| } | |
| marker.setLatLng(latlngs[index]); | |
| setTimeout(moveMarker, 700); | |
| } | |
| moveMarker(); | |
| {% endmacro %} | |
| """) | |
| def __init__(self, locations): | |
| super().__init__() | |
| self._name = "AnimateMarker" | |
| self.locations = locations | |
| # 7. Routing function with popup images on map markers | |
| def generate_map(start, end): | |
| if start == end: | |
| return "Hitamo aho utangiriye n’aho ugiye bitandukanye.", "", "" | |
| if not nx.has_path(G, start, end): | |
| return f"Nta nzira ibaho hagati ya {start} na {end}.", "", "" | |
| try: | |
| path = nx.astar_path(G, start, end, heuristic=lambda u, v: haversine(places[u], places[v]), weight='weight') | |
| coords = [places[p] for p in path] | |
| m = Map(location=[-1.9441, 30.0619], zoom_start=9) | |
| # Add markers for all places (normal popup with name) | |
| for name, coord in places.items(): | |
| if name == start or name == end: | |
| # For start and end: popup with image + name | |
| img_url = place_images.get(name, "https://via.placeholder.com/300?text=No+Image") | |
| html = f""" | |
| <h4>{name}</h4> | |
| <img src="{img_url}" width="300" style="border-radius:8px;"/> | |
| """ | |
| iframe = IFrame(html, width=320, height=320) | |
| popup = Popup(iframe, max_width=320) | |
| Marker(location=coord, popup=popup, icon=folium.Icon(color='green' if name == start else 'red')).add_to(m) | |
| else: | |
| Marker(location=coord, popup=name).add_to(m) | |
| # Draw the route line | |
| PolyLine(coords, color="blue", weight=5).add_to(m) | |
| m.add_child(AnimateMarker(coords)) | |
| return "Inzira ngufi ni: " + " ➔ ".join(path), m._repr_html_(), "" | |
| except Exception as e: | |
| return f"Ntibishoboka kubona inzira: {str(e)}", "", "" | |
| # 8. Gradio interface | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## Shaka inzira ngufi hagati y’uturere twa Rwanda") | |
| start = gr.Dropdown(list(places.keys()), label="Aho utangirira") | |
| end = gr.Dropdown(list(places.keys()), label="Aho ugiye") | |
| btn = gr.Button("Shaka inzira") | |
| output_text = gr.Textbox(label="Inzira", interactive=False) | |
| output_map = gr.HTML() | |
| btn.click(fn=generate_map, inputs=[start, end], outputs=[output_text, output_map, gr.Textbox(visible=False)]) | |
| demo.launch() | |