创建非自相交多边形算法的有效性

发布于 2024-10-21 16:50:36 字数 753 浏览 3 评论 0原文

作为我的线程的扩展和部分答案,我编写了一个简单的算法,给出了一组点(具有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 的最左边的顶点)顶点与最左边的顶点连接起来 我认为该算法


是正确的,并且找不到它会失败的测试,但也许我遗漏了一些东西。

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

As an extension and partial answer to my thread I wrote a simple algorithm that given a set of points(with xy coordinates) can form a non self-intersecting polygon.


Claim: Given an arbitrary set of points with different coordinates it is always possible to construct a regular or irregular, non self-intersecting polygon.

The algorithm:

Assume there is a set V containing all the vertices

1) Sort all vertices in V by x-coordinate

2) Imagine a straight line (we'll call that "the divider") parallel to the x-axis which starting from the first node expands to infinity and divides/splits the vertices into two sets.

3) Now consider the two sets:

A = The set of all vertices above or on the divider line

B = The set of all remaining vertices

4) Starting at the leftmost vertex of A connect all vertices in A until you get to the rightmost

5) If the rightmost vertex of the sorted set V (the vertex with the biggest x coordinate) is not in A connect that last vertex (rightmost of A) with it.

6) Work backwards and starting from the rightmost vertex of the sorted set V (the vertex with the biggest x coordinate) connect all the vertices that are in B

7)Connect the first (leftmost vertex of B) vertex of B with the leftmost vertex of A


I think that the algorithm is correct and can't find a test that it would fail but maybe I'm missing something.

I would appreciate it if you could have a look and give me an example that wouldn't work if there is any(which I'm sure there must be).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

流云如水 2024-10-28 16:50:36

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

counterexample

Here is a counterexample. When step 5 does not draw a line, it is possible to self intersect.

counterexample

川水往事 2024-10-28 16:50:36

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

I'm not sure I understand correctly what you're trying to do. In the other thread, and in the corresponding thread at math.SE (which brought me here), you said you had a polygon and were trying to find its center of gravity. Here you say you have a set of points and you want to construct a non-intersecting polygon from it. Those are two quite different things. As I mentioned at math.SE, if the polygons are not known to be convex, a set of points doesn't uniquely define a polygon -- so the algorithm you propose here may construct some arbitrary non-self-intersecting polygon (I haven't checked whether it successfully does that) but that may or may not bear any relation to the polygon you were originally interested in. Or did I misunderstand your question at math.SE and you actually only have some points and want to construct just any non-self-intersecting polygon from them and don't care that there may be several inequivalent solutions for this?

暗地喜欢 2024-10-28 16:50:36

我想我有一个更简单的算法来创建这样的多边形。用软件实现可能比较困难,但用文字描述要容易得多。

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

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

形状通常有点像星形,但满足要求。

计算执行类似于:

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

I think I have a simpler algorithm that creates such a polygon. May be harder to implement in software but is much easier to describe in words.

  • Pick any point in the set as your start. Create a line at 0 angle starting from it.
  • start rotating the line around the point. The moment it meets any other point, draw an edge from the starting point to the newly found point.
  • continue rotating around the starting point, connecting any newly-found point with the last found.
  • at finish of the rotation, close the shape by meeting the start point.

In case of multiple finds on one direction, connect them picking one direction (say, starting with inner-most ending with outer-most)

The shape will be usually somewhat star-like, but fulfilling the requirements.

Computational execution would be like:

  • translate all points to coordinate set with origin[0,0] in one of the points.
  • convert all points to polar coordinate set
  • sort by: angle ascending, radius ascending.
  • connect all points in the sort order.
  • connect last to the first ([0,0]) point.
北恋 2024-10-28 16:50:36

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

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

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

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

除此之外 - 我相信你的说法是正确的。

I would prove it slightly differently by setting the "divider line" as a connection between left-most and right-most points, rather than parallel to x axis. It could happen that there are no points below or above the parallel-to-x line and that could cause trouble to your proof.

Also, connection (5) could lead to some self-intersections with the connections generated in point (6)

There is also a special case when all points are colinear and your polygon is degraded to a line.

We assume that the set V of vertices is finite ;)

Other than that - I believe your claim is true.

宣告ˉ结束 2024-10-28 16:50:36

我在 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;
    }
  }
}

希望您喜欢它!

I had the same problem in javascript and OpenLayers library. So this is my solution for detecting validity of a polygon in 'vectors' layer as a 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;
    }
  }
}

hope you enjoy it!!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文