import os import json import argparse import heapq import math # Hilfsfunktionen def load_json(filepath): with open(filepath, 'r', encoding='utf-8') as f: return json.load(f) def parse_pos(pos_str): """ Konvertiert '(x, y)' oder '(x, y, z)' in ein Tuple """ try: return tuple(map(float, pos_str.strip('()').split(','))) except Exception: raise ValueError(f"Ungültiges Positionsformat: {pos_str}") def distance(p1, p2): """ Euklidische Distanz in 2D """ return math.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2) def add_edge(graph, node1, node2, dist): """ Fügt eine Kante zwischen zwei Knoten im Graphen hinzu """ if node1 not in graph: graph[node1] = [] if node2 not in graph: graph[node2] = [] graph[node1].append((node2, dist)) graph[node2].append((node1, dist)) def project_point_on_segment(p, a, b): """Projektion eines Punktes p auf ein Liniensegment a-b""" ax, ay = a bx, by = b px, py = p dx = bx - ax dy = by - ay if dx == dy == 0: return a t = ((px - ax) * dx + (py - ay) * dy) / (dx * dx + dy * dy) t = max(0, min(1, t)) # Begrenze t auf [0,1] return (ax + t * dx, ay + t * dy) def dijkstra(graph, start): """ Dijkstra-Algorithmus, um die kürzesten Wege im Graphen zu berechnen """ distances = {node: float('inf') for node in graph} distances[start] = 0 priority_queue = [(0, start)] # (Distanz, Knoten) while priority_queue: current_distance, current_node = heapq.heappop(priority_queue) if current_distance > distances[current_node]: continue for neighbor, weight in graph[current_node]: distance = current_distance + weight if distance < distances[neighbor]: distances[neighbor] = distance heapq.heappush(priority_queue, (distance, neighbor)) return distances if __name__ == "__main__": parser = argparse.ArgumentParser(description='Berechne Wege von Sensoren zu Verteilern über Kabeltrassen') parser.add_argument('-c', '--console', action='store_true', help='Ausgabe auf Konsole') args = parser.parse_args() # Umgebungsvariablen work_dir = os.environ.get("PROJECT_WORK") config_dir = os.environ.get("PROJECT_CFG") # Pfade zu JSON-Dateien sensors_path = os.path.join(work_dir, "sensors.json") subdist_path = os.path.join(work_dir, "subdistributors.json") racks_path = os.path.join(work_dir, "racks.json") # Einlesen sensors = load_json(sensors_path) subdists = {k: parse_pos(v) for k, v in load_json(subdist_path).items()} racks = load_json(racks_path) # Graph erstellen graph = {} # Sensoren zu Kabeltrassen verbinden for sensor_id, sensor_info in sensors.items(): #über alle Sensoren und alle deren Infos laufen sensor_pos = tuple(sensor_info['pos']) #sensor position als tuple übergeben for rack in racks: for segment_start, segment_end in zip(rack[:-1], rack[1:]): # Berechne Distanz von Sensor zur Kabeltrasse px, py = project_point_on_segment(sensor_pos, segment_start, segment_end) dist = distance(sensor_pos, (px, py)) add_edge(graph, sensor_id, f"rack_{rack}", dist) # Unterverteiler zu Kabeltrassen verbinden for uc_id, uc_pos in subdists.items(): for rack in racks: for segment_start, segment_end in zip(rack[:-1], rack[1:]): # Berechne Distanz von UC zur Kabeltrasse px, py = project_point_on_segment(uc_pos, segment_start, segment_end) dist = distance(uc_pos, (px, py)) add_edge(graph, uc_id, f"rack_{rack}", dist) # Sensor zu UC verbinden (Routing von Sensoren zu den zugehörigen Unterverteilern) for sensor_id, sensor_info in sensors.items(): subdist_id = None if 'KENNZEICHNUNG' in sensor_info: for uc_id in subdists: if uc_id in sensor_info['KENNZEICHNUNG']: subdist_id = uc_id break if subdist_id: # Verbinde den Sensor mit dem zugehörigen Unterverteiler sensor_pos = tuple(sensor_info['pos']) uc_pos = subdists[subdist_id] dist = distance(sensor_pos, uc_pos) add_edge(graph, sensor_id, subdist_id, dist) # Berechnung der kürzesten Wege mit Dijkstra routing_result = {} for sensor_id in sensors: distances = dijkstra(graph, sensor_id) routing_result[sensor_id] = distances if args.console: print(json.dumps(routing_result, indent=2))