Alte Hilfsfunktionen gelöscht. Erste Funktionen aus linesweep_cicle implementiert

This commit is contained in:
2025-05-12 17:27:07 +02:00
parent c087e3ada9
commit 58e121bdcf
+54 -168
View File
@@ -5,118 +5,37 @@ import heapq
import math import math
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import networkx as nx import networkx as nx
from shapely.geometry import LineString, Point
from shapely.ops import nearest_points
# Hilfsfunktionen # Funktionen
def load_json(filepath):
with open(filepath, 'r', encoding='utf-8') as f:
return json.load(f)
def parse_pos(pos_str): def rack_segmentation(racks):
""" Konvertiert '(x, y)' oder '(x, y, z)' in ein Tuple """ ''' Racks werden zu LineString konvertiert. Racks bestehend aus Polylinine werden in einzelne Segmente zerlegt.'''
try: rack_segments = []
return tuple(map(float, pos_str.strip('[]').split(','))) for rack_id, nodes in racks.items():
except Exception: # Sortiere Node_1, Node_2, ...
raise ValueError(f"Ungültiges Positionsformat: {pos_str}") sorted_keys = sorted(nodes.keys(), key=lambda k: int(k.split("_")[1]))
coords = [tuple(nodes[k]) for k in sorted_keys]
def distance(p1, p2):
""" Euklidische Distanz in 2D """ for i in range(len(coords) - 1):
return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2) p1, p2 = coords[i], coords[i+1]
line = LineString([p1, p2])
def add_edge(graph, node1, node2, dist): rack_segments.append((rack_id, i, line))
""" Fügt eine ungerichtete Kante zwischen zwei Knoten hinzu, aber nur einmal """
if node1 not in graph:
graph[node1] = []
if node2 not in graph:
graph[node2] = []
# Nur hinzufügen, wenn Kante noch nicht existiert (ungerichtet)
if not any(n == node2 for n, _ in graph[node1]):
graph[node1].append((node2, dist))
if not any(n == node1 for n, _ in graph[node2]):
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: return(rack_segments)
current_distance, current_node = heapq.heappop(priority_queue)
if current_distance > distances[current_node]: def rack_endpoints(rack_segments)
continue ''' Endpunkte der Racks werden in Points konvertiert'''
segment_endpoints = []
for rack_id, idx, line in rack_segments:
for pt in [line.coords[0], line.coords[1]]:
segment_endpoints.append((rack_id, idx, Point(pt)))
for neighbor, weight in graph[current_node]: return(segment_endpoints)
distance = current_distance + weight
if distance < distances[neighbor]: def pin_rack_endpoints(rack_segments, segment_endpoints)
distances[neighbor] = distance '''Erstellung eines Dicts, welches unter dem Key "Rack_id - Index" die Endpunkte der Racks speichert. Endpunkte von Racks innerhalb der Toleranz werden an nahegelegenes Rack gepinnt.'''
heapq.heappush(priority_queue, (distance, neighbor))
return distances
def print_graph(graph):
printed = set()
for node, edges in graph.items():
for neighbor, dist in edges:
edge_id = tuple(sorted((node, neighbor)))
if edge_id not in printed:
printed.add(edge_id)
print(f"{edge_id[0]} --> {edge_id[1]} (Distanz: {dist})")
def visualize_graph(graph, racks):
G = nx.Graph()
pos = {}
for node, edges in graph.items():
pos[node] = node_to_coords(node, racks)
for neighbor, distance in edges:
if not G.has_edge(node, neighbor): # Doppelte Kanten vermeiden
G.add_edge(node, neighbor, weight=round(distance, 1))
plt.figure(figsize=(10, 10))
nx.draw(
G, pos,
with_labels=True,
node_size=100,
font_size=8,
node_color='skyblue',
edge_color='gray'
)
edge_labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=6)
plt.title("Rack-Graph (aus racks.json)")
plt.axis("equal")
plt.tight_layout()
plt.show()
def node_to_coords(node_name, racks):
"""Extrahiert die Koordinaten aus dem Knotennamen wie 'Rack_1_Node_2'"""
parts = node_name.split("_")
rack = f"{parts[0]}_{parts[1]}"
node = f"{parts[2]}_{parts[3]}"
coords = racks[rack][node]
return tuple(coords)
@@ -142,73 +61,40 @@ if __name__ == "__main__":
subdists = data["distributors"] subdists = data["distributors"]
racks = data["racks"] racks = data["racks"]
# Graph erstellen
graph = {} # 1. Alle Kreuzungspunkte der Racks ermitteln
''' Funktion linesweep_circle wird aufgerufen.
for rack_id, rack in racks.items(): Eingabe für Funktion: Nummerierte Racks aus getpositions.py. Reine Liste aus Koordinaten [((Anfang), (Ende)), ((Anfang), (Ende)), ... ] wird in Funktion erstellt
nodes = list(rack.values()) # Liste aller Knoten im Rack Racks werden abgelaufen und tatsächliche Schnittpunkte sowie Nahezu-Schnitte erfasst.
Ausgabe von Linesweep Circle: Liste von Endpunkten der Racks aus .dxf & Liste von SP von Rack_a mit Rack_b
for i in range(len(nodes) - 1):
segment_start = tuple(nodes[i])
segment_end = tuple(nodes[i + 1])
dist = distance(segment_start, segment_end)
# Erstelle Kanten zwischen den benachbarten Knoten
add_edge(graph, f"{rack_id}_Node_{i+1}", f"{rack_id}_Node_{i+2}", dist)
# Graph in Kommandozeile beschreiben und mittels matplotlib ausgeben
print("\nGraph basierend auf den Racks (ungerichtet, eindeutige Kanten):")
print_graph(graph)
visualize_graph(graph, racks)
'''
"""# 1. Vom Sensor zum Rack laufen und Knoten einfügen # 2. Graph aus Racks erstellen
for sensor_id, sensor_info in sensors.items(): ''' Zunächst leeren Graph erstellen.
sensor_pos = tuple(sensor_info['pos']) Endpunkte der Racks wie in .dxf als Knoten hinzufügen. Kanten zwischen den Knoten ebenso hinzufügen.
for rack in racks: Mittels ausgabe von linesweep_cirle: weitere Knoten auf Kanten hinzufügen und graph vollständig verknüpfen
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))
rack_id = f"rack_{rack}"
# Sensor zum Rack Knoten verbinden
add_edge(graph, sensor_id, rack_id, dist)
# 2. Vom Unterverteiler (UV) zum Rack laufen und Knoten einfügen Frage: Problematisch, wenn Knoten sehr nahe beieinander liegen also teoretischen "Doppelt" sind? -> lieber Endpunkte von Racks, die über linesweep_circle gefunden werden überschreiben?
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 UV zur Kabeltrasse
px, py = project_point_on_segment(uc_pos, segment_start, segment_end)
dist = distance(uc_pos, (px, py))
rack_id = f"rack_{rack}"
# UV zum Rack Knoten verbinden
add_edge(graph, uc_id, rack_id, dist)
# 3. Vom Sensor Knoten zum zugehörigen Unterverteiler Knoten entlang der Racks Zusätzlich: über shapely und distance funktion sämtliche Distanzen bestimmen und Graph gewichten
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]
# Berechne Distanz von Sensor zum Unterverteiler (über Trassen)
dist = distance(sensor_pos, uc_pos)
add_edge(graph, sensor_id, subdist_id, dist)
# 4. Berechnung der kürzesten Wege mit Dijkstra # 3. Sensoren mit nächstgelegenen Racks verknüpfen
routing_result = {} ''' Für jeden Sensor: Sensor pos aus json zu Graph hinzufügen
for sensor_id in sensors: Für jeden Sensor: shapely.distance aufrufen und distance zu allen Racks bzw. Edges ermitteln. (if distance(a) > distance(b) -> Circle_methode um Sensor und Schnittpunkt zu Rack_b ermitteln)
distances = dijkstra(graph, sensor_id) SP von Sensor mit Rack als Node hinzufügen und Connection zwischen Sensor, Node, Edge herstellen
routing_result[sensor_id] = distances '''
if args.console: # 4. Unterverteiler mit nächstegelegenen Racks verknüpfen
print(json.dumps(routing_result, indent=2))""" ''' siehe 3.
'''
# 5. Bestimmung des küzesten Wegs
''' über Graphen-Toolbox z.B. nx wird für jeden Knoten zu dessen zugehörigen Unterverteilung der kürzeste Weg gefunden.
Schreiben der Ergebnisse in eine seperate kabel.json z.B.
'''