zoukankan      html  css  js  c++  java
  • ArcGIS Engine开发之量测功能

    1、距离测量

     距离测量时,片段长度通过两点之间距离计算得到,全部长度通过片段长度的和计算得到。主要用到INewLineFeedback和IScreenDisplay两个接口。

     1)INewLineFeedback接口

    该接口的主要方法如表:

    方法 描述
    Start 从指定点开始绘制追踪线的绘制
    MoveTo 鼠标移动到的点,并实时绘制与上一节点的连接线
    AddPoint 添加一个点
    Stop 停止追踪线的绘制,并返回用户绘制的几何体

    2)IScreenDisplay接口

    MapControl中的每一个视图都有一个ScreenDisplay对象,用于控制视图中的图形绘制。ScreenDisplay对象除了管理窗体屏幕的显示属性外,也管理缓存和视图屏幕的变化等。可以通过IActiveView接口的ScreenDisplay属性获取ScreenDisplay对象。通ScreenDisplay对象的DisplayTransformation属性进行设备单位和地图单位的转换。

    3)实现的思路

      • 鼠标点击时,首先判断INewLineFeedback接口的实例化对象pNewLineFeedback是否为空,如果为空就实例化,并设当前的鼠标点为pNewLineFeedback的起始点。反之,则把当前鼠标点添加到pNewLineFeedback中。
      • 鼠标移动时。实时计算鼠标移动点与上一鼠标点击点的距离,以及所画线的长度。
      • 鼠标双击时,停止绘制,并清空pNewLineFeedback对象
      • btnMeasureLine的单击事件打结果窗体,并设置bMeasurelength为true,以便从数据视图的鼠标事件中判断量算功能是否开启。

    2、面积量测

    面积量测通过INewPolygonFeedback接口绘制多边形来实现。使用NewPolygonFeedback和使用NewLineFeedback的方法类似,但其显示和返回的几何特征是一个封闭多边形,这意味着画多边形停止时,起点将成为终点,从而结束形状的绘制,该方法至少需要三个点被添加到几何对象中。

    实现的思路如下

    1)、点击鼠标时首先判断INewPolygonFeedback接口的实例化对象pNewPolygonFeedback是否为空,则实例化,并设当前鼠标点为pNewPolygonFeedback的起始点;反之则把当前的鼠标点添加到pNewPolygonFeedback中。

    2)、鼠标移动时,判断绘制多边形时点的个数pPointCol是否超过3个点,如果超过三个,则由点击构建IPolygon接口,IArea接口,进而计算出面的总长度和面积。

    3)、鼠标双击时,停止绘制,并清空pNewPloygonFeedback对象。


    3、面积测量和距离测量的具体代码分布:

    1.前提:新建一个用来显示测量结果的公共窗体
    2.二者的button_click事件:
     1  #region 距离的测量按钮单击事件
     2         private void barButtonItem10_ItemClick(object sender, ItemClickEventArgs e)
     3         {
     4             mainMapControl.CurrentTool = null;
     5             pMouseOperate = "MeasureLength";
     6             mainMapControl.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
     7             if (frmMeasureResult == null || frmMeasureResult.IsDisposed)
     8             {
     9                 frmMeasureResult = new FormMeasureResult();
    10                 frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
    11                 frmMeasureResult.labToltal.Text = "";
    12                 frmMeasureResult.Text = "距离量测";
    13                 frmMeasureResult.Show();
    14             }
    15             else
    16             {
    17                 frmMeasureResult.Activate();
    18             }
    19         }
    20         #endregion
     1  #region 面积测量按钮单击事件
     2         private void btnPolyMeasure_ItemClick(object sender, ItemClickEventArgs e)
     3         {
     4             mainMapControl.CurrentTool = null;
     5             pMouseOperate = "MeasureArea";
     6             mainMapControl.MousePointer = esriControlsMousePointer.esriPointerCrosshair;//光标样式为十字丝
     7             if (frmMeasureResult == null || frmMeasureResult.IsDisposed)
     8             {
     9                 frmMeasureResult = new FormMeasureResult();
    10                 frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed); ;
    11                 frmMeasureResult.labToltal.Text = "";
    12                 frmMeasureResult.Text = "面积测量";
    13                 frmMeasureResult.Show();
    14             }
    15             else
    16             {
    17                 frmMeasureResult.Activate();
    18             }
    19         }
    20         #endregion
    3.在mainForm中定义全局变量
     1  #region 变量的定义
     2         //变量的定义
     3         //距离和面积量测的变量
     4         private FormMeasureResult frmMeasureResult = null;//量算的结果窗体
     5         private INewLineFeedback pNewLineFeedback;//追踪线对象
     6         private INewPolygonFeedback pNewPolyFeedback;//追踪面对象
     7         private IPoint pPoint = null;//鼠标点击点
     8         private IPoint pMovePt = null;//鼠标移动时的当前点
     9         private double dToltalLength = 0;//量测总长度
    10         private double dSegmentLength = 0;//片段距离
    11         private IPointCollection pArearPointCol = new MultipointClass();//对面积量算时画的点进行存储
    12         //定义状态栏坐标显示工具
    13         private string sMapUnits = "未知单位";//地图单位变量
    14         private object missing = Type.Missing;
    15         #endregion
    4.在mianMapControl控件的OnMouse_Down事件中进行switch语句注册
     1 #region   距离量测
     2                     case "MeasureLength":
     3                         //判断追踪线对象是否为空,若是则实例化并设置当前鼠标点为起始点
     4                         if (pNewLineFeedback == null)
     5                         {
     6                             //实例化追踪线对象
     7                             pNewLineFeedback = new NewLineFeedbackClass();
     8                             pNewLineFeedback.Display = (mainMapControl.Map as IActiveView).ScreenDisplay;
     9                             //设置起点,开始动态线绘制
    10                             pNewLineFeedback.Start(pPoint);
    11                             dToltalLength = 0;
    12                         }
    13                         else //如果追踪线对象不为空,则添加当前鼠标点
    14                         {
    15                             pNewLineFeedback.AddPoint(pPoint);
    16                         }
    17                         //pGeometry = m_PointPt;
    18                         if (dSegmentLength != 0)
    19                         {
    20                             dToltalLength = dToltalLength + dSegmentLength;
    21                         }
    22                         break;
    23                     #endregion
    24                     #region 面积测量
    25                     case "MeasureArea":
    26                         if (pNewPolyFeedback == null)
    27                         {
    28                             //实例化追踪面对象
    29                             pNewPolyFeedback = new NewPolygonFeedback();
    30                             pNewPolyFeedback.Display = (mainMapControl.Map as IActiveView).ScreenDisplay;
    31                             pArearPointCol.RemovePoints(0, pArearPointCol.PointCount);
    32                             //开始绘制多边形
    33                             pNewPolyFeedback.Start(pPoint);
    34                             pArearPointCol.AddPoint(pPoint, ref missing, ref missing);
    35                         }
    36                         else
    37                         {
    38                             pNewPolyFeedback.AddPoint(pPoint);
    39                             pArearPointCol.AddPoint(pPoint,ref missing,ref missing );
    40                             
    41                         }
    42                         break;
    43                     #endregion
    5.在mapControl的OnMouseMove事件中进行设置鼠标移动的实时测量结果
     1  #region 长度量算 实时显示测量结果
     2             if (pMouseOperate == "MeasureLength")
     3             {
     4                 if (pNewLineFeedback != null)
     5                 {
     6                     pNewLineFeedback.MoveTo(pMovePt);
     7                 }
     8                 double deltaX = 0; //两点之间X差值
     9                 double deltaY = 0; //两点之间Y差值
    10 
    11                 if ((pPoint != null) && (pNewLineFeedback != null))
    12                 {
    13                     deltaX = pMovePt.X - pPoint.X;
    14                     deltaY = pMovePt.Y - pPoint.Y;
    15                     dSegmentLength = Math.Round(Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY)), 3);
    16                     dToltalLength = dToltalLength + dSegmentLength;
    17                     if (frmMeasureResult != null)
    18                     {
    19                         frmMeasureResult.labToltal .Text = String.Format("当前线段长度{0}{1}",dSegmentLength,sMapUnits );
    20                         frmMeasureResult.labToltalLength.Text = String.Format("总长度:{0}{1}",dToltalLength,sMapUnits );
    21                        //// frmMeasureResult.labToltal.Text  = String.Format(
    22                        //     "当前线段长度:{0:.###}{1};
    总长度为: {2:.###}{1}",
    23                        //     dSegmentLength, sMapUnits, dToltalLength);
    24                         dToltalLength = dToltalLength - dSegmentLength; //鼠标移动到新点重新开始计算
    25                     }
    26                     frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
    27                 }
    28             }
    29             #endregion
    30             #region 面积量算
    31             if(pMouseOperate=="MeasureArea")
    32             {
    33                 if(pNewPolyFeedback!=null)
    34                 {
    35                    pNewPolyFeedback .MoveTo(pMovePt);
    36                 }
    37                 IPointCollection pPointCol=new Polygon();
    38                 IPolygon pPolygon=new PolygonClass();
    39                 IGeometry pGeo=null;
    40                 ITopologicalOperator pTopo=null;
    41                 for(int i=0;i<=pArearPointCol.PointCount-1;i++)
    42                 {
    43                     pPointCol.AddPoint(pArearPointCol.get_Point(i),ref missing,ref missing);
    44                 }
    45                 pPointCol.AddPoint(pMovePt,ref missing,ref missing);
    46                 if(pPointCol.PointCount<3)  return;
    47                 pPolygon=pPointCol as IPolygon;
    48                 if((pPolygon!=null))
    49                 {
    50                     pPolygon.Close();
    51                     pGeo=pPolygon as IGeometry;
    52                     pTopo=pGeo as ITopologicalOperator ;
    53                     //使几何图形的拓扑正确
    54                     pTopo.Simplify();
    55                     pGeo.Project(mainMapControl.Map.SpatialReference);
    56                     IArea pArea=pGeo as IArea ;//面积量算所画的面
    57                     frmMeasureResult.labToltal.Text=String.Format("总面积为:{0}平方{1}",pArea.Area,sMapUnits);
    58                     frmMeasureResult.labToltalLength.Text=String.Format("总长度为:{0}{1}",pPolygon.Length,sMapUnits);
    59                     pPolygon=null;
    60                 }
    61             }
    62           #endregion
    6.mainMapControl的OnDoubleclick事件中
     1  #region 距离量测的结束设置
     2             if (pMouseOperate == "MeasureLength")
     3             {
     4                 if (frmMeasureResult != null)
     5                 {
     6                     frmMeasureResult .labToltalLength .Text  = "线段总长度为:" + dToltalLength + sMapUnits;
     7                 }
     8                 if (pNewLineFeedback != null)
     9                 {
    10                     pNewLineFeedback.Stop();
    11                     pNewLineFeedback = null;
    12                     //清空所画的线对象
    13                     (mainMapControl.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
    14                 }
    15                 dToltalLength = 0;
    16                 dSegmentLength = 0;
    17             }
    18             #endregion
    19             #region 面积测量的结束设置
    20             if (pMouseOperate == "MeasureArea")
    21             {
    22                 if (pNewPolyFeedback != null)
    23                 {
    24                     pNewPolyFeedback.Stop();
    25                     pNewPolyFeedback = null;
    26                     //清空所画的线对象
    27                     (mainMapControl.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
    28                 }
    29                 pArearPointCol.RemovePoints(0, pArearPointCol.PointCount);//清空点集中的所有点
    30             }
    31             #endregion

    综上述:一个完美的距离和面积测量的工具就完成了!欢迎同行们相互交流和学习。

  • 相关阅读:
    2017年前端开发者应该重拾基本技能学习
    手机号码月消费档次API
    实用且免费API接口2
    在线文档转换API word,excel,ppt等在线文件转pdf、png
    火车票抢票API 根据乘客的车次与座席要求快速订票出票
    利用问答机器人API开发制作聊天类App
    用聚合数据API(苏州实时公交API)快速写出小程序
    OllyDbg使用笔记
    解决git commit 大文件推送失败
    每日一语
  • 原文地址:https://www.cnblogs.com/dongteng/p/5891196.html
Copyright © 2011-2022 走看看