Skip to content
This repository was archived by the owner on Feb 3, 2023. It is now read-only.

Commit 49c3ecd

Browse files
authored
vectorize line intersection (#7)
* vectorize line intersection * fix lint * bump versiom
1 parent a295a58 commit 49c3ecd

File tree

3 files changed

+49
-5
lines changed

3 files changed

+49
-5
lines changed

blmath/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.2.1'
1+
__version__ = '1.2.2'

blmath/geometry/primitives/plane.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,22 @@ def _line_segment_xsection(self, a, b):
229229
return None
230230
return pt
231231

232+
def line_xsections(self, pts, rays):
233+
denoms = np.dot(rays, self.normal)
234+
denom_is_zero = denoms == 0
235+
denoms[denom_is_zero] = np.nan
236+
p = np.dot(self.reference_point - pts, self.normal) / denoms
237+
return np.vstack([p, p, p]).T * rays + pts, ~denom_is_zero
238+
239+
def line_segment_xsections(self, a, b):
240+
pts, pt_is_valid = self.line_xsections(a, b-a)
241+
pt_is_out_of_bounds = np.logical_or(np.any(np.logical_and(pts[pt_is_valid] > a[pt_is_valid], pts[pt_is_valid] > b[pt_is_valid]), axis=1),
242+
np.any(np.logical_and(pts[pt_is_valid] < a[pt_is_valid], pts[pt_is_valid] < b[pt_is_valid]), axis=1))
243+
pt_is_valid[pt_is_valid] = ~pt_is_out_of_bounds
244+
pts[~pt_is_valid] = np.nan
245+
return pts, pt_is_valid
246+
247+
232248
def mesh_xsection(self, m, neighborhood=None):
233249
'''
234250
Backwards compatible.
@@ -309,11 +325,13 @@ def get(self, u, v):
309325
return None
310326

311327
intersection_map = EdgeMap()
312-
for e in es:
328+
329+
pts, pt_is_valid = self.line_segment_xsections(m.v[es[:, 0]], m.v[es[:, 1]])
330+
valid_pts = pts[pt_is_valid]
331+
valid_es = es[pt_is_valid]
332+
for val, e in zip(valid_pts, valid_es):
313333
if not intersection_map.contains(e[0], e[1]):
314-
val = self._line_segment_xsection(m.v[e[0]], m.v[e[1]])
315-
if val is not None:
316-
intersection_map.add(e[0], e[1], val)
334+
intersection_map.add(e[0], e[1], val)
317335
verts = np.array(intersection_map.values)
318336

319337
class Graph(object):

blmath/geometry/primitives/test_plane.py

+26
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,19 @@ def test_line_plane_intersection(self):
245245
np.testing.assert_array_equal(plane.line_xsection(pt=[0., -1., 0.], ray=[0., 1., 0.]), [0., 0., 0.])
246246
np.testing.assert_array_equal(plane.line_xsection(pt=[0., -1., 0.], ray=[1., 1., 0.]), [1., 0., 0.])
247247

248+
def test_line_plane_intersections(self):
249+
# x-z plane
250+
normal = np.array([0., 1., 0.])
251+
sample = np.array([0., 0., 0.])
252+
253+
plane = Plane(sample, normal)
254+
pts = np.array([[0., -1., 0.], [0., 0., 0.], [0., -1., 0.], [0., -1., 0.]])
255+
rays = np.array([[1., 0., 0.], [1., 0., 0.], [0., 1., 0.], [1., 1., 0.]])
256+
expected = np.array([[np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan], [0., 0., 0.], [1., 0., 0.]])
257+
intersections, is_intserseting = plane.line_xsections(pts, rays)
258+
np.testing.assert_array_equal(intersections, expected)
259+
np.testing.assert_array_equal(is_intserseting, [False, False, True, True])
260+
248261
def test_line_segment_plane_intersection(self):
249262
# x-z plane
250263
normal = np.array([0., 1., 0.])
@@ -257,6 +270,19 @@ def test_line_segment_plane_intersection(self):
257270
np.testing.assert_array_equal(plane.line_segment_xsection([0., -1., 0.], [2., 1., 0.]), [1., 0., 0.])
258271
self.assertIsNone(plane.line_segment_xsection([0., 1., 0.], [0., 2., 0.])) # line intersecting, but not in segment
259272

273+
def test_line_segment_plane_intersections(self):
274+
# x-z plane
275+
normal = np.array([0., 1., 0.])
276+
sample = np.array([0., 0., 0.])
277+
278+
plane = Plane(sample, normal)
279+
a = np.array([[0., -1., 0.], [0., 0., 0.], [0., -1., 0.], [0., -1., 0.], [0., 1., 0.]])
280+
b = np.array([[1., -1., 0.], [1., 0., 0.], [0., 1., 0.], [2., 1., 0.], [0., 2., 0.]])
281+
expected = np.array([[np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan], [0., 0., 0.], [1., 0., 0.], [np.nan, np.nan, np.nan]])
282+
intersections, is_intserseting = plane.line_segment_xsections(a, b)
283+
np.testing.assert_array_equal(intersections, expected)
284+
np.testing.assert_array_equal(is_intserseting, [False, False, True, True, False])
285+
260286
def test_mesh_plane_intersection(self):
261287
# x-z plane
262288
normal = np.array([0., 1., 0.])

0 commit comments

Comments
 (0)