如何检查一个点是否位于其他2个点之间的一条线上

nuw*_*way 15 algorithm geometry

我该怎么写这个函数?任何例子都赞赏

function isPointBetweenPoints(currPoint, point1, point2):Boolean {

    var currX = currPoint.x;
    var currY = currPoint.y;

    var p1X = point1.x;
    var p1y = point1.y;

    var p2X = point2.x;
    var p2y = point2.y;

    //here I'm stuck
}
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 41

假设point1point2不同,首先检查点是否在线上.为此你只需要一个矢量point1 -> currPoint和的"交叉产品" point1 -> point2.

dxc = currPoint.x - point1.x;
dyc = currPoint.y - point1.y;

dxl = point2.x - point1.x;
dyl = point2.y - point1.y;

cross = dxc * dyl - dyc * dxl;
Run Code Online (Sandbox Code Playgroud)

当且仅当cross等于零时,你的观点就在线上.

if (cross != 0)
  return false;
Run Code Online (Sandbox Code Playgroud)

现在,正如你所知,这一点确实存在于线上,现在是时候检查它是否位于原始点之间.x如果线条比"垂直"更"水平",则可以通过比较坐标来轻松完成,否则进行y坐标

if (abs(dxl) >= abs(dyl))
  return dxl > 0 ? 
    point1.x <= currPoint.x && currPoint.x <= point2.x :
    point2.x <= currPoint.x && currPoint.x <= point1.x;
else
  return dyl > 0 ? 
    point1.y <= currPoint.y && currPoint.y <= point2.y :
    point2.y <= currPoint.y && currPoint.y <= point1.y;
Run Code Online (Sandbox Code Playgroud)

注意,如果输入数据是完整的,则上述算法是完全积分的,即它不需要整数输入的浮点计算.计算时要小心潜在的溢出cross.

PS这个算法绝对精确,这意味着它会拒绝非常接近线但不精确在线上的点.有时这不是我们需要的.但这是一个不同的故事.

  • 您可以通过在交叉乘积验证中实现阈值来降低算法精度.因此,如果交叉乘积几乎为零,那么该点几乎就在"阈值= 0.1; if(abs(cross)> threshold)返回false;`. (7认同)
  • @mkirk:"线上任何给定的x只能有一个y值" - 对于垂直线不是这样.如果段是严格垂直的,则对"x"的范围检查不会产生有意义的答案.是的,人们可以随时检查`x`范围,但对于严格垂直的段,必须检查`y`范围.我的"更横向"/"更垂直"的方法只是一种平衡的概括. (3认同)
  • @Romel Pérez:不确定你的意思。上面的答案清楚地显示了如何检查点是否位于两个原始点之间。 (2认同)

max*_*000 23

Distance(point1,currPoint)+Distance(currPoint,point2)==Distance(point1,point2)
Run Code Online (Sandbox Code Playgroud)

但是如果你有浮点值,要小心,它们的情况有所不同......

  • 非常好,有浮点值(比如在JavaScript中),你可以做一些像`return distanceAC + distanceBC - distanceAB <THRESHOLD;` (4认同)

ima*_*ett 5

这与 JavaScript 无关。尝试以下算法,其中点 p1=point1 和 p2=point2,第三个点是 p3=currPoint:

v1 = p2 - p1
v2 = p3 - p1
v3 = p3 - p2
if (dot(v2,v1)>0 and dot(v3,v1)<0) return between
else return not between
Run Code Online (Sandbox Code Playgroud)

如果您想确保它也在 p1 和 p2 之间的线段上:

v1 = normalize(p2 - p1)
v2 = normalize(p3 - p1)
v3 = p3 - p2
if (fabs(dot(v2,v1)-1.0)<EPS and dot(v3,v1)<0) return between
else return not between
Run Code Online (Sandbox Code Playgroud)