Skip to content

Commit aae7307

Browse files
committed
Fixes & tests point-line intersection methods
1 parent 8266f63 commit aae7307

File tree

2 files changed

+61
-15
lines changed

2 files changed

+61
-15
lines changed

src/osut/osut.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3031,7 +3031,7 @@ def segments(pts=None) -> openstudio.Point3dVectorVector:
30313031
pts = uniques(pts)
30323032
if len(pts) < 2: return vv
30333033

3034-
for i1, pt in enumerate(pts):
3034+
for i1, p1 in enumerate(pts):
30353035
i2 = i1 + 1
30363036
if i2 == len(pts): i2 = 0
30373037
p2 = pts[i2]
@@ -3185,7 +3185,7 @@ def isPointAlongSegments(p0=None, sgs=[]) -> bool:
31853185
cl2 = openstudio.Point3dVectorVector
31863186

31873187
if not isinstance(sgs, cl2):
3188-
sgs = getSegments(sgs)
3188+
sgs = segments(sgs)
31893189
if not sgs:
31903190
return oslg.empty("segments", mth, CN.DBG, False)
31913191
if not isinstance(p0, cl1):
@@ -3211,8 +3211,8 @@ def lineIntersection(s1=[], s2=[]):
32113211
None: If no intersection, or invalid input (see logs).
32123212
32133213
"""
3214-
s1 = segments(s1)
3215-
s2 = segments(s2)
3214+
s1 = segments(s1)
3215+
s2 = segments(s2)
32163216
if not s1: return None
32173217
if not s2: return None
32183218

@@ -3237,12 +3237,12 @@ def lineIntersection(s1=[], s2=[]):
32373237
if areSame(a2, b2): return a2
32383238

32393239
# Segment endpoint along opposite segment?
3240-
if isPointAlongSegments(a1, s2): return a1
3241-
if isPointAlongSegments(a2, s2): return a2
3242-
if isPointAlongSegments(b1, s1): return b1
3243-
if isPointAlongSegments(b2, s1): return b2
3240+
if isPointAlongSegment(a1, s2): return a1
3241+
if isPointAlongSegment(a2, s2): return a2
3242+
if isPointAlongSegment(b1, s1): return b1
3243+
if isPointAlongSegment(b2, s1): return b2
32443244

3245-
# Line segments as vectors. Skip if colinear.
3245+
# Line segments as vectors. Skip if collinear or parallel.
32463246
a = a2 - a1
32473247
b = b2 - b1
32483248
xab = a.cross(b)
@@ -3263,6 +3263,14 @@ def lineIntersection(s1=[], s2=[]):
32633263
xa1b1 = a.cross(a1b1)
32643264
xa1b2 = a.cross(a1b2)
32653265

3266+
if xa1b1.length() < CN.TOL2:
3267+
if isPointAlongSegment(a1, [a2, b1]): return None
3268+
if isPointAlongSegment(a2, [a1, b1]): return None
3269+
3270+
if xa1b2.length() < CN.TOL2:
3271+
if isPointAlongSegment(a1, [a2, b2]): return None
3272+
if isPointAlongSegment(a2, [a1, b2]): return None
3273+
32663274
# Both segment endpoints can't be 'behind' point.
32673275
if a.dot(a1b1) < 0 and a.dot(a1b2) < 0: return None
32683276

@@ -3281,15 +3289,16 @@ def lineIntersection(s1=[], s2=[]):
32813289
n = a.cross(xc1a1)
32823290
dot = b.dot(n)
32833291
if dot < 0: n = n.reverseVector()
3292+
if abs(b.dot(n)) < CN.TOL: return None
32843293
f = c1a1.dot(n) / b.dot(n)
32853294
p0 = c1 + scalar(b, f)
32863295

32873296
# Intersection can't be 'behind' point.
32883297
if a.dot(p0 - a1) < 0: return None
32893298

32903299
# Ensure intersection is sandwiched between endpoints.
3291-
if not isPointAlongSegments(p0, s2): return None
3292-
if not isPointAlongSegments(p0, s1): return None
3300+
if not isPointAlongSegment(p0, s2): return None
3301+
if not isPointAlongSegment(p0, s1): return None
32933302

32943303
return p0
32953304

tests/test_osut.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,9 +2451,6 @@ def test25_segments_triads_orientation(self):
24512451
self.assertEqual(o.level(), DBG)
24522452
self.assertEqual(o.status(), 0)
24532453

2454-
# --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- #
2455-
# Basic OpenStudio intersection methods.
2456-
24572454
# Enclosed polygon.
24582455
p0 = openstudio.Point3d(-5, -5, -5)
24592456
p1 = openstudio.Point3d( 5, 5, -5)
@@ -2510,9 +2507,49 @@ def test25_segments_triads_orientation(self):
25102507
self.assertTrue(o.is_error())
25112508
self.assertEqual(len(o.logs()), 1)
25122509
self.assertEqual(o.logs()[0]["message"], m2)
2513-
25142510
self.assertTrue(o.clean(), DBG)
25152511

2512+
# CASE a1: 2x end-to-end line segments (returns matching endpoints).
2513+
self.assertTrue(osut.doesLineIntersect([p0, p1], [p1, p2]))
2514+
pt = osut.lineIntersection([p0, p1], [p1, p2])
2515+
self.assertTrue(osut.areSame(pt, p1))
2516+
#
2517+
# # CASE a2: as a1, sequence of line segment endpoints doesn't matter.
2518+
self.assertTrue(osut.doesLineIntersect([p1, p0], [p1, p2]))
2519+
pt = osut.lineIntersection([p1, p0], [p1, p2])
2520+
self.assertTrue(osut.areSame(pt, p1))
2521+
#
2522+
# # CASE b1: 2x right-angle line segments, with 1x matching at corner.
2523+
self.assertTrue(osut.doesLineIntersect([p1, p2], [p1, p3]))
2524+
pt = osut.lineIntersection([p1, p2], [p2, p3])
2525+
self.assertTrue(osut.areSame(pt, p2))
2526+
#
2527+
# # CASE b2: as b1, sequence of segments doesn't matter.
2528+
self.assertTrue(osut.doesLineIntersect([p2, p3], [p1, p2]))
2529+
pt = osut.lineIntersection([p2, p3], [p1, p2])
2530+
self.assertTrue(osut.areSame(pt, p2))
2531+
2532+
# CASE c: 2x right-angle line segments, yet disconnected.
2533+
self.assertFalse(osut.doesLineIntersect([p0, p1], [p2, p3]))
2534+
pt = osut.lineIntersection([p0, p1], [p2, p3])
2535+
self.assertFalse(pt)
2536+
2537+
# CASE d: 2x connected line segments, acute angle.
2538+
self.assertTrue(osut.doesLineIntersect([p0, p2], [p3, p0]))
2539+
pt = osut.lineIntersection([p0, p2], [p3, p0])
2540+
self.assertTrue(osut.areSame(pt, p0))
2541+
#
2542+
# # CASE e1: 2x disconnected line segments, right angle.
2543+
self.assertTrue(osut.doesLineIntersect([p0, p2], [p4, p6]))
2544+
pt = osut.lineIntersection([p0, p2], [p4, p6])
2545+
self.assertTrue(osut.areSame(pt, p5))
2546+
#
2547+
# # CASE e2: as e1, sequence of line segment endpoints doesn't matter.
2548+
self.assertTrue(osut.doesLineIntersect([p0, p2], [p6, p4]))
2549+
pt = osut.lineIntersection([p0, p2], [p6, p4])
2550+
self.assertTrue(osut.areSame(pt, p5))
2551+
2552+
25162553
def test26_ulc_blc(self):
25172554
o = osut.oslg
25182555
self.assertEqual(o.status(), 0)

0 commit comments

Comments
 (0)