Spaces:
Running
Running
import gradio as gr | |
import folium | |
import networkx as nx | |
from folium import Map, Marker, PolyLine | |
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), # Kigali city center | |
"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. 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 | |
# 3. 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 connections | |
("Kigali", "Nyarugenge"), ("Kigali", "Gasabo"), ("Kigali", "Kicukiro") | |
] | |
# 4. Create Graph | |
G = nx.Graph() | |
for u, v in edges: | |
G.add_edge(u, v, weight=haversine(places[u], places[v])) | |
# 5. Animation class | |
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 | |
# 6. Routing Function | |
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) | |
for name, coord in places.items(): | |
Marker(location=coord, popup=name).add_to(m) | |
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)}", "" | |
# 7. Gradio Interface | |
iface = gr.Interface( | |
fn=generate_map, | |
inputs=[ | |
gr.Dropdown(list(places.keys()), label="Hitamo aho uri"), | |
gr.Dropdown(list(places.keys()), label="Hitamo aho ugiye") | |
], | |
outputs=[ | |
gr.Textbox(label="Ubutumwa"), | |
gr.HTML(label="Ikarita") | |
], | |
title="🗺️ VIATEUR AI - Rwanda Smart Route Planner", | |
theme="default" | |
) | |
iface.launch() | |