Erweiterung des Skripts mit Linienverlängerung. Code allerdings unscoen, if-edundanzen, etc. Kein zufriedenstellendes Ergebnis.
This commit is contained in:
+109
-51
@@ -2,7 +2,7 @@ from bisect import bisect_left, bisect_right,insort
|
||||
import unittest
|
||||
from collections import namedtuple
|
||||
import math
|
||||
from shapely.geometry import LineString
|
||||
from shapely.geometry import LineString, Point
|
||||
from itertools import combinations
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ def find_intersections(horizontal_segments, vertical_segments, epsilon=0.0):
|
||||
|
||||
return intersections
|
||||
|
||||
|
||||
def find_all_intersections(segments):
|
||||
# segments: List of ((x1, y1), (x2, y2))
|
||||
lines = [LineString([p1, p2]) for p1, p2 in segments]
|
||||
@@ -48,7 +47,7 @@ def find_all_intersections(segments):
|
||||
|
||||
return list(intersections)
|
||||
|
||||
def find_touch_cut_close(segments):
|
||||
def find_touch_cut_close(segments, tol):
|
||||
# segments: Liste aus ((x1, y1), (x2,y2)) mit 1=Anfang, 2=Ende
|
||||
verbindungen = []
|
||||
for i,(s1_start, s1_end) in enumerate(segments):
|
||||
@@ -58,11 +57,67 @@ def find_touch_cut_close(segments):
|
||||
continue
|
||||
line2 = LineString([s2_start,s2_end])
|
||||
|
||||
if line1.distance(line2) < 0.5: #Toleranz 0,5 Hardcode
|
||||
if line1.distance(line2) < tol:
|
||||
verbindungen.append((i,j,line1.intersection(line2)))
|
||||
|
||||
return verbindungen
|
||||
|
||||
def find_touch_cut_close_ext(segments,tol):
|
||||
# segments: Liste aus ((x1, y1), (x2,y2)) mit 1=Anfang, 2=Ende
|
||||
verbindungen = []
|
||||
for i,(s1_start, s1_end) in enumerate(segments):
|
||||
line1 = LineString([s1_start, s1_end])
|
||||
for j, ([s2_start, s2_end]) in enumerate(segments):
|
||||
if i >= j:
|
||||
continue
|
||||
line2 = LineString([s2_start,s2_end])
|
||||
|
||||
#Prüfe Abstand
|
||||
if line1.distance(line2) < tol:
|
||||
schnitt = line1.intersection(line2) #Existiert tatsächlicher SP?
|
||||
|
||||
if schnitt.is_empty:
|
||||
#Prüfen, welcher Endpunkt von Segment näer an line2
|
||||
dist_start = Point(s2_start).distance(line1) #Abstand Statpunkt v. Linie1 zu Linie2
|
||||
dist_end = Point(s2_end).distance(line1) #Abstand Endpunkt v. Linie 1 zu Linie2
|
||||
|
||||
if dist_start > dist_end:
|
||||
line2_ext = extend_from_point(s2_start, s2_end)
|
||||
else:
|
||||
line2_ext =extend_from_point(s2_end, s2_start)
|
||||
|
||||
if dist_start < dist_end:
|
||||
line1_ext = extend_from_point(s1_start, s1_end)
|
||||
else:
|
||||
line1_ext = extend_from_point(s1_end, s1_start)
|
||||
|
||||
schnitt_ext1 = line2_ext.intersection(line1)
|
||||
schnitt_ext2 = line1_ext.intersection(line2)
|
||||
|
||||
if not schnitt_ext1.is_empty:
|
||||
verbindungen.append((i,j,schnitt_ext1))
|
||||
if not schnitt_ext2.is_empty:
|
||||
verbindungen.append((i,j,schnitt_ext2))
|
||||
else:
|
||||
verbindungen.append((i,j,schnitt))
|
||||
|
||||
return verbindungen
|
||||
|
||||
def extend_from_point(p1, p2, max_extension=0.3):
|
||||
"""Verlängert eine Linie von p1 in Richtung p2 um `max_extension`."""
|
||||
dx = p2[0] - p1[0]
|
||||
dy = p2[1] - p1[1]
|
||||
length = math.hypot(dx, dy)
|
||||
|
||||
if length == 0:
|
||||
return LineString([p1, p1]) # Kein Verlängern möglich
|
||||
|
||||
# Normierter Richtungsvektor * (ursprüngliche Länge + Verlängerung)
|
||||
scale = (length + max_extension) / length
|
||||
new_end = (p1[0] + dx * scale, p1[1] + dy * scale)
|
||||
|
||||
return LineString([p1, new_end])
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -109,61 +164,48 @@ def find_touch_cut_close(segments):
|
||||
# self.assertEqual( [(0,0),(0,0)], b)
|
||||
|
||||
# class TestScanLineAllgMethods(unittest.TestCase):
|
||||
# def test_sweep(self):
|
||||
def test_sweep(self):
|
||||
|
||||
# seks = [((1, 2), (5, 2)), ((3, 4), (7, 4)), ((4, 1), (4, 5)), ((6, 3), (6, 6))]
|
||||
seks = [((1, 2), (5, 2)), ((3, 4), (7, 4)), ((4, 1), (4, 5)), ((6, 3), (6, 6))]
|
||||
|
||||
# a = find_all_intersections(seks)
|
||||
# self.assertEqual( [(4,2),(4,4),(6,4)], a)
|
||||
a = find_all_intersections(seks)
|
||||
self.assertEqual( [(4,2),(4,4),(6,4)], a)
|
||||
|
||||
# def test_tol_hor(self):
|
||||
# """Testet die Anzahl der Schnittpunkte bei gegebener Toleranz
|
||||
# schnittpunkt zwischen gegebener horizontalen und zu kurzen vertikalen
|
||||
# """
|
||||
def test_tol_hor(self):
|
||||
"""Testet die Anzahl der Schnittpunkte bei gegebener Toleranz
|
||||
schnittpunkt zwischen gegebener horizontalen und zu kurzen vertikalen
|
||||
"""
|
||||
|
||||
# seks = [((0, 0), (10, 0)), ((4, 0.6), (4, 5)), ((6, 0.2), (6, 6)),((8,-0.2),(8, 4))]
|
||||
seks = [((0, 0), (10, 0)), ((4, 0.6), (4, 5)), ((6, 0.2), (6, 6)),((8,-0.2),(8, 4))]
|
||||
|
||||
# b = find_all_intersections(seks, 0.5)
|
||||
# self.assertEqual( len(b), 2)
|
||||
# self.assertEqual( [(6,0),(8,0)], b)
|
||||
b = find_all_intersections(seks, 0.5)
|
||||
self.assertEqual( len(b), 2)
|
||||
self.assertEqual( [(6,0),(8,0)], b)
|
||||
|
||||
# def test_tol_ver(self):
|
||||
# """Testet die Anzahl der Schnittpunkte bei gegebener Toleranz
|
||||
# schnittpunkt zwischen gegebener vertikalen und zu kurzen horizontalen
|
||||
# """
|
||||
def test_tol_ver(self):
|
||||
"""Testet die Anzahl der Schnittpunkte bei gegebener Toleranz
|
||||
schnittpunkt zwischen gegebener vertikalen und zu kurzen horizontalen
|
||||
"""
|
||||
|
||||
# seks = [((0.2, 0), (9.8, 0)), ((0, 0), (0, 10)), ((10, 0), (10, 10))]
|
||||
seks = [((0.2, 0), (9.8, 0)), ((0, 0), (0, 10)), ((10, 0), (10, 10))]
|
||||
|
||||
# b = find_all_intersections(seks, 0.5)
|
||||
# self.assertEqual( len(b), 2)
|
||||
# self.assertEqual( [(6,0),(8,0)], b)
|
||||
b = find_all_intersections(seks, 0.5)
|
||||
self.assertEqual( len(b), 2)
|
||||
self.assertEqual( [(6,0),(8,0)], b)
|
||||
|
||||
# def test_tol_diag(self):
|
||||
# """Testet die Anzahl der Schnittpunkte bei gegebener Toleranz
|
||||
# Horizontale mit Diagonalen
|
||||
# """
|
||||
def test_tol_diag(self):
|
||||
"""Testet die Anzahl der Schnittpunkte bei gegebener Toleranz
|
||||
Horizontale mit Diagonalen
|
||||
"""
|
||||
|
||||
# seks = [((0, 0), (5, 0)), ((0, -5), (10, 5))]
|
||||
seks = [((0, 0), (5, 0)), ((0, -5), (10, 5))]
|
||||
|
||||
# b = find_all_intersections(seks, 0.5)
|
||||
# self.assertEqual( len(b), 1)
|
||||
# self.assertEqual( [(6,0),(8,0)], b)
|
||||
b = find_all_intersections(seks, 0.5)
|
||||
self.assertEqual( len(b), 1)
|
||||
self.assertEqual( [(6,0),(8,0)], b)
|
||||
|
||||
# def test_shapely(self):
|
||||
# # Beispiel
|
||||
# segments = [
|
||||
# ((0, 0), (4, 4)), # Diagonal /
|
||||
# ((0, 4), (4, 0)), # Diagonal \
|
||||
# ((2, -1), (2, 5)), # Vertikal
|
||||
# ((-1, 2), (5, 2)) # Horizontal
|
||||
# ]
|
||||
|
||||
# result = find_all_intersections(segments)
|
||||
# print(result)
|
||||
|
||||
class TestShapely(unittest.TestCase):
|
||||
def test_shapely_2_Stern(self):
|
||||
# Beispiel !Stern mit gemeinsamen Schnittpunkt in (2,2)
|
||||
def test_shapely(self):
|
||||
# Beispiel
|
||||
segments = [
|
||||
((0, 0), (4, 4)), # Diagonal /
|
||||
((0, 4), (4, 0)), # Diagonal \
|
||||
@@ -171,10 +213,12 @@ class TestShapely(unittest.TestCase):
|
||||
((-1, 2), (5, 2)) # Horizontal
|
||||
]
|
||||
|
||||
result = find_touch_cut_close(segments)
|
||||
self.assertEqual(len(result),1)
|
||||
result = find_all_intersections(segments)
|
||||
print(result)
|
||||
|
||||
def test_shapely_2_Rand(self):
|
||||
|
||||
class TestShapely(unittest.TestCase):
|
||||
def test_shapely(self):
|
||||
#Test mit Strecken horizontal, vertikal, diagonal, Schnittpunkt u. Annaeherung
|
||||
segments = [
|
||||
((0, 0), (5, 0)), # Horizontale
|
||||
@@ -183,8 +227,22 @@ class TestShapely(unittest.TestCase):
|
||||
((0.25, 4), (4, 3)) # Diagonale \ mit 0.25 Abstand zu vertikaler und 1 zu horizontaler
|
||||
]
|
||||
|
||||
result = find_touch_cut_close(segments)
|
||||
result = find_touch_cut_close(segments, 0.5)
|
||||
self.assertEqual(len(result),3)
|
||||
|
||||
def test_shapely_ext(self):
|
||||
#Test mit Strecken horizontal, vertikal, diagonal, Schnittpunkt u. Annaeherung
|
||||
segments = [
|
||||
((0, 0), (5, 0)), # Horizontale
|
||||
((0, 0), (0, 5)), # Vertikale mit Schnitt Horizontal in 0,0
|
||||
((0.25, 2), (5, 2)), # Horizontale mit 0.25 Abstand zu vertikaler
|
||||
((0.25, 4), (4, 3)), # Diagonale \ mit 0.25 Abstand zu vertikaler und 1 zu horizontaler
|
||||
((5.10, -1), (5.1, 3)) # Vertikale mit 0,25 Abstand zu erster u zweiter Horizontalen
|
||||
]
|
||||
|
||||
result = find_touch_cut_close_ext(segments, 0.5)
|
||||
self.assertEqual(len(result),3)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
from shapely.geometry import LineString, Point
|
||||
from shapely.ops import nearest_points
|
||||
|
||||
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
|
||||
]
|
||||
|
||||
tol = 0.5
|
||||
tol_step = 0.05
|
||||
|
||||
rack_lines = [LineString([start, end]) for start, end in racks]
|
||||
rack_endpoints = [(i, pt) for i, rack in enumerate(racks) for pt in rack]
|
||||
|
||||
verbindungen = []
|
||||
|
||||
# Überprüfe jedes Rack
|
||||
for i, rack_line in enumerate(rack_lines):
|
||||
print(f"\n=== Prüfe Rack {i}: {rack_line}")
|
||||
|
||||
for j, pt_coords in rack_endpoints:
|
||||
if i == j:
|
||||
continue # Eigenpunkte ignorieren
|
||||
|
||||
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
|
||||
|
||||
#alle Endpunkte prüfen, die NICHT exakt auf der Linie liegen
|
||||
for j, pt_coords in rack_endpoints:
|
||||
if i == j:
|
||||
continue # Eigenpunkte ignorieren
|
||||
|
||||
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
|
||||
if dist < tol:
|
||||
print(f" 🔍 Punkt {pt} liegt {dist:.3f} von Linie {i} 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)
|
||||
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))
|
||||
break
|
||||
radius += tol_step
|
||||
|
||||
Reference in New Issue
Block a user