【发布时间】:2013-01-22 20:20:15
【问题描述】:
我要计算一个点到一个三角形的最短距离(3d)。我已将该点投影到三角形平面上,然后采用该点投影的重心坐标。但是我找不到将坐标固定在三角形内的方法。
搜索时我只找到了 0
【问题讨论】:
-
如果平面上的投影不在三角形中,你可以忽略它,看看到线段的距离。
-
哦,没想到。仍然如果可以夹紧,它可能会更快。
我要计算一个点到一个三角形的最短距离(3d)。我已将该点投影到三角形平面上,然后采用该点投影的重心坐标。但是我找不到将坐标固定在三角形内的方法。
搜索时我只找到了 0
【问题讨论】:
我意识到这是一个老问题,但还没有真正得到解答,而且它目前是 Google 上“钳制重心坐标”的第一个热门话题。
在下面,p0、p1、p2 是三角形的顶点,u、v、w 是点 p = p0*u + p1*v + p2*w 的重心坐标。我假设u+v+w = 1。
正如 MSN 指出的那样,三角形上最近的点取决于三角形,因此任何仅对 u、v、w 的操作都无法工作。
如果u、v、w都是正数,则点在三角形内,无事可做。
如果其中任何一个为负数,则该点位于相应边的错误一侧。我们需要将点移动到该边上。对于相应的重心坐标,三角形边缘上的点为零。另外两个只是点从一端到另一端的距离。
if ( u < 0)
{
float t = Dot(p-p1,p2-p1)/Dot(p2-p1,p2-p1);
t = Clamp01( t );
return Vector3( 0.0f, 1.0f-t, t );
}
else if ( v < 0 )
{
float t = Dot(p-p2,p0-p2)/Dot(p0-p2,p0-p2);
t = Clamp01( t );
return Vector3( t, 0.0f, 1.0f-t );
}
else if ( w < 0 )
{
float t = Dot(p-p0,p1-p0)/Dot(p1-p0,p1-p0);
t = Clamp01( t );
return Vector3( 1.0f-t, t, 0.0f );
}
else
{
return Vector3( u, v, w );
}
Clamp01() 如果介于0 和1 之间,则返回t,如果为负数,则返回0,如果大于1,则返回1。 Dot( a, b ) 是两个向量 a 和 b 的点积。
【讨论】:
如果你想找到一个点到一个三角形的最短距离,你不能用这种方式把一个点夹在一个三角形上。距离在笛卡尔空间中,而重心坐标不在。
为了确定点到三角形外的三角形的距离,您需要确定该点最接近三角形的哪个特征(线段或角),然后确定到该特征的距离。以任何不考虑转换回笛卡尔空间的方式来钳制重心坐标都是行不通的。
【讨论】:
尝试将u 和v 钳制为0..1,然后设置w = 1 - u - v 以保持规范化约束。
【讨论】:
u、v 和w 需要夹在0..1 之间。就是这样。
例如
[u,v,w] = [-0.17, 0.64, 1.85]
三角形上会是
[u,v,w] = [0, 0.64, 1]
【讨论】:
[u,v,w] 和[2u,2v,2w] 指向同一个位置。所以你总是可以除以一个标量来得到u+v+w=1,但你不必这样做。要最终提取(x,y) 坐标,您需要进行除法,但从数学上讲,任何值都是有效的。
如果有人想知道,我先解决了
夹紧u 和v 和w = 1 - u - v 比
夹紧u 和w 和v = 1 - u - w 比
夹紧v 和w 和u = 1 - v - w
其他 2 个建议的解决方案给了我奇怪的输出,并且似乎正确钳位。
可能有更好/更快的方法,但目前这项工作。
【讨论】: