import osmnx as ox import shapely import random import uuid def generate_osm_city_data(lat, lon, dist=400, scale=1.0): print(f"🏙️ Fetching OSM buildings at ({lat}, {lon})") scale_factor = scale # Shrinks the city to make the camera look like a giant # ————— BUILDINGS ————— tags = {"building": True} gdf = ox.features_from_point((lat, lon), tags=tags, dist=dist) gdf = gdf[gdf.geometry.type.isin(["Polygon", "MultiPolygon"])].copy() gdf = gdf.to_crs(epsg=3857) gdf["centroid"] = gdf.geometry.centroid status_options = ["OK", "Warning", "Critical", "Offline"] raw_buildings = [] for i, row in gdf.iterrows(): centroid = row["centroid"] polygon = row["geometry"] try: height = float(row.get("height", None)) except: try: height = float(row.get("building:levels", 3)) * 3.2 except: height = 10.0 building_id = f"BLD-{uuid.uuid4().hex[:6].upper()}" status = random.choice(status_options) raw_buildings.append({ "id": building_id, "raw_x": centroid.x, "raw_z": centroid.y, "width": polygon.bounds[2] - polygon.bounds[0], "depth": polygon.bounds[3] - polygon.bounds[1], "height": height, "color": "#8a2be2", "status": status, }) # ————— CENTER AND SCALE ————— if raw_buildings: avg_x = sum(b['raw_x'] for b in raw_buildings) / len(raw_buildings) avg_z = sum(b['raw_z'] for b in raw_buildings) / len(raw_buildings) buildings = [] for b in raw_buildings: buildings.append({ "id": b['id'], "position_x": (b['raw_x'] - avg_x) * scale_factor, "position_z": (b['raw_z'] - avg_z) * scale_factor, "width": b['width'] * scale_factor, "depth": b['depth'] * scale_factor, "height": b['height'] * scale_factor, "color": b['color'], "status": b['status'], }) else: buildings = [] return { "buildings": buildings, }