Source code for xiuminglib.geometry.tri

import numpy as np


[docs]def barycentric(pts, tvs): r"""Computes barycentric coordinates of 3D point(s) w.r.t. a triangle. Args: pts (array_like): 3-array for one point; N-by-3 array for multiple points. tvs (array_like): 3-by-3 array with rows being the triangle's vertices. Returns: numpy.ndarray: Barycentric coordinates of the same shape as ``pts``. If any array element :math:`\notin [0, 1]`, the input point doesn't fall on the triangle. """ pts = np.array(pts) tvs = np.array(tvs) input_shape = pts.shape if pts.ndim == 1: pts = pts.reshape((1, -1)) vec0 = tvs[1] - tvs[0] vec1 = tvs[2] - tvs[0] vec2 = pts - tvs[0] d00 = vec0.dot(vec0) d01 = vec0.dot(vec1) d11 = vec1.dot(vec1) d20 = vec2.dot(vec0) d21 = vec2.dot(vec1) denom = d00 * d11 - d01 * d01 v = (d11 * d20 - d01 * d21) / denom w = (d00 * d21 - d01 * d20) / denom u = 1 - v - w uvw = np.hstack((u.reshape((-1, 1)), v.reshape((-1, 1)), w.reshape((-1, 1)))) return uvw.reshape(input_shape)
[docs]def moeller_trumbore(ray_orig, ray_dir, tri_v0, tri_v1, tri_v2): r"""Decides if a ray intersects with a triangle using the Moeller-Trumbore algorithm. :math:`O + D = (1-u-v)V_0 + uV_1 + vV_2`. Args: ray_orig (array_like): 3D coordinates of the ray origin :math:`O`. ray_dir (array_like): Ray direction :math:`D` (not necessarily normalized). tri_v0 (array_like): Triangle vertex :math:`V_0`. tri_v1 (array_like): Triangle vertex :math:`V_1`. tri_v2 (array_like): Triangle vertex :math:`V_2`. Returns: tuple: - **u** (*float*) -- The :math:`u` component of the Barycentric coordinates of the intersection. Intersection is in-triangle (including on an edge or at a vertex), if :math:`u\geq 0`, :math:`v\geq 0`, and :math:`u+v\leq 1`. - **v** (*float*) -- The :math:`v` component. - **t** (*float*) -- Distance coefficient from :math:`O` to the intersection along :math:`D`. Intersection is between :math:`O` and :math:`O+D`, if :math:`0 < t < 1`. """ # Validate inputs ray_orig = np.array(ray_orig) ray_dir = np.array(ray_dir) tri_v0 = np.array(tri_v0) tri_v1 = np.array(tri_v1) tri_v2 = np.array(tri_v2) assert (ray_orig.shape == (3,)), "'ray_orig' must be of length 3" assert (ray_dir.shape == (3,)), "'ray_dir' must be of length 3" assert (tri_v0.shape == (3,)), "'tri_v0' must be of length 3" assert (tri_v1.shape == (3,)), "'tri_v1' must be of length 3" assert (tri_v2.shape == (3,)), "'tri_v2' must be of length 3" M = np.array([-ray_dir, tri_v1 - tri_v0, tri_v2 - tri_v0]).T # noqa: N806 y = (ray_orig - tri_v0).T t, u, v = np.linalg.solve(M, y) return u, v, t