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

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