【问题标题】:Validity of algorithm for creation of a non self-intersecting polygon创建非自相交多边形的算法的有效性
【发布时间】:2011-07-13 19:44:53
【问题描述】:

作为对my thread 的扩展和部分回答,我编写了一个简单的算法,给定一组点(具有 xy 坐标)可以形成一个非自相交的多边形。


声明:给定一组具有不同坐标的任意点,总是可以构造一个规则或不规则、非自相交的多边形。

算法:

假设有一个包含所有顶点的集合 V

1) 按x坐标对V中的所有顶点进行排序

2) 想象一条平行于 x 轴的直线(我们称其为“分隔线”),从第一个节点开始扩展到无穷大并将顶点分割/分割成两组。

3) 现在考虑两个集合:

A = 分割线上所有顶点的集合

B = 所有剩余顶点的集合

4) 从 A 的最左边的顶点开始连接 A 中的所有顶点,直到到达最右边

5) 如果排序集 V 的最右边的顶点(x 坐标最大的顶点)不在 A 中,则连接最后一个顶点(A 的最右边)。

6) 向后工作,从排序集V的最右边的顶点(x坐标最大的顶点)开始连接B中的所有顶点

7)连接B的第一个(B的最左边的顶点)顶点和A的最左边的顶点


我认为该算法是正确的,找不到会失败的测试,但也许我遗漏了一些东西。

如果您能看一下并给我一个如果有的话(我相信一定有)不起作用的例子,我将不胜感激。

【问题讨论】:

    标签: algorithm geometry polygon computational-geometry vertex


    【解决方案1】:

    我将通过将“分隔线”设置为最左侧和最右侧点之间的连接而不是平行于 x 轴来证明这一点。有可能在平行于 x 线的下方或上方没有任何点,这可能会给您的证明带来麻烦。

    此外,连接 (5) 可能会导致与点 (6) 中生成的连接发生一些自相交

    还有一种特殊情况,即所有点都共线并且您的多边形退化为一条线。

    我们假设顶点集合 V 是有限的 ;)

    除此之外 - 我相信你的说法是真实的。

    【讨论】:

    • 感谢您的回复!!! [1]“还有一种特殊情况,即所有点都共线并且您的多边形退化为一条线。”这实际上是一个有效的观点!!! [2]您能否举个例子:“此外,连接 (5) 可能会导致与点 (6) 中生成的连接发生一些自相交”。 [3]“可能发生在平行于 x 线的下方或上方没有任何点的情况,这可能会给您的证明带来麻烦。”和[1]一样对???
    【解决方案2】:

    我不确定我是否正确理解您要执行的操作。在另一个线程中,在the corresponding thread at math.SE(把我带到这里)中,你说你有一个多边形并试图找到它的重心。在这里,您说您有一组点,并且您想从中构造一个不相交的多边形。这是两个完全不同的东西。正如我在 math.SE 中提到的,如果不知道多边形是凸的,则一组点不会唯一地定义一个多边形——所以你在这里提出的算法可能会构造一些任意的非自相交多边形(我没有'没有检查它是否成功地做到了这一点),但这可能与您最初感兴趣的多边形有任何关系,或者我是否误解了您在 math.SE 上的问题,而您实际上只有一些要点并且想要构建任何来自它们的非自相交多边形,并且不在乎可能有几个不等价的解决方案?

    【讨论】:

    • @joriki 对不起,我没有正确解释!我最初试图找到一种算法来计算任何给定多边形的重心(自相交与否)。但是,由于我没有实际的多边形,只有一组点,我认为我可以“绘制”多边形,使其永远不会自相交。这就是我基本上试图用这个算法做的事情。这样我就可以应用质心的公式了。
    • @mixkat:这听起来像是一个定义不明确的问题。你如何获得这些积分?你怎么知道你从它们形成的任何多边形的质心是相关的?您可以从相同点构造的不同多边形的质心可能会有很大差异。例如,想象一个点几乎位于其他两个点之间,但稍微“向内”——您可以将它连接在这两个点之间,也可以将它连接在对面的两个点之间,结果截然不同。也许你真正感兴趣的是凸包?!
    • @joriki 你是对的,质心可能会有很大差异。我需要我的最终算法来考虑每个点的坐标,这就是我不看凸包的原因。我说主要思想是为一群人计算最近的交汇点。我想多边形的质心并不总是最准确的结果,但我认为它应该足够好。
    • @mixkat:对不起,我一定错过了“一群人最近的会面点”部分;我不知道你在哪里写的。在那种情况下,我完全不明白你为什么要为多边形烦恼。为什么不简单的计算一下这些人的重心? IE。 $\sum_{i=1}^n\vec{x}_i/n$。这是最小化人们到会面点的距离的平方和的解决方案。我认为没有理由将多边形带入其中。
    • @joriki 没关系!我在 math.SE 中将其写为评论!我怎样才能做到这一点?你能提供一个链接或解释这是怎么可能的吗?再次感谢你的帮助!!!
    【解决方案3】:

    我想我有一个更简单的算法可以创建这样一个多边形。可能更难在软件中实现,但更容易用文字描述。

    • 选择集合中的任意点作为起点。从它开始以 0 角创建一条线。
    • 开始围绕该点旋转线。在它遇到任何其他点的那一刻,从起点画一条边到新找到的点。
    • 继续围绕起点旋转,将任何新找到的点与最后找到的点连接起来。
    • 在旋转结束时,通过与起点相遇来闭合形状。

    如果在一个方向上有多个发现,则选择一个方向连接它们(例如,从最内层开始到最外层)

    形状通常有点像星星,但符合要求。

    计算执行如下:

    • 将所有点转换为坐标集,其中一个点为 origin[0,0]。
    • 将所有点转换为极坐标集
    • 排序方式:角度升序,半径升序。
    • 按排序顺序连接所有点。
    • 最后连接到第一个 ([0,0]) 点。

    【讨论】:

    • 欣赏输入,但是这在代码中实现起来要困难得多。看起来它可以工作(还没有实际检查过)
    • @joriki:我认为你误解了算法。它不会随你切换旋转点,它肯定会在所有点上工作。例如:i54.tinypic.com/24zzt4m.png
    • 你说得对,我误解了算法。对此感到抱歉。
    【解决方案4】:

    这是一个反例。当第5步没有画线时,可以自相交。

    【讨论】:

    • 是的!自己画一个类似的就行了!不过布置得很好!谢谢!好消息是我毕竟不需要算法!
    【解决方案5】:

    我在 javascript 和 OpenLayers 库中遇到了同样的问题。所以这是我将“向量”层中多边形的有效性检测为 OpenLayers.Layer.Vector 的解决方案:

    var ps = vectors.features[0].geometry.getVertices(), i, j, inx, x1, x2, x3, x4, y1, y2, y3, y4, x43, x21, y21, y43, y31, maxx12, maxx34, minx12, minx34;
    ps.push(ps[0]);
    for(i = 0; i < ps.length -1 ; i++ ) {
      x1 = ps[i].x; x2 = ps[i+1].x;
      y1 = ps[i].y; y2 = ps[i+1].y;
      for(j = i + 2; j < ps.length -1 ; j++ ) {
        x3 = ps[j].x; x4 = ps[j+1].x;
        y3 = ps[j].y; y4 = ps[j+1].y;
        x43 = x4 - x3; x21 = x2 - x1; y21 = y2 - y1; y43 = y4 - y3; y31 = y3 - y1;
        inx = ( x43*y21*x1 - x21*y43*x3 + y31*x21*x43 )/( x43*y21 - x21*y43 );
        if( x1 < x2 ){
          minx12 = x1; maxx12 = x2;
        } else {
          minx12 = x2; maxx12 = x1;
        }
        if( x3 < x4 ){
          minx34 = x3; maxx34 = x4;
        } else {
          minx34 = x4; maxx34 = x3;
        }
        if (minx12 < inx && inx < maxx12 && minx34 < inx && inx < maxx34 ){
          console.log('intersected!'+' ,x1: '+x1+' ,x2: '+x2+' ,inx: '+inx+' ,i: '+i+' ,j: '+j);
    
          return;
        }
      }
    }
    

    希望你喜欢它!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-18
      • 1970-01-01
      • 2012-12-25
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      • 2019-11-23
      • 2013-08-25
      相关资源
      最近更新 更多