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};\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

綜上述:一個完美的距離和面積測量的工具就完成了!歡迎同行們相互交流和學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM