通過ArcEngine接口建立凸包(一)
阿新 • • 發佈:2017-10-07
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 = newPointArrayClass(); public IPointArray FirstCos = new PointArrayClass(); public IPointArray First2Pt = new PointArrayClass(); public IPointArray LoopPt = new PointArrayClass(); public IPointArray NextPts = new PointArrayClass(); public IPointArray NewPts = newPointArrayClass(); 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接口建立凸包(一)