AreEngine 求最小面积的外接矩形,非IEnvelope,表达不清楚了

 

 

1,总是会得到一些奇奇怪怪的要求,求一个面对象的外接最小面积的矩形,和ArcToolBox中的Mininum Bounding Geometry功能下的RECTANGLE_BY_AREA想似。具体看下图:

 

区别如上图所示:IEnvelope 得到的是下图所示,需要的是第一种

(只是记录一下,可以解决问题,但不是最优方法,代码冗余量大,待解决)

基本思路:获取所有边,以其中的某一条边入手,遍历所有点到这条边的距离,取最大距离的点(pointA),以此点为准画一条平行于第一条线的线,作为第二条边,再以此点(pointA)画一条垂直于第一条边的线作为辅助线,再次遍历所有点到此辅助线的距离,得到最大距离的点(pointB),以pointB画一条垂直第一条边的线作为第三条边,再次遍历所有点到第三条边的距离,取得最大距离的点pointC,以pointC画一条垂直第一条边的线,作为第四条边。然后相邻两条线求交点,得到四个点,用四个点构造矩形。计算面积,以此,将所有的矩形都得到然后,比较面积求最小的就好了,好鸡儿啰嗦我。

不喜就喷!接受反驳!

实现方法如下:

  1 private void Mininum()
  2         {
  3             IFeatureClass pFClass = (this.axMapControl1.get_Layer(0) as IFeatureLayer).FeatureClass;
  4             IFeatureCursor pFCursor = pFClass.Search(null, false);
  5             IFeature pFeature = pFCursor.NextFeature();
  6             while (pFeature != null)
  7             {
  8                 //求凸包
  9                 IGeometry pGeometry = pFeature.Shape;
 10                 ITopologicalOperator pTOperator = pGeometry as ITopologicalOperator;
 11                 IGeometry pNEWGeometry = pTOperator.ConvexHull();
 12                 //每个凸包边的集合
 13                 ISegmentCollection pSCollection = pNEWGeometry as ISegmentCollection;
 14                 //每个凸包点的集合
 15                 IPointCollection pPCollection = pNEWGeometry as IPointCollection;
 16                 //用来筛选最小的面积的一个界值,只要足够大,多少都可以
 17                 double area = 99999999999999;
 18                 //存储当前遍历的要素(feature)的最小面积矩形对象。
 19                 IGeometry pGeoMetry = null;
 20                 for (int i = 0; i < pSCollection.SegmentCount; i++)
 21                 {
 22                     double DIS = 0;
 23                     double DIS3 = 0;
 24                     double DIS4 = 0;
 25 
 26                     IPoint RESUPoint=new PointClass();
 27                     IPoint Resu3point = new PointClass();
 28                     IPoint Resu4point = new PointClass();
 29                     ISegment pPolyline_Segment = pSCollection.get_Segment(i);
 30                     IPoint FromPoint = pPolyline_Segment.FromPoint;
 31                     IPoint ToPoint = pPolyline_Segment.ToPoint;
 32                     //y=kx+b下边两行为第一条边的表达式的参数值
 33                     double k = (FromPoint.Y - ToPoint.Y) / (FromPoint.X - ToPoint.X);
 34                     double b = FromPoint.Y - FromPoint.X * k;
 35                     for (int j = 0; j < pPCollection.PointCount; j++)
 36                     {
 37                         IPoint eachPoint = pPCollection.get_Point(j);
 38                         double distanse = dis(eachPoint, k, b);
 39                         if (distanse > DIS)
 40                         {
 41                             DIS = distanse;
 42                             RESUPoint = eachPoint;
 43                         }
 44                     }
 45                     //第二条边的参数值
 46                     double k1 = k;
 47                     double b1 = RESUPoint.Y - k1 * RESUPoint.X;
 48                     //求第二个点到第一条边的投影点及所在直线的参数(辅助线)
 49                     double k2 = -1 / k;
 50                     double b2 = RESUPoint.Y - k2 * RESUPoint.X;
 51                     //遍历第三条边所在的位置
 52                     for (int m = 0; m < pPCollection.PointCount; m++)
 53                     {
 54                         IPoint pPoint = pPCollection.get_Point(m);
 55                         double distance = dis(pPoint, k2, b2);
 56                         if (distance > DIS3)
 57                         {
 58                             DIS3 = distance;
 59                             Resu3point = pPoint;
 60                         }
 61                     }
 62                     //第三条的参数值
 63                     double k3 = k2;
 64                     double b3 = Resu3point.Y - k3 * Resu3point.X;
 65                     //------------开始求第四条边
 66                     for (int n = 0; n < pPCollection.PointCount; n++)
 67                     {
 68                         IPoint pPoint=pPCollection.get_Point(n);
 69                         double distance = dis(pPoint,k3,b3);
 70                         if(distance>DIS4)
 71                         {
 72                             DIS4=distance;
 73                             Resu4point = pPoint;
 74                         }
 75                     }
 76                     //第四条边的参数值;
 77                     double k4 = k3;
 78                     double b4 = Resu4point.Y-k4*Resu4point.X;
 79 
 80                     //------------四个交点的值
 81                     //pointA
 82                     double x_a=(b4-b)/(k-k4);
 83                     double y_a = k * x_a + b;
 84                     //pointB
 85                     double x_b = (b4 - b1) / (k1 - k4);
 86                     double y_b = k1 * x_b + b1;
 87                     //pointC
 88                     double x_c = (b3 - b1) / (k1 - k3);
 89                     double y_c = k1 * x_c + b1;
 90                     //pointD
 91                     double x_d = (b3 - b) / (k - k3);
 92                     double y_d = k * x_d + b;
 93                     //构造矩形
 94                     IPoint pointa = new PointClass();
 95                     pointa.PutCoords(x_a, y_a);
 96                     IPoint pointb = new PointClass();
 97                     pointb.PutCoords(x_b, y_b);
 98                     IPoint pointc = new PointClass();
 99                     pointc.PutCoords(x_c, y_c);
100                     IPoint pointd = new PointClass();
101                     pointd.PutCoords(x_d, y_d);
102                     IPoint pointa1 = new PointClass();
103                     pointa1.PutCoords(x_a, y_a);
104                     IPointCollection RECTANG = new PolygonClass();
105                     RECTANG.AddPoint(pointa);
106                     RECTANG.AddPoint(pointb);
107                     RECTANG.AddPoint(pointc);
108                     RECTANG.AddPoint(pointd);
109                     RECTANG.AddPoint(pointa1);
110                     IPolygon pPolygon = RECTANG as IPolygon;
111                     IGeometry PPPPPPPPGeo = pPolygon as IGeometry;
112                     //*************************
113                     //axMapControl1.FlashShape(PPPPPPPPGeo);
114                     //注意此处!因构造矩形的时候,顺时针逆时针不能确定,因此从ArcGIS来说这个面积有可能为负值,并不是取绝对值就可以,外环与内环的区别,因此用数学方法。
115                     double a1=Math.Sqrt((pointb.Y-pointa.Y)*(pointb.Y-pointa.Y)+(pointb.X-pointa.X)*(pointb.X-pointa.X));
116                     double c1=Math.Sqrt((pointc.Y-pointb.Y)*(pointc.Y-pointb.Y)+(pointc.X-pointb.X)*(pointc.X-pointb.X));
117                     double pArea = a1 * c1;
118                     if (Math.Abs(pArea) < area)
119                     {
120                         area = Math.Abs(pArea);
121                         pGeoMetry = PPPPPPPPGeo;
122                     }
123                 }
124                 axMapControl1.FlashShape(pGeoMetry);
125                 pFeature = pFCursor.NextFeature();
126             }
127             System.Runtime.InteropServices.Marshal.ReleaseComObject(pFCursor);
128         }
1 public double dis(IPoint pPoint, double k, double b)
2         {
3             double numerator = System.Math.Abs(k * pPoint.X - pPoint.Y + b);
4             double Denominator = System.Math.Sqrt(k * k + 1);
5             double dis=numerator/Denominator;
6             return Math.Abs(dis);
7         }

弱弱的再啰嗦一句:这个功能在arcpy中很好实现

arcpy.MinimumBoundingGeometry_management("parks.shp",
                                         "c:/output/output.gdb/parks_mbg",
                                         "RECTANGLE_BY_AREA", "NONE")

就一句就可以了,只是这个东西速度慢的要死,再次使用最小得到的矩形的又得选择。

OK!BBBBBBBBBBBBBBBBBBBBBBBBBBB完了,

转载于:https://www.cnblogs.com/clgis/p/9831915.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你解答这个问题。 首先,需要用到 Arcenginee 的鼠标事件。在鼠标按下事件中记录鼠标的起始位置,然后在鼠标移动事件中获取当前鼠标位置,计算出矩形的左上角和右下角坐标,最后在鼠标释放事件中完成矩形的绘制。 以下是伪代码的示例: ``` // 定义全局变量 private Point startPoint; // 鼠标起始位置 private Point endPoint; // 鼠标当前位置 private bool isDrawing; // 是否正在绘制矩形 private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e) { // 记录鼠标起始位置 startPoint = new Point(e.x, e.y); isDrawing = true; } private void axMapControl1_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e) { if (isDrawing) { // 获取当前鼠标位置 endPoint = new Point(e.x, e.y); // 刷新地图控件,实时显示矩形 axMapControl1.Refresh(); } } private void axMapControl1_OnMouseUp(object sender, IMapControlEvents2_OnMouseUpEvent e) { if (isDrawing) { // 绘制矩形 DrawRectangle(axMapControl1.ActiveView.ScreenDisplay); // 重置标志位和起始/结束点坐标 isDrawing = false; startPoint = null; endPoint = null; // 刷新地图控件,清除矩形 axMapControl1.Refresh(); } } private void DrawRectangle(IScreenDisplay screenDisplay) { // 创建矩形对象 IEnvelope envelope = new EnvelopeClass(); envelope.PutCoords(startPoint.X, endPoint.Y, endPoint.X, startPoint.Y); // 创建符号对象 ISimpleFillSymbol fillSymbol = new SimpleFillSymbolClass(); fillSymbol.Color = GetRGBColor(255, 0, 0); // 绘制矩形 screenDisplay.SetSymbol(fillSymbol); screenDisplay.DrawRectangle(envelope); } private IColor GetRGBColor(int r, int g, int b) { // 创建颜色对象 IRgbColor rgbColor = new RgbColorClass(); rgbColor.Red = r; rgbColor.Green = g; rgbColor.Blue = b; return rgbColor; } ``` 这段代码可以在 Arcenginee 中实现绘制矩形的功能。当鼠标按下时,记录鼠标起始位置;当鼠标移动时,获取当前鼠标位置并计算矩形的左上角和右下角坐标,实时绘制矩形;当鼠标释放时,完成矩形的绘制并清除矩形,重置标志位和起始/结束点坐标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值