[英]How can I find out if point is within a triangle in 3D?
I need an algorithm (3D), which would determine if point belongs to a triangle. 我需要一个算法(3D),它将确定点是否属于三角形。 And also if it does I want to know the distance between some point in triangle and a another point.
如果确实如此,我想知道三角形中某个点与另一个点之间的距离。 Triangles can be slightly rotated, but if point is outside triangles vertical reach then it should not be considered as inside the triangle.
三角形可以稍微旋转,但如果点在三角形垂直范围之外,则不应将其视为三角形内部。
Now I realize, my question probably doesn't make a lot of sense so here's the picture, which explains what I want. 现在我意识到,我的问题可能并没有多大意义所以这里是图片,它解释了我想要的东西。
Grey lines display, which way triangle is actually facing. 灰色线条显示,三角形实际面向哪个方向。
It's not actually that I want to check if a point is within a prism, but I after i find out if point lies within triangle (not exactly, might be on top of or below) then I need to find the distance between point and a triangle it belongs to. 实际上,我并不是要检查一个点是否在棱柱内,但是当我确定该点是否位于三角形内(不完全是,可能在其顶部或下方)之后,我需要找到点与a之间的距离。它属于的三角形。 And depending on the distance function will finally return if that point is inside the triangle.
如果该点在三角形内,则取决于距离函数将最终返回。 A little inaccuracy is allowed.
允许有点不准确。 However, maybe I want to check if a point is within a prism, but do not know that.
但是,也许我想检查一个点是否在棱镜内,但不知道。 I am just horrible at math so I am not aware of correct terminology.
我对数学很恐怖,所以我不知道正确的术语。
This seems like the 3D equivalent of Data structure to query points which lie inside a triangle . 这看起来像3D 数据结构等效于位于三角形内部的查询点 。 You could use the same method in 3D: in 3D, a plane cuts the space in two halves: a point is either at one side of the plane or at the other side.
您可以在3D中使用相同的方法:在3D中,平面将空间切成两半:一个点位于平面的一侧或另一侧。 The wedge-shape is a collection of planes: just combine the which_side_of_the_plane information for a given point with all the planes that build up the wedge .
楔形是平面的集合:只需将给定点的which_side_of_the_plane信息与构成楔形的所有平面结合起来 。
You can use a cylindrical version of barycentric coordinates . 您可以使用圆柱形重心坐标 。 I've only checked this for prisms that rise perpendicular from the triangular base -- another way to put this is that we are orthogonally projecting the point into the plane defined by the triangle, and checking if it is inside or not.
我只检查了这个从三角形基座垂直上升的棱镜 - 另一种方法是将这个点正交投影到由三角形定义的平面中,并检查它是否在内部。
If you want more details on the math ask (or better yet, try to figure it out yourself since it's a neat little exercise). 如果您想了解有关数学问题的更多详细信息(或更好的方法,请尝试自己解决,因为这是一个精巧的小练习)。
If our triangle is ABC
(non-degenerate), then N = (BA)x(CA)
(cross product) is a normal to the (unique) plane defined by the triangle. 如果我们的三角形是
ABC
(非退化),则N = (BA)x(CA)
(叉积)是该三角形定义的(唯一)平面的法线。 Call the point we want to test P
. 调用我们要测试的点
P
Now calculate the value a' = N . ((PB) x (PC))
现在计算值
a' = N . ((PB) x (PC))
a' = N . ((PB) x (PC))
(where .
is dot product). a' = N . ((PB) x (PC))
(其中.
是点积)。 a'
is the usual barycentric coordinate multiplied by NN
(which is positive). a'
是通常的重心坐标乘以NN
(正数)。
Similarly, we find b' = N . ((PC) x (PA))
同样,我们找到
b' = N . ((PC) x (PA))
b' = N . ((PC) x (PA))
and c' = N . ((PA) x (PB))
b' = N . ((PC) x (PA))
和c' = N . ((PA) x (PB))
c' = N . ((PA) x (PB))
. c' = N . ((PA) x (PB))
。 If all three of 'a'', 'b'', and 'c'' are non-negative, then the projection of P is inside the triangle (if you want to exclude the triangle itself, then all three must be strictly positive). 如果'a'','b''和'c''中的所有三个都是非负的,则P的投影在三角形内部(如果你想排除三角形本身,那么这三个必须是严格正的)。
This can be split into 2 problems. 这可以分为两个问题。
Withe the example below, you can do a check, for eg: 通过以下示例,您可以进行检查,例如:
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
... where eps
is the distance to consider points 'on the triangle' . ...其中
eps
是考虑三角形上的点的距离。
This code example uses functional Python so should be easy to move to other languages, it uses only simple arithmetic, no sqrt
or complex functions. 此代码示例使用函数式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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.