import networkx as nx import math def compute_distance(t1, t2): """ Compute Euclidean distance between two towers in the horizontal plane. """ dx = t1['position_x'] - t2['position_x'] dz = t1['position_z'] - t2['position_z'] return math.sqrt(dx**2 + dz**2) def compute_mst_fiber_paths(towers): """ Given a list of tower dictionaries, compute a Minimum Spanning Tree (MST) and return a list of fiber paths connecting the towers. """ G = nx.Graph() # Add towers as nodes for tower in towers: G.add_node(tower['id'], **tower) # Add edges: compute pairwise distances n = len(towers) for i in range(n): for j in range(i+1, n): d = compute_distance(towers[i], towers[j]) G.add_edge(towers[i]['id'], towers[j]['id'], weight=d) # Compute MST mst = nx.minimum_spanning_tree(G) fiber_paths = [] for edge in mst.edges(data=True): id1, id2, data = edge # Find towers corresponding to these IDs tower1 = next(t for t in towers if t['id'] == id1) tower2 = next(t for t in towers if t['id'] == id2) fiber_paths.append({ 'id': len(fiber_paths) + 1, 'start_x': tower1['position_x'], 'start_z': tower1['position_z'], 'end_x': tower2['position_x'], 'end_z': tower2['position_z'], 'mid_x': (tower1['position_x'] + tower2['position_x']) / 2, 'mid_y': 0.1, # Slightly above the ground 'mid_z': (tower1['position_z'] + tower2['position_z']) / 2, 'length': data['weight'], # Optionally, compute the angle in degrees if needed: 'angle': math.degrees(math.atan2(tower2['position_x'] - tower1['position_x'], tower2['position_z'] - tower1['position_z'])), 'status': 'Connected', 'color': '#4682b4' }) return fiber_paths def compute_network_summary(towers, fiber_paths, wifi_hotspots): total_fiber = sum(fiber['length'] for fiber in fiber_paths) return { 'num_towers': len(towers), 'total_fiber_length': total_fiber, 'num_wifi': len(wifi_hotspots), }