ArcEngine c#開發 距離面積量算 (零碎)
using System; using System.IO ; using System.Windows.Forms ; using System.Reflection ; using ESRI.ArcGIS.Carto ; using ESRI.ArcGIS.Display ; using ESRI.ArcGIS.Geometry ; namespace AoTest { /// <summary> /// 使用本物件可在地圖上進行距離、面積、角度測量 /// 可取得當前線段長度、線段總長度、多邊形面積、當前線段方位角、當前線段與前一線段夾角 /// 使用時需設定Map變數 /// </summary> public class SurveyTools { private IMap m_pMap; //地圖物件 private IPointCollection m_pPnts; //點集合 private INewPolygonFeedback m_pPolygonFeedback; //新建多邊形物件 private INewLineFeedback m_pLineFeedback; //新建線物件 private int m_iSurveyType; //0-空操作;1-測距離; 2-測面積; 3-測角度 private bool m_bBusy ; //是否正在測量 private double m_dTotalLength =0 ; //線總長度 private double m_dCurrentLength =0 ; //當前線段長度 private double m_dArea = 0 ; //多邊形面積 private double m_dAngle = 0; //當前線段與前一線段的夾角 private double m_dDirection = 0; //與正北方向的夾角,即方位角 /// <summary> /// Map物件,只寫 /// </summary> public IMap Map { set { m_pMap = value; } } /// <summary> /// 判斷是否正在測量,只讀 /// </summary> public bool IsSurveying { get { return m_bBusy; } } /// <summary> /// 折線總長度,只讀 /// </summary> public double totalLength { get { return m_dTotalLength ; } } /// <summary> /// 當前線段長度,只讀 /// </summary> public double currentLength { get { return m_dCurrentLength ; } } /// <summary> /// 多邊形面積,只讀 /// </summary> public double Area { get { return m_dArea ; } } /// <summary> /// 當前線段與前一線段的夾角,只讀 /// </summary> public double Angle { get { return m_dAngle; } } /// <summary> /// 當前線段的方向角,只讀 /// </summary> public double Direction { get { return m_dDirection; } } /// <summary> /// 建構函式 /// </summary> public SurveyTools() { m_pMap = null; m_pPnts = null; m_pPolygonFeedback = null ; m_pLineFeedback = null; m_iSurveyType = 0; m_bBusy = false ; } /// <summary> /// 啟動距離測量,pPnt為測量起點,測量結果為 /// totalLength:線總長度 /// currentLength:當前線段長度 /// 在Map的MouseDown事件中呼叫本方法 /// </summary> /// <param name="pPnt">測量起點</param> public void LengthStart(IPoint pPnt) { m_iSurveyType = 1; m_pLineFeedback = new NewLineFeedbackClass(); m_pLineFeedback.Display =((IActiveView) m_pMap).ScreenDisplay; m_pLineFeedback.Start(pPnt); m_bBusy = true; m_pPnts= new PolylineClass() ; object ep = System.Reflection.Missing.Value; m_pPnts.AddPoint(pPnt,ref ep, ref ep) ; } /// <summary> /// 啟動面積測量,pPnt為多邊形起點,測量結果為 /// Area:多邊形面積 /// 在Map的MouseDown事件中呼叫本方法 /// </summary> /// <param name="pPnt">測量起點</param> public void AreaStart(IPoint pPnt) { m_iSurveyType = 2; m_pPolygonFeedback = new NewPolygonFeedbackClass(); m_pPolygonFeedback.Display =((IActiveView) m_pMap).ScreenDisplay; m_pPolygonFeedback.Start(pPnt); m_bBusy = true ; m_pPnts= new PolygonClass() ; object ep = System.Reflection.Missing.Value; m_pPnts.AddPoint(pPnt,ref ep, ref ep) ; } /// <summary> /// 開始測角度,pPnt為折線起點,測量結果為 /// Direction:當前線段的方向角,即與正北方向的夾角 /// Angle:當前線段與前一線段的夾角 /// 在Map的MouseDown事件中呼叫本方法 /// </summary> /// <param name="pPnt">折線起點</param> public void AngleStart(IPoint pPnt) { m_iSurveyType = 3; m_pLineFeedback = new NewLineFeedbackClass(); m_pLineFeedback.Display =((IActiveView) m_pMap).ScreenDisplay; m_pLineFeedback.Start(pPnt); m_bBusy = true ; m_pPnts= new PolylineClass() ; object ep = System.Reflection.Missing.Value; m_pPnts.AddPoint(pPnt,ref ep, ref ep) ; } /// <summary> /// 向折線或多邊形上新增節點 /// 在Map的MouseDown事件中呼叫本方法,將當前游標位置作為節點 /// 新增到折線或多邊形上 /// </summary> /// <param name="pPnt">拐點</param> public void AddPoint(IPoint pPnt) { if (m_iSurveyType == 1 || m_iSurveyType == 3) { m_pLineFeedback.AddPoint(pPnt); } else if (m_iSurveyType == 2) { m_pPolygonFeedback.AddPoint(pPnt); } object ep = System.Reflection.Missing.Value; m_pPnts.AddPoint(pPnt,ref ep, ref ep) ; } /// <summary> /// 移動滑鼠位置,動態改變折線或多邊形最後節點的位置, /// 重新計算各個測量值,建議在Map的MouseMove事件中呼叫, /// 並提取當前的測量結果進行顯示 /// </summary> /// <param name="pPnt">終點</param> public void MoveTo(IPoint pPnt) { if (m_iSurveyType == 1 || m_iSurveyType == 3) { m_pLineFeedback.MoveTo(pPnt) ; CalculateLength(pPnt); CalculateDirection(pPnt); CalculateAngle(pPnt); } else if (m_iSurveyType == 2) { m_pPolygonFeedback.MoveTo(pPnt); CalculateArea( pPnt); } } /// <summary> /// 結束當前的測量,返回進行量算時在地圖上繪的圖形物件 /// 建議在Map的DoubleClick事件或MouseDown(右鍵)事件中呼叫本方法 /// 將返回物件用map.DrawShape方法繪在地圖臨時層上 /// </summary> /// <param name="pPnt">終點</param> /// <returns>地圖上繪的圖形物件</returns> public IGeometry SurveyEnd(IPoint pPnt) { IGeometry pGeometry =null; if (m_iSurveyType == 1 || m_iSurveyType == 3) { m_pLineFeedback.AddPoint(pPnt) ; pGeometry = (IGeometry) m_pLineFeedback.Stop(); m_pLineFeedback = null; } else if (m_iSurveyType == 2) { m_pPolygonFeedback.AddPoint(pPnt); pGeometry = (IGeometry) m_pPolygonFeedback.Stop(); m_pPolygonFeedback = null; } m_pPnts = null; m_bBusy = false; if (pGeometry != null) return pGeometry; else return null; } /// <summary> /// 計算測量線段長度,結果分別存貯在: /// totalLength:線總長度 /// currentLength:當前線段長度 /// </summary> /// <param name="pPnt">計算時的終點</param> private void CalculateLength(IPoint pPnt) { try { IPointCollection pPs = new PolylineClass() ; double dL = 0; pPs.AddPointCollection(m_pPnts); IPolyline pLine ; if (pPs.PointCount > 1 ) { pLine = (IPolyline) pPs; dL = pLine.Length ; } object ep = System.Reflection.Missing.Value; pPs.AddPoint(pPnt,ref ep, ref ep) ; pLine = (IPolyline) pPs; m_dTotalLength = pLine.Length ; m_dCurrentLength = m_dTotalLength - dL; } catch(System.Exception e) { Console.WriteLine(e.Message.ToString()); } } /// <summary> /// 計算多邊形面積,結果存貯在Area中 /// </summary> /// <param name="pPnt">計算時的終點</param> private void CalculateArea(IPoint pPnt) { try { IPointCollection pPs = new PolygonClass() ; pPs.AddPointCollection(m_pPnts); object ep = System.Reflection.Missing.Value; pPs.AddPoint(pPnt,ref ep, ref ep) ; if (pPs.PointCount > 2 ) { IPolygon pPolygon =(IPolygon) pPs; IArea pArea = (IArea) pPolygon; m_dArea = pArea.Area; m_dArea = System.Math.Abs(m_dArea); } } catch(System.Exception e) { Console.WriteLine(e.Message.ToString()); } } /// <summary> /// 計算當前線段的方向角,結果存貯為Direction中 /// 正北方向為0度,順時針為正,值域為0--360度 /// </summary> /// <param name="pPnt">計算時的終點</param> private void CalculateDirection(IPoint pPnt) { double dx, dy, da; IPoint p1, p2; p1 = m_pPnts.get_Point(m_pPnts.PointCount - 1 ); p2 = pPnt ; dx = p2.X - p1.X ; dy = p2.Y - p1.Y ; if (dx == 0) { if (dy >0 ) { m_dDirection =0; } else { m_dDirection = 180; } } else if (dx > 0) { if (dy==0) { m_dDirection=90; } else if( dy > 0) { da = System.Math.Abs(dx/dy); m_dDirection = System.Math.Atan(da) * 180 / 3.14159265 ; } else if (dy < 0 ) { da = System.Math.Abs(dx/dy); m_dDirection = System.Math.Atan(da) * 180 / 3.14159265 ; m_dDirection = 180 -m_dDirection; } } else { if (dy==0) { m_dDirection=270; } else if (dy >= 0) { da = System.Math.Abs(dx/dy); m_dDirection = System.Math.Atan(da) * 180 / 3.14159265 ; m_dDirection = 360 - m_dDirection; } else { da = System.Math.Abs(dx/dy); m_dDirection = System.Math.Atan(da) * 180 / 3.14159265 ; m_dDirection = 180 + m_dDirection; } } } /// <summary> /// 計算當前線段與前一線段的夾角,結果存貯為Angle中 /// 演算法採用餘弦定理,結果值域為0--180度. /// </summary> /// <param name="pPnt">計算時的終點</param> private void CalculateAngle(IPoint pPnt) { int iCount = m_pPnts.PointCount ; if (iCount < 2) return ; double a, aa, b, bb, cc; IPoint Pnt1, Pnt2, Pnt3; try { Pnt1 = pPnt; Pnt2 = m_pPnts.get_Point(iCount -1); Pnt3 = m_pPnts.get_Point(iCount -2); aa = (Pnt1.X -Pnt2.X ) * (Pnt1.X -Pnt2.X ) + (Pnt1.Y -Pnt2.Y ) * (Pnt1.Y -Pnt2.Y ); a = Math.Sqrt(aa); bb = (Pnt3.X -Pnt2.X ) * (Pnt3.X -Pnt2.X ) + (Pnt3.Y -Pnt2.Y ) * (Pnt3.Y -Pnt2.Y ); b = Math.Sqrt(bb); cc = (Pnt1.X -Pnt3.X ) * (Pnt1.X -Pnt3.X ) + (Pnt1.Y -Pnt3.Y ) * (Pnt1.Y -Pnt3.Y ); m_dAngle = Math.Acos((aa+bb-cc)/2/a/b) * 180 /3.14159265; } catch(Exception e) { Console.WriteLine(e.Message.ToString()); } } } }