准备步骤:
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; }