当前位置:编程学习 > C#/ASP.NET >>

凸包的c#实现算法

       前段时间看到生成凸包的Graham算法,查了一些资料,没看到c#版的,于是想动手写一个,该程序草草完成,其中有值得优化的地方,诸位可自行改正。
             Graham算法的原理:
    (1)给定一个点集P={P0,P1,.....Pn),找出点集中Y值最小的点,如果Y值最小的点有多个,可选择其中X值最小的 www.zzzyk.com
    (2)假设上一步找出的点位P0,现在对剩下的点进行极角排序,按逆时针(本程序是这样,其他的方式是一样的)极角从小到大排序,假定排序结果集为{p1,p2,p3,p4,....pn}。注意,这里不一定有N个点,因为可能存在几个点的极角相同,这时取据P0距最远的点,也或者你设定了一个极角阈值,当两个点的极角差小于该阈值时,取据P0距离远的点,这时生成的凸包有一点点误差,误差的大小取决于你设置的阈值。本程序没采用阈值,所以生成的凸包理论上不存在误差。
      在进行极角排序时,不需要真的算法每个点的极角(注意,这里的极角是该点与P0相对于X轴的夹角),只需要使用向量叉积来判断即可,这个过程我使用了链表来存储排序结果,因为这个过程会进行频繁的插入。
   (3)将p0,p1,p3入栈,p0,p1这两个点肯定在凸包上(原因很简单,p0不用解释了吧,p1因为它是极角最小的且为第一个点),p2则不一定在凸包上,然后进行循环(for(int i=2;i<n;i++),判定栈顶的下一个点,栈顶点,及p[i]点这三点组成的折线段是否向左转,如果是的话,则p[i]入栈;否则,当前位于栈顶的点不在凸包上,弹栈(该过程进行回朔,确保之前的所有点转向正确,这个步骤很重要,不然不能生成凸多边形),最后返回栈即可。
  下面是整个代码:
     算法部分:
   
 class ConvexAogrithm 
        { 
                private List<PointF> nodes; 
                private Stack<PointF> sortedNodes; 
                public PointF[] sor_nodes; 
                public ConvexAogrithm(List<PointF> points) 
                { 
                        nodes = points; 
                } 
                private double DistanceOfNodes(PointF p0, PointF p1) 
                { 
                        if (p0.IsEmpty || p1.IsEmpty) 
                                return 0.0; 
                        return Math.Sqrt((p1.X - p0.X) * (p1.X - p0.X) + (p1.Y - p0.Y) * (p1.Y - p0.Y)); 
                } 
                public void GetNodesByAngle( out PointF p0) 
                { 
                        LinkedList<PointF> list_node = new LinkedList<PointF>(); 
                        p0 = GetMinYPoint(); 
                        LinkedListNode<PointF> node = new LinkedListNode<PointF>(nodes[0]); 
                        list_node.AddFirst(node); 
                        for (int i = 1; i < nodes.Count; i++) 
                        { 
                                int direct = IsClockDirection(p0, node.Value, nodes[i]); 
                                if (direct == 1) 
                                { 
                                         list_node.AddLast(nodes[i]); 
                                         node = list_node.Last; 
                                         //node.Value = nodes[i]; 
                                        
                                } 
                                else if (direct == -10) 
                                { 
                                        list_node.Last.Value = nodes[i]; 
                                        //node = list_node.Last 
                                        //node.Value = nodes[i]; 
                                } 
                                else if (direct == 10) 
                                        continue; 
                                else if (direct == -1) 
                                { 
                                        LinkedListNode<PointF> temp = node.Previous; 
                                        while (temp != null && IsClockDirection(p0, temp.Value, nodes[i]) == -1) 
                                        { 
                                                temp = temp.Previous; 
                                        } 
补充:软件开发 , C# ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,