forked from twut/GEOBIM_Tool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lineintersect.py
127 lines (110 loc) · 3.74 KB
/
lineintersect.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import numpy as np
def doBoundingBoxesIntersect(a, b, c, d):
'''
Check if bounding boxes do intersect. If one bounding box touches
the other, they do intersect.
First segment is of points a and b, second of c and d.
'''
ll1_x = min(a[0],b[0]); ll2_x = min(c[0],d[0])
ll1_y = min(a[1],b[1]); ll2_y = min(c[1],d[1])
ur1_x = max(a[0],b[0]); ur2_x = max(c[0],d[0])
ur1_y = max(a[1],b[1]); ur2_y = max(c[1],d[1])
return ll1_x <= ur2_x and \
ur1_x >= ll2_x and \
ll1_y <= ur2_y and \
ur1_y >= ll2_y
def isPointOnLine(a,b,c):
'''
Check if a point a is on a line b-c.
'''
# move to origin
aTmp = (0,0)
bTmp = (b[0] - a[0], b[1] - a[1])
cTmp = (c[0] - a[0], c[1] - a[1])
r = np.cross(bTmp, cTmp)
return np.abs(r) < 0.0000000001
def isPointRightOfLine(a,b,c):
'''
Check if a point (c) is right of a line (a-b).
If (c) is on the line, it is not right it.
'''
# move to origin
aTmp = (0,0)
bTmp = (b[0] - a[0], b[1] - a[1])
cTmp = (c[0] - a[0], c[1] - a[1])
return np.cross(bTmp, cTmp) < 0
def lineSegmentTouchesOrCrossesLine(a,b,c,d):
'''
Check if line segment (a-b) touches or crosses
line segment (c-d).
'''
return isPointOnLine(a,b,c) or \
isPointOnLine(a,b,d) or \
(isPointRightOfLine(a,b,c) ^
isPointRightOfLine(a,b,d))
def doLinesIntersect(a,b,c,d):
'''
Check if line segments (a-b) and (c-d) intersect.
'''
#print(type(a), a,b,c,d)
return doBoundingBoxesIntersect(a,b,c,d) and \
lineSegmentTouchesOrCrossesLine(a,b,c,d) and \
lineSegmentTouchesOrCrossesLine(c,d,a,b)
##############################
## Tests
##############################
def test_doBoundingBoxesIntersect():
A=(1,1); B=(2,2); C=(3,1); D=(4,2)
assert doBoundingBoxesIntersect(A,B,C,D) == False
A=(1,2); B=(3,4); C=(2,1); D=(4,3)
assert doBoundingBoxesIntersect(A,B,C,D) == True
def test_isPointOnLine():
A=(1,1); B=(3,3); C=(2,2)
assert isPointOnLine(A,B,C) == True
A=(1,1); B=(3,3); C=(3,2)
assert isPointOnLine(A,B,C) == False
def test_isPointRightOfLine():
A=(1,1); B=(3,3); C=(2,2)
assert isPointRightOfLine(A,B,C) == False
A=(1,1); B=(3,3); C=(3,2)
assert isPointRightOfLine(A,B,C) == True
A=(1,1); B=(3,3); C=(1,2)
assert isPointRightOfLine(A,B,C) == False
# a lot of testcases to be tested with the final function
def tcase(name):
if name == 'F1':
return (0,0), (7,7), (3,4), (4,5), False
elif name == 'F2':
return (-4,4), (-2,1), (-2,3), (0,0), False
elif name == 'F3':
return (0,0), (0,1), (2,2), (2,3), False
elif name == 'F4':
return (0,0), (0,1), (2,2), (3,2), False
elif name == 'F5':
return (-1,-1), (2,2), (3,3), (5,5), False
elif name == 'F6':
return (0,0), (1,1), (2,0), (0.5,2), False
elif name == 'F7':
return (1,1), (4,1), (2,2), (3,2), False
elif name == 'F8':
return (0,5), (6,0), (2,1), (2,2), False
elif name == 'T1':
return (0,-2), (0,2), (-2,0), (2,0), True
elif name == 'T2':
return (5,5), (0,0), (1,1), (8,2), True
elif name == 'T3':
return (-1,0), (0,0), (-1,-1), (-1,1), True
elif name == 'T4':
return (0,2), (2,2), (2,0), (2,4), True
elif name == 'T5':
return (0,0), (5,5), (1,1), (3,3), True
elif name == 'T6':
return (0,0), (3,3), (0,0), (3,3), True
cases = ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8',
'T1', 'T2', 'T3', 'T4', 'T5', 'T6']
def check_intersection(name):
A,B,C,D, result = tcase(name)
assert doLinesIntersect(A,B,C,D) == result
def test_doLinesIntersect():
for case in cases:
yield check_intersection, case