From 3a7b3aeecebdf89b732c5b9f9958fbcd05d382d5 Mon Sep 17 00:00:00 2001 From: lertlmaier Date: Mon, 12 May 2025 13:50:51 +0200 Subject: [PATCH] =?UTF-8?q?LineSweep=20Algorithmus=20angepasst,=20alten=20?= =?UTF-8?q?Stand=20=C3=BCberschrieben.=20Ausgaben=20in=20Kommandozeile=20z?= =?UTF-8?q?u=20Debug-Zwecken?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/linesweep_circle.py | 115 ++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/lib/linesweep_circle.py b/lib/linesweep_circle.py index df0ba55..efdd40d 100644 --- a/lib/linesweep_circle.py +++ b/lib/linesweep_circle.py @@ -1,75 +1,88 @@ +import json from shapely.geometry import LineString, Point from shapely.ops import nearest_points +# === Konfiguration === +tol = 200 +tol_step = 10 -"""Code läuft Racks nacheinander entlang. Über vorgegebene toleranz wird bounding Box erzeugt - und infrage kommende Punkte aufgezeichnet. Bei exaktem Schnittpunkt wird zu überprüfendes Rack - und Schnittpunkt mit Punkt in Verbindungen aufgenommen. Bei nicht exaktem Schnittpunkt wird - wachsender Kreis um Punkt gezeichnet bis Rack geschnitten wird. Dieser Schnittpunkt dann in - Verbindungen aufgenommen. -""" -racks = [ - ((0, 0), (5, 0)), # Horizontal - ((0, 0), (0, 5)), # Vertikal (schneidet exakt) - ((0.25, 2), (5, 2)), # Parallel mit 0.25 Abstand zur Vertikalen - ((0.25, 4), (4, 3)), # Diagonal - ((5.10, -0.25), (5.1, 3)) # Parallel sehr nah an erstem Rack -] +# === Lade JSON-Daten === +with open("C:/10-Develop/kabellaengen/work/easy_positions.json", "r") as f: + data = json.load(f) -tol = 0.5 -tol_step = 0.05 +racks_json = data["racks"] #Suchen nach Racks in gesamter Json-Übergabe -rack_lines = [LineString([start, end]) for start, end in racks] -rack_endpoints = [(i, pt) for i, rack in enumerate(racks) for pt in rack] +# === 1. Racks in Segmente zerlegen === +''' Hier werden Racks, die aus "echter" Polylinie bestehen (mehrere Nodes, z.B. Rack 2 in easy.dxf) in einzelne Segmente zerlegt (Node1 -> Node2, Node2 -> Node3)''' +rack_segments = [] +for rack_id, nodes in racks_json.items(): + # Sortiere Node_1, Node_2, ... + sorted_keys = sorted(nodes.keys(), key=lambda k: int(k.split("_")[1])) + coords = [tuple(nodes[k]) for k in sorted_keys] + + for i in range(len(coords) - 1): + p1, p2 = coords[i], coords[i+1] + line = LineString([p1, p2]) + rack_segments.append((rack_id, i, line)) + +# === 2. Alle Endpunkte sammeln === +''' Alle Endpunkte aller Racks als Point gespeichert, um shapely funktionen verwenden zu können''' +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))) + + +# === 3. Verbindungen suchen === verbindungen = [] -# Überprüfe jedes Rack -for i, rack_line in enumerate(rack_lines): - print(f"\n=== Prüfe Rack {i}: {rack_line}") +# === A: Echte Schnittpunkte zwischen Linien finden === +''' Alle Segmente mit allen überprüfen, um echte SP zu finden''' +for i, (rack_id1, idx1, line1) in enumerate(rack_segments): + print(f"\n=== Prüfe {rack_id1}_{idx1} auf echte Schnittpunkte") + for j, (rack_id2, idx2, line2) in enumerate(rack_segments): + if i >= j: + continue # keine Duplikate / sich selbst - for j, pt_coords in rack_endpoints: - if i == j: - continue # Eigenpunkte ignorieren + if line1.intersects(line2): + inter = line1.intersection(line2) + if inter.geom_type == "Point": + print(f"✅ Exakter Schnittpunkt {inter} zwischen {rack_id1}_{idx1} und {rack_id2}_{idx2}") + verbindungen.append((rack_id1, rack_id2, inter)) - pt = Point(pt_coords) - # Prüfe auf exakten Schnittpunkt - if rack_line.intersects(pt): - intersection = rack_line.intersection(pt) - print(f" ✅ Echter Schnittpunkt mit Endpunkt von Rack {j}: {intersection}") - verbindungen.append((i,j, intersection)) - continue #diesen Punkt überspringen +# === B: Näherungsweise Verbindung durch Toleranz-Kreise === +''' Entlanglaufen der Racks und Scan nach Endpunkten im Toleranzbereich''' +for rack_id, idx, line in rack_segments: + print(f"\n=== Prüfe {rack_id}_{idx1} auf Punkte im Toleranzbereich") + for other_rack_id, other_idx, pt in segment_endpoints: + if rack_id == other_rack_id: + continue # ignoriere eigene Endpunkte - #alle Endpunkte prüfen, die NICHT exakt auf der Linie liegen - for j, pt_coords in rack_endpoints: - if i == j: - continue # Eigenpunkte ignorieren + # Exakte Schnittpunkte ignorieren + if line.intersects(pt): + continue - pt = Point(pt_coords) - - # Prüfe nur, wenn der Punkt **nicht** genau auf der Linie liegt - if rack_line.intersects(pt): - continue # Exakte Schnittpunkte nicht erneut behandeln - - dist = rack_line.distance(pt) - - #überprüfen, ob der Punkt im Toleranzbereich ist + dist = line.distance(pt) if dist < tol: - print(f" 🔍 Punkt {pt} liegt {dist:.3f} von Linie {i} entfernt") + print(f"🔍 Punkt {pt} liegt {dist:.2f} von Linie {rack_id}_{idx} entfernt") radius = tol_step while radius <= tol: - circle = pt.buffer(radius) # Kreis wächst mit dem Toleranzradius - if circle.intersects(rack_line): # Wenn der Kreis die Linie schneidet - contact = circle.intersection(rack_line) + circle = pt.buffer(radius) + if circle.intersects(line): + contact = circle.intersection(line) if contact.geom_type == "Point": nearest = contact else: - nearest = nearest_points(pt, contact)[1] # Erster Kontaktpunkt von rack_line - - print(f" 🟡 Berührpunkt bei Radius {radius:.2f}: {nearest}") - verbindungen.append((i,j,nearest)) + nearest = nearest_points(pt, contact)[1] + print(f" 🟡 Kreisberührung bei {nearest} mit {rack_id}_{idx}") + verbindungen.append((rack_id, other_rack_id, nearest)) break radius += tol_step +# === Ausgabe-Verbindungen === +print("\n=== Gefundene Verbindungen ===") +for v in verbindungen: + print(v)