点到多边形的距离

Posted

技术标签:

【中文标题】点到多边形的距离【英文标题】:Distance from a point to a polygon 【发布时间】:2012-06-14 13:55:55 【问题描述】:

我正在尝试确定二维空间中。该点可以在多边形内部或外部;多边形可以是凸的也可以是凹的。

如果点在多边形内或多边形外且距离小于用户定义的常量d,则程序应返回TrueFalse 否则。

我发现了一个类似的问题:Distance from a point to a polyhedron or to a polygon。但是,在我的情况下,空间是 2D 的,并且多边形可以是凹的,所以它与那个空间有些不同。

我想应该有一种比将多边形偏移d 并确定它在多边形内部还是外部更简单的方法。

任何算法、代码或提示我都可以用谷歌搜索。

【问题讨论】:

调用代码是否需要知道距离,还是只是在一定距离内? 我为你找到了这个。它返回从点到多边形的实际距离(如果点在多边形之外,则为正,否则为负)。这是 Matlab 代码,但从算法的角度来看可能会有所帮助:mathworks.com/matlabcentral/fileexchange/… @KendallFrey 只是它是否在一定距离内。但是,是否有可能在不知道确切距离的情况下确定它是否在一定距离内? 多边形上的哪个点是否重要,它可以在连接 2 个点的线上的一部分上吗?您是在寻找最小距离,还是只是在寻找任何距离? @trumpetlicks 寻找最小距离。抱歉,不确定“连接 2 点的线的一部分”是什么意思。多边形边界上的任何点都很重要。 【参考方案1】:

最好的办法是遍历所有线并找到从点到线段的最小距离。

要找到从点到线段的距离,首先通过选择线上的任意点P1P2 来找到点到线的距离(使用端点可能是明智的) .然后将向量从P1 带到您的点P0 并找到(P2-P1) . (P0 - P1),其中. 是点积。将此值除以||P2-P1||^2,得到一个值r

现在如果您选择P1P2 作为您的点,您可以简单地检查r 是否介于0 和1 之间。如果r 大于1,则P2 是最近的点,所以你的距离是||P0-P2||。如果r小于0,那么P1是最近的点,所以你的距离是||P0-P1||

如果0<r<1,那么你的距离就是sqrt(||P0-P1||^2 - (r * ||P2-P1||)^2)

伪代码如下:

for p1, p2 in vertices:

  var r = dotProduct(vector(p2 - p1), vector(x - p1))
  //x is the point you're looking for

  r /= (magnitude(vector(p2 - p1)) ** 2)

  if r < 0:
    var dist = magnitude(vector(x - p1))
  else if r > 1:
    dist = magnitude(vector(p2 - x))
  else:
    dist = sqrt(magnitude(vector(x - p1)) ^ 2 - (r * magnitude(vector(p2-p1))) ^ 2)

  minDist = min(dist,minDist)

【讨论】:

这也是我的想法。这个 SO 答案谈到了找到点和线段之间的最短距离:***.com/questions/849211/…。 有没有可用的算法? @Muneem 我最后更新了我的答案,以便于理解伪代码。 我相信描述和代码中有几个错误:r 应该除以 P1P2 的平方幅度,而不是 PP1 的幅度。尚未检查数学,但这与@hatchet 评论中链接的答案一致,而且效果更好! 首先,您还需要检查点是否在多边形中。如果是,则返回零,否则按照@HansZ 计算【参考方案2】:

如果你有一个工作点到线段的距离函数,你可以用它来计算从点到多边形每个边的距离。当然,你必须先检查点是否在多边形内。

【讨论】:

【参考方案3】:

您需要快速还是简单? 它是否必须在边缘情况下始终绝对正确,或者足够好大部分时间都可以吗?

典型的解决方案是找出到每个顶点的距离并找到具有最小值的对(请注意,对于凸多边形外的点,这些可能不相邻),然后检查每个线段的点到线的交点。

对于大型复杂形状,您还可以存储近似多边形边界框(矩形或六边形)并在检查更多细节之前找到最近的边。

您可能还需要代码来处理恰好在一行中的特殊情况。

【讨论】:

考虑一个三角形多边形的极端例子,它有两个顶点离目标点很远,但它们之间的线非常接近目标点。三角形的第三个顶点距离该线仅一小段距离。只检查连接到最近顶点的线的快捷方式会产生错误的答案。 @hatchet,是的,这就是我说你需要考虑使用的原因。游戏中的碰撞检测例程不同于导航,分形海岸线不同于 CFD 应用。 我编写游戏程序,这个算法似乎不适用于多边形的边不能保证等长的任何应用程序。 为其他刚刚发现这个的人详细说明。我认为这个解决方案“边界框”是碰撞广泛阶段的一个很好的解决方案。但是,如果您正在处理距离,即试图找到几个多边形中的一个最接近一个点,它根本没有帮助。这是因为你总是可以设计一个多边形来生成一个更接近点但实际边界更远的边界框。【参考方案4】:

我可以帮助你解决这个问题:

即使使用未经测试的代码片段,也可以使用Wikipedia entry 计算距离。 内/外边界可以用这个Stack Post and links解决

还有一些备注:

您应该只检查最近的点,正如 Martin Beckett 的回答指出的那样,因为另一个段可以“预测”非常接近,但实际上并不需要接近。

【讨论】:

对于内/外边界问题,我不仅比较矩形,而且比较一般多边形。我发现您提供的链接中的评论有帮助。谢谢!【参考方案5】:

我不知道其他答案的性能差异,但在 boost C++ 库中,有一个名为 distance 的通用实现。它包含有关每种情况下复杂性的信息,并且在您的问题情况下它是线性的。

几天前我也在寻找这个问题的解决方案,我想分享这个发现。希望它对某人有所帮助。

【讨论】:

【参考方案6】:

如果这对其他人有帮助,我对doverbin 的答案进行了逆向工程,以了解它为何能够以图形方式显示这三个案例正在计算的内容。 (doverbin,如果您愿意,请随时将其合并到您的答案中。)

【讨论】:

以上是关于点到多边形的距离的主要内容,如果未能解决你的问题,请参考以下文章

用于查找从点到多边形的最小距离的 Javascript 代码(由 html 区域定义)

POJ 1584 A Round Peg in a Ground Hole 判断凸多边形 点到线段距离 点在多边形内

POJ - 1584 A Round Peg in a Ground Hole(判断凸多边形,点到线段距离,点在多边形内)

POJ 1584 A Round Peg in a Ground Hole(凸多边形判断 + 点是否在多边形内 + 点到线段的最短距离)

C# 计算地图上某个坐标点的到多边形各边的距离

C# 计算地图上某个坐标点的到多边形各边的距离