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