1. 程式人生 > >通過ArcEngine接口建立凸包(一)

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

geb ppt esp sqrt rect urn tar 次循環 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;
            }

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