191 lines
6.5 KiB
Python
191 lines
6.5 KiB
Python
from bisect import bisect_left, bisect_right,insort
|
|
import unittest
|
|
from collections import namedtuple
|
|
import math
|
|
from shapely.geometry import LineString
|
|
from itertools import combinations
|
|
|
|
|
|
def find_intersections(horizontal_segments, vertical_segments, epsilon=0.0):
|
|
horizontal_segments.sort(key=lambda h: h[0][1]) # sortiere nach y
|
|
|
|
horizontal_ys = []
|
|
horizontal_x_ranges = []
|
|
for (x1, y), (x2, _) in horizontal_segments:
|
|
if x1 > x2:
|
|
x1, x2 = x2, x1
|
|
horizontal_ys.append(y)
|
|
horizontal_x_ranges.append((x1, x2))
|
|
|
|
intersections = []
|
|
|
|
for (x, y1), (_, y2) in vertical_segments:
|
|
if y1 > y2:
|
|
y1, y2 = y2, y1
|
|
|
|
for idx, y in enumerate(horizontal_ys):
|
|
if y1 - epsilon <= y <= y2 + epsilon:
|
|
x_start, x_end = horizontal_x_ranges[idx]
|
|
if x_start - epsilon <= x <= x_end + epsilon:
|
|
intersections.append((x, y))
|
|
|
|
return intersections
|
|
|
|
|
|
def find_all_intersections(segments):
|
|
# segments: List of ((x1, y1), (x2, y2))
|
|
lines = [LineString([p1, p2]) for p1, p2 in segments]
|
|
intersections = set()
|
|
|
|
for l1, l2 in combinations(lines, 2):
|
|
if l1.intersects(l2):
|
|
point = l1.intersection(l2)
|
|
if point.geom_type == "Point":
|
|
intersections.add((point.x, point.y))
|
|
elif point.geom_type == "MultiPoint":
|
|
for p in point.geoms:
|
|
intersections.add((p.x, p.y))
|
|
|
|
return list(intersections)
|
|
|
|
def find_touch_cut_close(segments):
|
|
# 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])
|
|
|
|
if line1.distance(line2) < 0.5: #Toleranz 0,5 Hardcode
|
|
verbindungen.append((i,j,line1.intersection(line2)))
|
|
|
|
return verbindungen
|
|
|
|
|
|
|
|
|
|
# class TestSweepMethods(unittest.TestCase):
|
|
|
|
# def test_sweep(self):
|
|
# horizontal = [((1, 2), (5, 2)), ((3, 4), (7, 4))]
|
|
# vertical = [((4, 1), (4, 5)), ((6, 3), (6, 6))]
|
|
|
|
# a = find_intersections(horizontal, vertical)
|
|
# 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
|
|
# """
|
|
# horizontal = [((0, 0), (10, 0))]
|
|
# vertical = [((4, 0.6), (4, 5)), ((6, 0.2), (6, 6)),((8,-0.2),(8, 4))]
|
|
|
|
# b = find_intersections(horizontal, vertical, 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
|
|
# """
|
|
# horizontal = [((0.2, 0), (9.8, 0))]
|
|
# vertical = [((0, 0), (0, 10)), ((10, 0), (10, 10))]
|
|
|
|
# b = find_intersections(horizontal, vertical, 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
|
|
# """
|
|
# horizontal = [((0, 0), (5, 0))]
|
|
# diagonal = [((0, -5), (10, 5))]
|
|
|
|
# b = find_intersections(horizontal, diagonal, 0.5)
|
|
# self.assertEqual( len(b), 1)
|
|
# self.assertEqual( [(0,0),(0,0)], b)
|
|
|
|
# class TestScanLineAllgMethods(unittest.TestCase):
|
|
# def test_sweep(self):
|
|
|
|
# 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)
|
|
|
|
# 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))]
|
|
|
|
# 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
|
|
# """
|
|
|
|
# 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)
|
|
|
|
# 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))]
|
|
|
|
# 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)
|
|
segments = [
|
|
((0, 0), (4, 4)), # Diagonal /
|
|
((0, 4), (4, 0)), # Diagonal \
|
|
((2, -1), (2, 5)), # Vertikal
|
|
((-1, 2), (5, 2)) # Horizontal
|
|
]
|
|
|
|
result = find_touch_cut_close(segments)
|
|
self.assertEqual(len(result),1)
|
|
|
|
def test_shapely_2_Rand(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
|
|
]
|
|
|
|
result = find_touch_cut_close(segments)
|
|
self.assertEqual(len(result),3)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main() |