【问题标题】:how to order vertices in a simple, non-convex polygon如何在简单的非凸多边形中对顶点进行排序
【发布时间】:2011-07-28 21:01:09
【问题描述】:

我有一个问题,我有一系列简单的非凸多边形的点(我希望我的术语是正确的)。但这些点不一定是按顺序排列的(即顺时针或逆时针)。为了让 Flash 的绘图 API 正确绘制填充区域,我需要让这些点在边缘周围按顺序排列(最终连接到起点)。

有没有什么方法可以顺时针或逆时针对笛卡尔坐标列表进行排序,这样我就可以在不“举笔”的情况下从一个点到另一个点绘制我的形状?

我看到一篇文章对多边形的 4 点进行排序,但我认为这是仅针对 4 点的特殊情况。我的形状至少有 6 分。在列表中,保证每个条目与至少一个相邻条目(前一点或后一点)相邻(顺时针或逆时针顺序)。例如:A、B、D、C... 或 B、A、D、C... 但不是 A、C、B、D...(我需要排序所以我得到 A、B、C、D 或 D、C、B、A)。我找到了这篇文章,但似乎没有答案:Sort point list into polygon

CPU 性能是个问题。但即使是“缓慢”的解决方案,如果它易于实现和理解(对于下一个程序员),如果我能想出一个有效的缓存机制,也可能没问题。

我想附上一张图片来展示我需要做什么但还没有 10 点声望点的例子。无论如何,如果我有办法在这个多边形列表中对第三个示例的顶点进行排序,那将是完美的:http://upload.wikimedia.org/wikipedia/commons/1/1f/Assorted_polygons.svg

非常感谢任何和所有的帮助,谢谢!

编辑: 我确实可以保证坐标系的中心点——它将是屏幕的中心。所有点都将介于 0 和屏幕宽度/高度之间(原点显然是宽度/高度 / 2)。我不能保证多边形将在其内部包含原点。这是一个罕见的例外情况,但我需要考虑它。

顺便说一句,我的线段不一定按顺序排列的原因是因为它们是使用 Conrec 生成的:http://paulbourke.net/papers/conrec/(它们是等高线)。我使用以下命令对 Conrec 生成的等高线段进行排序:How to assemble an array(s) of continuous points for a contour line using Conrec 现在的问题案例是地图上的外部等高线。这些将与地图的边缘相交(即,不形成封闭的多边形)。在这种情况下,我在地图边界的边缘绘制,直到我重新连接线开始的位置(在地图的边缘)或兄弟线进入地图(重复直到我最终回到我的起点观点)。然后我可以绘制一个区域并让填充 API 工作。希望这些信息有所帮助。我认为最好的办法是生成多边形顶点的有序列表,但也许需要另一种方法。

【问题讨论】:

  • 这个问题没有意义。多边形的形状取决于顶点的顺序。如果你改变它们的顺序,你会画出不同的形状...但是如果你想选择一个任意的中心,你可以从那个中心点按 angle 排序。 atan2(y - centerY,x - centerX) 顺便说一句,我认为您的意思是“凸”或“非凹”。圆是凸的。
  • 您是否检查了我提供的链接中的示例?那应该能够确认我的意思是不是非凸的。我可以保证绘制点的原点。我会适当地编辑。
  • 您实际上不是从 Conrec 获得了 的列表吗?这与顶点列表不同。您可以通过检查共享顶点的线来发现连接的线。
  • 是的,抱歉,您在技术上是正确的。我从 Conrec 得到一个两点线段。但我的最终结果是一个行列表,其中行是一个点列表(它是一个多维数组)。这是因为不能保证等高线在有限有界地图上与自身闭合。它可能多次进入和离开地图,因此是多维线阵列。这些线实际上不会共享任何顶点。请注意,我并不是说这是最好的做事方式。这是我能想到的唯一方法。
  • 是的,但是如果线条在离开地图时才变得不连续,那么您将有一个更容易解决的问题。例如,在地图的顶部边界上,找到最左边的那个点,然后在下一个最左边的那个点上画一条边,然后跳到下一个,然后在后面的那个点上画一条边,依此类推。对地图/视口的每个边缘重复此操作。

标签: geometry polygon vertex-array non-convex


【解决方案1】:

一个表明问题不是唯一可解的简单示例是点 a=(0,0), b=(2,0), c=(1,1), d=(1,2);每个顺序 (a,b,c,d,a), (a,b,d,c,a) (a,c,b,d,a) 都是简单的多边形。

【讨论】:

    【解决方案2】:

    我正在考虑一个O(n^2) 算法:
    由于您有绘制点的顺序(希望如此),因此您知道每条边的端点。
    选择一个开始点,然后继续直到与另一条边相交。
    然后你标记那个点,继续在新的边缘,直到你到达另一个边缘或端点。每当您到达更改边缘的点时,将其列出。一旦你到达起点,你就完成了。

    【讨论】:

    • 这听起来很接近我必须做的。谢谢你。对于任何给定的线段,首先我必须确定其他哪条线的端点最接近当前线的终点,然后我必须从最近的端点开始沿着下一条线绘制(可能是倒序)。
    【解决方案3】:

    也许你的意思是多边形 是凸的(即它是非凹的)。否则我不认为你正在做的事情实际上是可能的(可能有多种方法可以“连接点”并形成一个多边形)。

    在这种情况下我能想到的一种技术: 首先,根据您给出的规则,列表中的前两项必须形成一条边。 然后尝试添加以列表顺序出现的顶点;在每种情况下,如果结果只能是凹的,则从结果列表中删除前一个元素并暂时忽略它。浏览完源列表后,如果您仍有跳过的顶点,请继续处理那些跳过的顶点。

    编辑:好的,刚刚从维基百科查看了您的示例,您确实是指非凸的。不幸的是,我认为这是不可能的。

    【讨论】:

    • 谢谢。我希望在我的问题中使用其他一些有保证的条件,我可能会比你建议的更容易解决(在 CPU 周期中更容易)。但我也可以试试这个。
    【解决方案4】:

    好吧,你不会喜欢它,但这是不可能的。如果您考虑删除演示多边形中的所有线,您可以以不同的方式连接它们并且仍然具有有效的非凸多边形,那么排序应该如何知道该走哪条路?这就是非凸多边形的糟糕之处。

    【讨论】:

    • 确实如此。但至少它会给我一个有力的论据,争取更多的时间。 “数学上不可能”有一个很好的戒指。不幸的是,之前的程序员告诉我们他已经完成了这个功能,然后退出了。所以现在我必须告诉项目负责人... :-)
    猜你喜欢
    • 1970-01-01
    • 2013-11-11
    • 2015-10-04
    • 2012-12-17
    • 2011-11-14
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    • 2013-05-26
    相关资源
    最近更新 更多