【问题标题】:Insert a set of vertex within a convex polygon在凸多边形内插入一组顶点
【发布时间】:2014-04-06 16:00:46
【问题描述】:

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

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

这里是我的代码的 sn-p,如果还不够,请询问我更多信息,并使用 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:如果上述算法的任何步骤不清楚,并且需要更多信息来帮助我解决问题,请随时提问。

【问题讨论】:

  • 你有一组分散的点,想找到一个最小长度的环,连接所有这些点?
  • 确实如此,可能是出现问题的一种方式,但仍然需要以排序方式的顶点
  • 你的问题会是这样的吗? en.wikipedia.org/wiki/Hamiltonian_cycle 这看起来更像是一个几何问题,而不仅仅是一个编程问题。
  • 看这里stackoverflow.com/q/21816562/2521214 我的部分答案包含多边形化(找到正确的顶点顺序),您必须稍微调整一下(反转地图使用),因为该代码会找到孔并且您想找到区域相反...

标签: c# algorithm geometry


【解决方案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.现在您已经对顶点进行了排序

  • 这就是你想要的

【讨论】:

  • @monk 我看到你是新用户,所以......如果问题得到回答,请检查正确答案附近的复选标志(它会给作者积分并标记解决方案供其他人快速查看)如果它仅在某种方式上有所帮助,您可以通过单击上方的三角形投赞成票,或者如果它是错误的harm-full abusive ...然后您可以通过该下方的三角形投反对票(每个问题或答案只能投 1 票)我认为这也会奖励你一些徽章......如果你有足够的积分,你也可以投票给cmets。因为所有投票都可以撤消所以不用担心
  • 感谢您的提示。我保持联系
【解决方案2】:

如果您的顶点保证形成一个凸多边形,这种替代方法将节省角度计算:

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

  • 通过两个极值点画一条线,并将这些点划分为两个子集中,位于其两侧;您将分离上下轮廓部分;

  • 保持直线下方的点以相同的顺序排列,并将其他点颠倒。你完成了。

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

【讨论】:

  • 我的方法使用 Jarvis's March,类似于您上面描述的过程,但我的多边形并不总是凸的,这就是问题所在。计算点集的质心并使用该点对它们进行排序作为枢轴解决了我的问题。取而代之的是使用角度值,我使用叉积来获得排序的点序列,这在计算上更有效。感谢您的评论。
猜你喜欢
  • 2013-05-26
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 2012-04-15
  • 2013-04-25
  • 2020-08-27
  • 2020-03-20
  • 1970-01-01
相关资源
最近更新 更多