hub/venv/lib/python3.7/site-packages/trimesh/path/intersections.py

74 lines
2.2 KiB
Python
Raw Normal View History

import numpy as np
from .. import util
from ..constants import tol_path as tol
def line_line(origins,
directions,
plane_normal=None):
"""
Find the intersection between two lines.
Uses terminology from:
http://geomalgorithms.com/a05-_intersect-1.html
line 1: P(s) = p_0 + sU
line 2: Q(t) = q_0 + tV
Parameters
---------
origins: (2, d) float, points on lines (d in [2,3])
directions: (2, d) float, direction vectors
plane_normal: (3, ) float, if not passed computed from cross
Returns
---------
intersects: boolean, whether the lines intersect.
In 2D, false if the lines are parallel
In 3D, false if lines are not coplanar
intersection: if intersects: (d) length point of intersection
else: None
"""
# check so we can accept 2D or 3D points
origins, is_2D = util.stack_3D(origins, return_2D=True)
directions, is_2D = util.stack_3D(directions, return_2D=True)
# unitize direction vectors
directions /= util.row_norm(directions).reshape((-1, 1))
# exit if values are parallel
if np.sum(np.abs(np.diff(directions,
axis=0))) < tol.zero:
return False, None
# using notation from docstring
q_0, p_0 = origins
v, u = directions
w = p_0 - q_0
# recompute plane normal if not passed
if plane_normal is None:
# the normal of the plane given by the two direction vectors
plane_normal = np.cross(u, v)
plane_normal /= np.linalg.norm(plane_normal)
# vectors perpendicular to the two lines
v_perp = np.cross(v, plane_normal)
v_perp /= np.linalg.norm(v_perp)
# if the vector from origin to origin is on the plane given by
# the direction vector, the dot product with the plane normal
# should be within floating point error of zero
coplanar = abs(np.dot(plane_normal, w)) < tol.zero
if not coplanar:
return False, None
# value of parameter s where intersection occurs
s_I = (np.dot(-v_perp, w) /
np.dot(v_perp, u))
# plug back into the equation of the line to find the point
intersection = p_0 + s_I * u
return True, intersection[:(3 - is_2D)]