Это можно разделить на 2 задачи.
- Проверьте, чтобы точка внутри 3-х плоскостей определялась сторонами треугольника.
- Найти расстояние до плоскости, определенной нормалью треугольника.
(и использовать собственную логику для проверки, считается ли это расстояние близким или нет) .
В приведенном ниже примере вы можете выполнить проверку, например:
if (isect_point_tri_prism_v3(p, v1, v2, v2) and
(dist_signed_squared_point_tri_plane_v3(p, v1, v2, v2) < (eps * eps)):
# do stuff
... где eps
- расстояние, на которое необходимо рассмотреть точки 'на треугольнике' .
В этом примере кода используется функциональный Python, поэтому его легко перенести на другие языки, он использует только простую арифметику, без sqrt
или сложных функций.
# ----------------
# helper functions
def sub_v3v3(v0, v1):
return (v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2])
def dot_v3v3(v0, v1):
return ((v0[0] * v1[0]) + (v0[1] * v1[1]) + (v0[2] * v1[2]))
def cross_v3v3(v0, v1):
return ((v0[1] * v1[2]) - (v0[2] * v1[1]),
(v0[2] * v1[0]) - (v0[0] * v1[2]),
(v0[0] * v1[1]) - (v0[1] * v1[0]))
def closest_to_line_v3(p, l0, l1):
"""
Return the closest point to p on the line defined by (l0, l1)
"""
u = sub_v3v3(l1, l0)
h = sub_v3v3(p, l0)
l = dot_v3v3(u, h) / dot_v3v3(u, u)
return (l0[0] + u[0] * l,
l0[1] + u[1] * l,
l0[2] + u[2] * l)
def point_in_slice_v3(p, v, l0, l1):
cp = closest_to_line_v3(v, l0, l1)
q = sub_v3v3(cp, v)
rp = sub_v3v3(p, v)
# For languages which allow divide-by-zero,
# this is taken into account and returns false.
h = dot_v3v3(q, rp) / dot_v3v3(q, q)
return (h >= 0.0 and h <= 1.0)
# --------------
# main functions
def isect_point_tri_prism_v3(p, v0, v1, v2):
"""
Return True when the point is inside the triangular prism.
Zero area triangles always return false.
"""
return (point_in_slice_v3(p, v0, v1, v2) and
point_in_slice_v3(p, v1, v2, v0) and
point_in_slice_v3(p, v2, v0, v1))
def dist_signed_squared_point_tri_plane_v3(p, v0, v1, v2):
"""
Return the squared distance to the triangle,
positive values are 'in-front' of the triangle, negative behind.
(using CCW coordinate system - OpenGL).
Remove the 'copysign' call for the non-signed version.
(if you don't need to know which side of the triangle the point is on).
"""
from math import copysign
n = cross_v3v3(sub_v3v3(v2, v1), sub_v3v3(v0, v1))
rp = sub_v3v3(p, v1)
len_sq = dot_v3v3(n, n)
side = dot_v3v3(rp, n)
fac = side / len_sq
return copysign(len_sq * (fac * fac), side)