【问题标题】:For a point in an irregular polygon, what is the most efficient way to select the edge closest to the point?对于不规则多边形中的一个点,选择最接近该点的边的最有效方法是什么?
【发布时间】:2011-05-30 12:20:50
【问题描述】:

给定一个不规则多边形和该多边形内的一个点,我如何确定多边形中的哪条边最接近该点?

我可能需要对多边形内的大量点(例如 50-200 个点)运行此计算。

【问题讨论】:

  • 只有大约 100 个点,这不是一个大的点集,除非你这样做了无数次,或者除非多边形本身有无数的边。在某些时候,四叉树分解可能会有所帮助。在达到这一点之前,如果您的语言允许这样的计算,即使是矢量化形式,也很容易求解点到线段的距离。

标签: geometry computational-geometry


【解决方案1】:
  1. 计算直线上与多边形每条边相切的最近点。
  2. 计算每条线段(多边形的边缘)上离相关点最近的点。
  3. 计算每条线段上最近点到相关点的距离。
  4. 找到最小距离。距离最短的对应多边形边就是答案。

这个算法的每一步都是线性时间(O(n))。

以下是每个步骤的基本公式:

计算与多边形每条边相切的直线上的最近点。

  • 令多边形边的一个端点为p1 = {x1, y1}
  • 令多边形边的另一个端点为p2 = {x2, y2}
  • 让您正在分析的多边形中的点为p3 = {x3,y3}
  • u 为p1 和p2 之间距离的百分比,这是在p1 和p2 形成的线上找到点所需的距离,这样p1+u(p2-p1) = 线上最靠近p3 的点(此点与 p3 之间的线段也恰好垂直于通过 p1 和 p2 的线)。
  • u = ((x3 - x1)(x2 - x1)+(y3 - y1)(y2 - y1)) / ((x2 - x1)^2 + (y2 - y1)^2)
  • 设p1和p2形成的直线上离p3最近的点为pu = {xu, yu}
  • xu = x1 + u (x2 - x1)
  • yu = y1 + u (y2- y1)
  • 就像我们之前所说的pu = {xu, yu}
  • 对每个多边形边缘重复这些计算(即替换为新的 p1s 和 p2s)

计算每条线段(多边形的边缘)上离相关点最近的点。

pu 只是在0 <= u <= 1 时线段上最近的点。否则,线段的适当端点是离相关点最近的点。因此,对于在上述步骤中计算的每个pu, p1, p2, and u,请执行以下操作:

  • Let pc = {xc, yc} 被表示为多边形边缘的线段上离相关点最近的点。
  • IF u<0 THEN pc = p1
  • ELSE IF u>1 THEN pc = p2
  • ELSE pc = pu

计算每条线段上最近点到相关点的距离。

  • p3pc 之间的距离 = `sqrt((x3 - xc)^2 + (y3 - yc)^2)
  • 对所有电脑重复此计算

求最小距离。距离最短的对应多边形边就是答案。

  • 遍历所有距离,直到找到最小的距离。对应的多边形边就是答案。

这是一个图表,可帮助您理解本文中的要点和术语所代表的含义:

....

【讨论】:

  • 我认为# ELSE IF u>0 THEN pc = p2 中有错字...应该是 u>1 吗?
  • 谢谢!如果可以的话,我会 +2 你的答案:)
  • 我非常喜欢这个答案,但我注意到了一件事。 u 公式中有一个“错字”。 (x3 - x1)(x2 - x1)+(y3 - y1)(y2 - y1) 的结果必须除以 (x2 - x1)^2 + (y2 - y1)^2 所以正确的分组是需要。
【解决方案2】:

正确答案取决于问题的整体结构:当您考虑多个查询时会发生什么?我假设每个查询将处理不同的点。但是多边形呢?您是否希望收到针对同一个多边形的多个查询?还是每次多边形都不一样?

如果每个查询都应用于不同的、不可预测的多边形,那么您拥有的唯一解决方案本质上是对所有多边形边缘进行全面检查,并对每个边缘进行点到线段距离测试。它可以通过各种 [启发式] 方式进行优化(尽早丢弃不必要的测试),但在最坏的情况下,无法绕过完整的测试。

但是,如果您期望问题的多边形方面具有某种可预测性和稳定性(对同一个多边形或一组固定多边形进行足够多的点查询),那么情况就会发生巨大变化。在这种情况下,最好的方法是在多边形内预先构建基于边缘的 Voronoi 图。然后您可以解决点定位问题(有已知的有效算法),以确定查询点属于哪个 Voronoi 区域。这将立即告诉您哪个边缘最接近。

当您需要处理对同一多边形的许多点查询时,后者的效率无与伦比,但需要相当多的努力才能实现。所以,这完全取决于您需要什么样的解决方案。

附:我看到您在问题中声明您将为单个多边形的大量点运行它。这立即使基于 Voronoi 图的解决方案成为可行的方法。算法的额外细微差别可能取决于大量点是事先完全知道还是以不可预测的方式逐点到达。

【讨论】:

  • 我已经这样做了。为什么没有支持不规则边界多边形的 C# 轻量级 Voronoi 库?我想编写自己的库,但到目前为止我发现的唯一信息充满了我不熟悉的数学符号和结构。所以我想出了一种快速简便的方法(可能不是最有效的)来计算 Voronoi 图,即首先执行 Delaunay 三角剖分并将质心用于 Voronoi 顶点,然后,对于非平分的 Delaunay 边,运行边界多边形边缘的一条新的二等分线。
  • (字符用完了...)...在每个质心的外部质心和最近的边界多边形边缘之间运行线将为我提供 Voronoi 图所需的所有外部多边形。如果我有一个干净、高效、轻量级的支持不规则多边形的 Voronoi 库,我什至不需要问这个问题。
【解决方案3】:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 2011-06-20
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多