查找点是否位于线段上

AMH*_*AMH 25 c# algorithm 3d point

我有由两个点A(x1,y1,z1)和B(x2,y2,z2)和点p(x,y,z)定义的线段.如何检查该点是否位于线段上?

use*_*999 36

从线端点A,B找到点P的距离.如果AB = AP + PB,则P位于线段AB上.

AB = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1));
AP = sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1)+(z-z1)*(z-z1));
PB = sqrt((x2-x)*(x2-x)+(y2-y)*(y2-y)+(z2-z)*(z2-z));
if(AB == AP + PB)
    return true;
Run Code Online (Sandbox Code Playgroud)

  • 它的速度怎么样?与分裂相比,Sqrt相当慢. (6认同)
  • 很好的答案.您可能想要考虑的一点是浮点舍入错误.假设AB = 12.0000001且AP + PB = 12.000003,您仍然可能想要考虑"足够接近"的事情,这取决于您正在做什么. (4认同)
  • 完全没有,处理器有专门的 Math.Sqrt() 指令。它需要的时间与除法一样长。 (2认同)

Rob*_*gar 21

如果该点上线,则:

(x - x1) / (x2 - x1) = (y - y1) / (y2 - y1) = (z - z1) / (z2 - z1)
Run Code Online (Sandbox Code Playgroud)

计算所有三个值,如果它们是相同的(在某种程度的容差范围内),您的点就在线上.

要测试点是否在段中,而不仅仅是在线上,您可以检查它

x1 < x < x2, assuming x1 < x2, or
y1 < y < y2, assuming y1 < y2, or
z1 < z < z2, assuming z1 < z2
Run Code Online (Sandbox Code Playgroud)

  • 如果x1 == x2或y1 == y2,您的测试将失败 (22认同)
  • 由于无法修复的浮点精度问题,如果 x 接近 x1 或 y 接近 y1 或 z 接近 z1,则失败。不要使用此解决方案。数学考试很好,但 c# 代码的答案完全错误。 (3认同)
  • 只是为了完成这个答案,[这里](http://mathforum.org/library/drmath/view/65721.html)你可以找到完整的数学解释 (2认同)

Cad*_*oux 7

首先考虑AB和AP的交叉产品.如果它们是共线的,则它将为0.

此时,它仍然可以在延伸超过B或A之前的更大线上,因此我认为您应该能够检查pz是否介于az和bz之间.

实际上,这似乎是重复的,并且作为答案中的一个提及,它在美丽的代码中.


小智 5

如果有人寻找内联版本:

public static bool PointOnLine2D (this Vector2 p, Vector2 a, Vector2 b, float t = 1E-03f)
{
    // ensure points are collinear
    var zero = (b.x - a.x) * (p.y - a.y) - (p.x - a.x) * (b.y - a.y);
    if (zero > t || zero < -t) return false;

    // check if x-coordinates are not equal
    if (a.x - b.x > t || b.x - a.x > t)
        // ensure x is between a.x & b.x (use tolerance)
        return a.x > b.x
            ? p.x + t > b.x && p.x - t < a.x
            : p.x + t > a.x && p.x - t < b.x;

    // ensure y is between a.y & b.y (use tolerance)
    return a.y > b.y
        ? p.y + t > b.y && p.y - t < a.y
        : p.y + t > a.y && p.y - t < b.y;
}
Run Code Online (Sandbox Code Playgroud)