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};\r\n總長度為: {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