在凸多边形内插入一组顶点

时间:2014-04-06 16:00:46

标签: c# algorithm geometry

我想找出以无序方式给出的多边形中一组顶点的正确顺序。对于这个问题,我开发了一种基于计算几何概念的算法。首先,我得到逆时针排序的顶点集的凸包。然后,我保持剩余的顶点按其极角排序,从一个枢轴开始,该顶点是具有最低X坐标的顶点,然后我将使用我想要添加的顶点之间的叉积计算的绝对值插入和凸包边缘的两个端点。有了这些信息,我将在两个点之间插入相应的顶点,其十字产品的绝对值最低,与我上面解释的相同。

这是我的问题,这个启发式并不总是正确的,我有问题得到多边形顶点的排序序列。重要的是要记住,多边形可以是复杂的多边形。我想知道是否有任何算法允许我以更一致的方式做到这一点,或者有人可以帮助我改进上面解释的算法。

在这里,我的代码片段,如果还不够,请问我更多,并使用c#和.NET 4.5:

var CH = JarvisMarch(P); // P is the set of unsorted vertex of the polygon
            var V = (from v in P where !CH.Contains(v) select v).ToArray();
            var pivot = (from v in V orderby v.Y, v.X select v).FirstOrDefault();                


            if (CH.Count < P.Length)
            {
                QuickSortPolar(ref V, 0, V.Length - 1, pivot);

                foreach (var rm in V)
                {
                    var C = CH.ToArray();
                    var T = new RedBlackTree(); // this is not entirely necessary 
                    var wlk = new List<IComparable>();
                    var min = float.MaxValue;
                    var succ = default(GeometryVertex); // this structure have the X and Y coordenate of the vertex

                    QuickSortCoorX(ref C, 0, C.Length - 1);  // for the sweep plane algorithm

                    for (int i = 0; i < C.Length; i++) // this is just to build the segments in a appropriate way
                    {
                        var j = CH.IndexOf(C[i]) == CH.Count - 1 ?
                            0 : CH.IndexOf(C[i]) + 1;
                        var sgm = new GeometrySegment()
                        {
                            Start = CH[j == 0 ? CH.Count - 1 : j - 1],
                            End = CH[j]
                        };
                        var find = T.Search(sgm);

                        if (find == null || find == RedBlackTree.sentinel)
                            T.Insert(sgm);
                    }

                    T.Inorder(T.root, ref wlk);

                    foreach (var sgm in wlk) // Here is the key of the algorithm
                    {
                        var s = (GeometrySegment)sgm;
                        var curr = (float)Math.Abs(cw(s.Start, rm, s.End));

                        if (curr < min || (curr == min && s.End < succ))
                        {
                            min = curr;
                            succ = s.End;
                        }
                    }

                    CH.Insert(CH.IndexOf(succ), rm);
                } 

先谢谢!!

PD:如果上面解释的算法的任何步骤都不清楚,并且需要更多信息来帮助我解决问题,请随时询问。

2 个答案:

答案 0 :(得分:1)

如果你只有没有洞的2D凸面区域,那么你可以轻松完成这个

  • (类似于您目前的做法)
  • 如果不是这种情况,请使用与我的评论或
  • 中的链接不同的方法
  • 某种多边形/三角剖分算法......

1.计算区域中心(您的支点)

  • 只计算平均点坐标(您的支点)

    x0 = (p1.x+p2.x+...pn.x)  / n
    y0 = (p1.y+p2.y+...pn.y)  / n
    

2.计算所有点的极坐标

a = atan2(p(i).x-x0,p(i).y-y0)
r = sqrt ((p(i).x-x0)^2,(p(i).y-y0)^2) // ^ is power not xor !!!
  • 对于速度你不需要r平方你可以用同样的方式使用r ^ 2

3.按角度排序所有顶点

  • 升序或降序将决定多边形绕组CW / CCW
  • 根据您的坐标系配置

4.如果同一角度有多个点

  • 使用最高r
  • 的人
  • 删除其余的

5.现在你已经排序了顶点

  • 这是你想要的

答案 1 :(得分:0)

如果您的顶点保证形成凸多边形,则此备选方法将备用角度计算:

  • 排序X;检查两个极端的可能关系并在Y上对它们进行排序;

  • 通过两个极值点绘制直线,并在两侧的两个子集中划分点;你将把上下轮廓部分分开;

  • 将点下方的点保持在相同的顺序中并反转其他点。你已经完成了。

请注意,如果您的多边形不是凸面,则使用字典排序和两个子序列的Graham扫描的相同过程将计算凸包。