通过ArcEngine接口建立凸包(一)

准备步骤:

1.先要能实现选择点的功能,可以利用矩形选点要素的方法axMapControl1.TrackRectangle()。

2.要建立凸包,必须有存凸包(线要素)的文件,然后通过下拉框选择这个图层,再在构建凸包的时候把凸包线存进去。

3.前面的接口声明如下:

        public IPoint qian = new PointClass();
        public IPoint zhong = new PointClass();
        public IPoint hou = new PointClass();

        public IPointArray Ymin = new PointArrayClass();
        public IPointArray FirstCos = new PointArrayClass();
        public IPointArray First2Pt = new PointArrayClass();
        public IPointArray LoopPt = new PointArrayClass();
        public IPointArray NextPts = new PointArrayClass();
        public IPointArray NewPts = new PointArrayClass();
        public IPolyline pPolyLine = new PolylineClass();  //这个后来没用到了
        //这个方法是将所选择的点存进IPointArray
public IPointArray LoadPoint(IArray pIDArray, IGeometry pGeo, IPoint pt, IFeature pFeature, IIdentifyObj pIdObj, IEnumFeature enumFeature) { if (pIDArray != null) { for (int i = 0; i < pIDArray.Count; i++) { pGeo = pFeature.Shape as IGeometry; pt = pFeature.Shape as IPoint; pFeature = enumFeature.Next(); pIdObj = pIDArray.get_Element(i) as IIdentifyObj; LoadPt.Add(pt); } } return LoadPt; }
//先计算最开始的两个点
            public IPointArray First2Point(IPointArray LoadPt)
            {
                Ymin.RemoveAll();
                int p = 0;
                for (int j = 0; j < LoadPt.Count; j++)
                {
                    if (LoadPt.Element[p].Y > LoadPt.Element[j].Y)//找出y最小的极限点
                        p = j;
                }
                Ymin.Add(LoadPt.Element[p]);//先把第一个点存进来
                for (int j = 0; j < LoadPt.Count; j++)//再把LoadPt的所有点存进来
                {
                    IPoint Pt = new PointClass();
                    Pt = LoadPt.get_Element(j);
                    Ymin.Add(Pt);
                }
                DeleteRepeatPoint(Ymin);//删除掉重复存的那个点(留9个点)
                //MessageBox.Show("最下方点是" + Ymin.Element[0].X.ToString("#0.00") + " , " + Ymin.Element[0].Y.ToString("#0.00"));

                FirstCos.RemoveAll();
                for (int i = 0; i < Ymin.Count; i++)
                {
                    IPoint Pt = new PointClass();
                    Pt.PutCoords(30000000, Ymin.Element[0].Y);
                    hou = Pt;
                    zhong = Ymin.Element[0];
                    qian = Ymin.Element[i];//下一个点

                    //计算余弦值,取最大的余弦值的点就是下一个点(黄石)
                    double c = System.Math.Sqrt((hou.X - zhong.X) * (hou.X - zhong.X) + (hou.Y - zhong.Y) * (hou.Y - zhong.Y));
                    double a = System.Math.Sqrt((qian.X - zhong.X) * (qian.X - zhong.X) + (qian.Y - zhong.Y) * (qian.Y - zhong.Y));
                    double b = System.Math.Sqrt((hou.X - qian.X) * (hou.X - qian.X) + (hou.Y - qian.Y) * (hou.Y - qian.Y));
                    double Cosine = (a * a + c * c - b * b) / (2 * a * c);
                    FirstCos.Add(Ymin.Element[i]);
                    FirstCos.Element[i].M = Cosine;
                }
                //下面这个循环是为了删除FirstCos里面的最下方点,因为它的值是NaN
                for (int j = 0; j < FirstCos.Count; j++)
                {
                    if (double.IsNaN(FirstCos.Element[j].M))
                        FirstCos.Remove(j);//将最下方点去掉
                }

                First2Pt.RemoveAll();
                int m = 0;
                for (int k = 1; k < FirstCos.Count; k++)
                {
                    if (FirstCos.Element[m].M < FirstCos.Element[k].M)//找出cos最小的点(黄冈)
                        m = k;
                }
                First2Pt.Add(FirstCos.Element[m]);//将这个cos最小的点最先存储进数组中
                First2Pt.Add(Ymin.Element[0]);//将第一个点存储进数组中
                for (int j = 0; j < FirstCos.Count; j++)//再把FirstCos的所有点存进来
                {
                    IPoint Pt = new PointClass();
                    Pt = FirstCos.get_Element(j);
                    First2Pt.Add(Pt);
                }
                DeleteRepeatPoint(First2Pt);//删除掉重复存的那个点
                return First2Pt;
            }

之后再开始计算第一圈余下的点

public IPointArray Next(IPointArray First2Pt)
            {
                LoopPt.RemoveAll();
                IPointArray NextCos = new PointArrayClass();
                for (int j = 2; j - 2 < First2Pt.Count; j++)
                {
                    for (int i = 2; i < First2Pt.Count; i++)
                    {
                        hou = First2Pt.Element[1];
                        zhong = First2Pt.Element[0];
                        qian = First2Pt.Element[i];//下一个点

                        //计算余弦值,取最大的余弦值的点就是下一个点(黄石)
                        double c = System.Math.Sqrt((hou.X - zhong.X) * (hou.X - zhong.X) + (hou.Y - zhong.Y) * (hou.Y - zhong.Y));
                        double a = System.Math.Sqrt((qian.X - zhong.X) * (qian.X - zhong.X) + (qian.Y - zhong.Y) * (qian.Y - zhong.Y));
                        double b = System.Math.Sqrt((hou.X - qian.X) * (hou.X - qian.X) + (hou.Y - qian.Y) * (hou.Y - qian.Y));
                        double Cosine = (a * a + c * c - b * b) / (2 * a * c);
                        First2Pt.Element[i].M = Cosine;
                        NextCos.Add(First2Pt.Element[i]);
                    }

                    int m = 0;
                    for (int k = 1; k < NextCos.Count; k++)
                    {
                        if (NextCos.Element[m].M > NextCos.Element[k].M)//找出cos最小的点
                            m = k;
                    }
                    NextPts.Add(NextCos.Element[m]);
                    for (int k = 0; k < First2Pt.Count; k++)//再把First2Pt的所有点存进来
                    {
                        IPoint Pt = new PointClass();
                        Pt = First2Pt.get_Element(k);
                        NextPts.Add(Pt);
                    }
                    DeleteRepeatPoint(NextPts);

                    LoopPt.Add(NextCos.Element[m]);
                    First2Pt.RemoveAll();//重新装下一次循环要用的First2Pt
                    for (int k = 0; k < NextPts.Count; k++)//再把NextPts的所有点给First2Pt(此时点顺序已经变了)
                    {
                        IPoint Pt = new PointClass();
                        Pt = NextPts.get_Element(k);
                        First2Pt.Add(Pt);
                    }
                    NextCos.RemoveAll();
                    NextPts.RemoveAll();
                }
                DeleteRepeatPoint(LoopPt);//删除掉重复存的那个点
                LoopPt.Add(LoopPt.Element[0]);
                //下面代码是测试这一步的结果
                //ArrayList mesPt = new ArrayList();
                //for (int i = 0; i < LoopPt.Count; i++)
                //{
                //    mesPt.Add(LoopPt.Element[i].X.ToString("#0.00") + " , " + LoopPt.Element[i].Y.ToString("#0.00"));
                //}
                //string str = string.Join(";\n", (string[])mesPt.ToArray(typeof(string)));
                //MessageBox.Show("凸包点包括:\n" + str);

                return LoopPt;
            }
原文地址:https://www.cnblogs.com/huangyanjia/p/7635604.html