using KGIS.Framework.Commands; using Kingo.Plugin.MapView.Views; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using KGIS.Framework.Platform; using ESRI.ArcGIS.ADF.BaseClasses; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Geodatabase; using Kingo.Plugin.MapView.Views.MeasurementUi; using KGIS.Framework.Utils.Helper; using ESRI.ArcGIS.esriSystem; using KGIS.Framework.Utils.ExtensionMethod; using KGIS.Framework.Utils; using KGIS.Framework.Maps; using KGIS.Framework.EngineEditor; namespace Kingo.Plugin.MapView.Commands { public class MeasurementToolClass : BaseToolCmd { private INewLineFeedback pNewLineFeedback;//追踪线对象 private INewPolygonFeedback pNewPolygonFeedback;//追踪面对象 private IPoint pPointPt = null;//鼠标点击点 private IPoint pMovePt = null;//鼠标移动时的当前点 private double dToltalLength = 0;//测量总长度 private IPointCollection pAreaPointCol = new MultipointClass();//对面积测量时所画的点进行存储 private string sMapUnits = "";//地图单位变量 private double dSegmentLength = 0;//片段距离 private double dSumLength = 0;//保存所有距离 private IHookHelper m_hookHelper;//获取地图控件和主窗体 private object missing = Type.Missing; private int pMouseOperate = 0; private double DsumLength = 0; private INewEnvelopeFeedback m_NewPolygonFeedback; MeasurementUi main; IArea pArea; IPolygon pPolygon; private bool bDoubleClickMark = false;//双击是否要起作用标记(true有效 false已无效) /// /// 鼠标点击事件 /// /// /// /// /// private List iPoitns = new List(); /// /// 测量地图中距离与面积 /// public MeasurementToolClass() { base.m_caption = "测量"; base.m_toolTip = "左键点击开始测量,双击结束测量"; base.m_cursor = System.Windows.Forms.Cursors.Cross; } public override void OnClick() { try { if (m_hookHelper != null) { this.m_NewPolygonFeedback = new NewEnvelopeFeedback() { Display = (m_hookHelper.FocusMap as IActiveView).ScreenDisplay }; if (main != null) return; main = new MeasurementUi(); main.Closed += Main_Closed; main.Width = 300; main.Height = 200; main.WindowStartupLocation = System.Windows.WindowStartupLocation.Manual; main.Left = 240; main.Top = 110; main.ActionsUpda = ActionUpdate; main.ShowInMainWindow(false); } else { MessageHelper.Show("hookHelper获取失败"); //return; } } catch (Exception ex) { //LogAPI.Debug("测量异常:" + ex); LogAPI.Debug("点击 测量工具 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("点击 测量工具 时异常信息结束"); } } public override void OnCreate(object Hook) { try { base.OnCreate(Hook); if (m_hookHelper == null) { m_hookHelper = new HookHelper(); m_hookHelper.Hook = Hook; } } catch (Exception ex) { //LogAPI.Debug("测量异常!" + en.Message); LogAPI.Debug("初始化 测量工具 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("初始化 测量工具 时异常信息结束"); } } /// /// 鼠标双击事件 /// public override void OnDblClick() { bDoubleClickMark = true; if (pMouseOperate == 0) { if (pNewLineFeedback == null) { return; } DeletePoint(); } else if (pMouseOperate == 1) { if (pNewPolygonFeedback == null) { return; } DeletePolyg(); } else if (pMouseOperate == 2) { } } /// /// 释放控件 /// /// public override bool Deactivate() { if (main != null) { main.Close(); } base.Deactivate(); this.m_deactivate = true; return this.m_deactivate; } private void Main_Closed(object sender, EventArgs e) { if (main != null) { main.Closed -= Main_Closed; } sMapUnits = ""; dSegmentLength = 0; dToltalLength = 0; pPointPt = null;//鼠标点击点 pMovePt = null;//鼠标移动时的当前点 this.EndFeedback(); this.EndArcFeedback(); this.EndTraceFeedback(); } /// /// 测量线 /// /// 0:测量长度 1:测量面积 其他:关闭测量工具 //[LogWrite(Description = "")] public void ActionUpdate(int ss) { try { pMouseOperate = ss; if (ss == 0) { DeletePolyg(); } else if (ss == 1) { DeletePoint(); } else if (ss == 2) { DeletePoint(); } else { pMouseOperate = 0; main = null; DeletePolyg(); DeletePoint(); } } catch (Exception ex) { //LogAPI.Debug(e.Message); LogAPI.Debug("使用测量工具期间 测量线 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("使用测量工具期间 测量线 时异常信息结束"); } } //[LogWrite(Description = "")] public override void OnMouseDown(int Button, int Shift, int X, int Y) { try { if (main == null || Button == 4) return; //通过鼠标点击的位置获取地图中XY轴坐标 //以数据视图的坐标系为标准获取点 #region 捕捉 this.m_pPointCatched = (this.m_hookHelper.FocusMap as IActiveView).ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y); if (this.m_pSnappingEnv != null && this.m_pSnappingEnv.Enabled) { ISnappingResult snappingResult = this.m_pPntSnapper.Snap(this.m_pPointCatched); this.m_pSnappingFeedback.Update(snappingResult, 0); if (snappingResult != null) { this.m_pPointCatched = snappingResult.Location; } } #endregion pPointPt = this.m_pPointCatched; if (pMouseOperate == 0) { //判断追踪线对象是否为空,若是则实例化并设置当前鼠标点为起始点 if (pNewLineFeedback == null) { //实例化追踪线对象 pNewLineFeedback = new NewLineFeedbackClass(); pNewLineFeedback.Display = (m_hookHelper.FocusMap as IActiveView).ScreenDisplay; //设置起点,开始动态线绘制 pNewLineFeedback.Start(pPointPt); dToltalLength = 0; } else //如果追踪线对象不为空,则添加当前鼠标点 { pNewLineFeedback.AddPoint(pPointPt); } if (dSegmentLength != 0) { dToltalLength = dToltalLength + dSegmentLength; dSumLength = dSumLength + dSegmentLength; } } else if (pMouseOperate == 1) { if (pNewPolygonFeedback == null) { //实例化追踪面对象 pNewPolygonFeedback = new NewPolygonFeedback(); pNewPolygonFeedback.Display = (m_hookHelper.FocusMap as IActiveView).ScreenDisplay; // pAreaPointCol.RemovePoints(0, pAreaPointCol.PointCount); //开始绘制多边形 pNewPolygonFeedback.Start(pPointPt); pAreaPointCol.AddPoint(pPointPt, ref missing, ref missing); } else { pNewPolygonFeedback.AddPoint(pPointPt); pAreaPointCol.AddPoint(pPointPt, ref missing, ref missing); } iPoitns.Add(pPointPt); } else if (pMouseOperate == 2) { pPointPt = (this.m_hookHelper.FocusMap as IActiveView).ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y); if (m_NewPolygonFeedback != null) { m_NewPolygonFeedback.Start(pPointPt); } } //KGIS.Common.Utility.CustomOperationLogAPICustomOperationLogAPI.InsertDatalogResLog("测量操作", "测量操作完成!"); } catch (Exception ex) { //LogAPI.Debug("测量异常!" + en.Message); LogAPI.Debug("使用测量工具期间 鼠标点击 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("使用测量工具期间 鼠标点击 时异常信息结束"); } } /// /// 清空线对象 /// private void DeletePoint() { try { if (pNewLineFeedback != null) { pNewLineFeedback.Stop(); pNewLineFeedback = null; //清空所画的线对象 (m_hookHelper.FocusMap as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null); } if (main != null) { sMapUnits = ""; dSegmentLength = 0; dToltalLength = 0; pPointPt = null;//鼠标点击点 pMovePt = null;//鼠标移动时的当前点 } // main.Txt_Segment.Text = String.Format("{0}{1}", dSegmentLength, sMapUnits); //main.Txt_Length.Text = String.Format("{0}{1}", dToltalLength, sMapUnits); } catch (Exception ex) { //LogAPI.Debug("测量异常!" + en.Message); LogAPI.Debug("使用测量工具期间 清空 线对象 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("使用测量工具期间 清空 线对象 时异常信息结束"); } } /// /// 清空面对象 /// //[LogWrite(Description = "")] private void DeletePolyg() { try { if (pNewPolygonFeedback != null) { pNewPolygonFeedback.Stop(); pNewPolygonFeedback = null; //清空所画的线对象 (m_hookHelper.FocusMap as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null); } pPointPt = null;//鼠标点击点 pMovePt = null;//鼠标移动时的当前点 pAreaPointCol.RemovePoints(0, pAreaPointCol.PointCount);//清空点集中的所有点 DsumLength = 0; pArea = null; pPolygon = null; sMapUnits = ""; // main.Txt_AreaSegment.Text = String.Format("{0}{1}", 0, sMapUnits); //main.Txt_SumArea.Text = String.Format("{0}{1}", 0, sMapUnits); // main.Txt_AreaLength.Text = String.Format("{0}{1}", 0, sMapUnits); } catch (Exception ex) { //LogAPI.Debug("测量异常!" + en.Message); LogAPI.Debug("使用测量工具期间 清空 面对象 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("使用测量工具期间 清空 面对象 时异常信息结束"); } } /// /// 鼠标移动事件 /// /// /// /// /// public override void OnMouseMove(int Button, int Shift, int X, int Y) { try { //鼠标移动的位置 #region 捕捉 this.m_pPointCatched = (this.m_hookHelper.FocusMap as IActiveView).ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y); if (this.m_pSnappingEnv != null && this.m_pSnappingEnv.Enabled) { ISnappingResult snappingResult = this.m_pPntSnapper.Snap(this.m_pPointCatched); this.m_pSnappingFeedback.Update(snappingResult, 0); if (snappingResult != null) { this.m_pPointCatched = snappingResult.Location; } } #endregion pMovePt = this.m_pPointCatched; //pMouseOperate=0则测量周长 if (pMouseOperate == 0) { if (pNewLineFeedback == null) { return; } if (pNewLineFeedback != null) { pNewLineFeedback.MoveTo(pMovePt); } //double deltaX = 0; //两点之间X差值 //double deltaY = 0; //两点之间Y差值 if ((pPointPt != null) && (pNewLineFeedback != null)) { IPointCollection pNewLineFeedbackLike = new Polyline(); pNewLineFeedbackLike.AddPoint(pMovePt); pNewLineFeedbackLike.AddPoint(pPointPt); dSegmentLength = (pNewLineFeedbackLike as IPolyline).Length; dToltalLength = dToltalLength + dSegmentLength; if (main != null) { double dToLength = Math.Round(dToltalLength, 6, MidpointRounding.AwayFromZero); //解决在地图上绘制草图功能错误 if (bDoubleClickMark == true) { dToLength = 0; bDoubleClickMark = false; } sMapUnits = "米"; if (dToLength > 1000) { sMapUnits = "千米"; dToLength = Math.Round((dToLength / 1000).ToDouble(), 6); } main.Txt_Length.Text = String.Format("{0}{1}", dToLength, sMapUnits); dToltalLength = dToltalLength - dSegmentLength; //鼠标移动到新点重新开始计算 } } } else { if (m_NewPolygonFeedback != null) { m_NewPolygonFeedback.MoveTo(pMovePt); } //pMouseOperate!=0则测量面积 if (pNewPolygonFeedback == null) { return; } if (pNewPolygonFeedback != null) { pNewPolygonFeedback.MoveTo(pMovePt); } IPointCollection pPointCol = new Polygon(); //对面积测量时所画的点进行存储 pPolygon = new PolygonClass(); IGeometry pGeo = null;//创建几何对象 ITopologicalOperator pTopo = null;//包含拓扑关系运算功能 for (int i = 0; i <= pAreaPointCol.PointCount - 1; i++) { pPointCol.AddPoint(pAreaPointCol.get_Point(i), ref missing, ref missing); } pPointCol.AddPoint(pMovePt, ref missing, ref missing); if (pPointPt != null) { //向pNewLineFeedbackLike中添加两个点组成一条线 IPointCollection pNewLineFeedbackLike = new Polyline(); pNewLineFeedbackLike.AddPoint(pMovePt); pNewLineFeedbackLike.AddPoint(pPointPt); DsumLength = (pNewLineFeedbackLike as IPolyline).Length; } // main.Txt_AreaSegment.Text = String.Format("{0}{1}", Math.Round(DsumLength, 3), sMapUnits); if (pPointCol.PointCount < 3) return; pPolygon = pPointCol as IPolygon; if ((pPolygon != null)) { pPolygon.Close(); pGeo = pPolygon as IGeometry; pTopo = pGeo as ITopologicalOperator; //使几何图形的拓扑正确 pTopo.Simplify(); //拓扑操作的空间引用设置为数据视图的空间引用 pGeo.Project(m_hookHelper.FocusMap.SpatialReference); pArea = pGeo as IArea;//面积量算所画的面 Double dobuleArea = Math.Round((pArea.Area).ToDouble(), 3); //解决在地图上绘制草图功能错误 if (bDoubleClickMark == true) { dobuleArea = 0; bDoubleClickMark = false; } sMapUnits = "平方米"; if (dobuleArea > 10000) { dobuleArea = Math.Round((dobuleArea / 10000).ToDouble(), 6); sMapUnits = "公顷"; } if (dobuleArea > 1000000) { dobuleArea = Math.Round((dobuleArea / 1000000).ToDouble(), 6); sMapUnits = "平方千米"; } main.Txt_SumArea.Text = String.Format("{0}{1}", dobuleArea, sMapUnits); // main.Txt_AreaLength.Text = String.Format("{0}{1}", Math.Round(pPolygon.Length, 3), sMapUnits); pPolygon = null; } } } catch (Exception ex) { //LogAPI.Debug("测量异常!" + en.Message); LogAPI.Debug("使用测量工具期间 调用鼠标移动事件 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("使用测量工具期间 调用鼠标移动事件 时异常信息结束"); } } public override void OnMouseUp(int Button, int Shift, int X, int Y) { try { if (pMouseOperate != 2) { return; } IGeometry pGeotry = m_NewPolygonFeedback.Stop(); //IPoint currentPoint = m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y); List layers = MapsManager.Instance.MapService.GetAllVisibleLayerInMap(); List features = Identify(pGeotry, layers); if (features != null && features.Count >= 1) { pArea = features[0].Shape as IArea;//面积量算所画的面 if (pArea != null) { Double dobuleArea = Math.Round((pArea.Area).ToDouble(), 3); //解决在地图上绘制草图功能错误 if (bDoubleClickMark == true) { dobuleArea = 0; bDoubleClickMark = false; } for (int i = 1; i < features.Count; i++) { dobuleArea += Math.Round(((features[i].Shape as IArea).Area).ToDouble(), 3); } sMapUnits = "平方米"; if (dobuleArea > 10000) { dobuleArea = Math.Round((dobuleArea / 10000).ToDouble(), 6); sMapUnits = "公顷"; } if (dobuleArea > 1000000) { dobuleArea = Math.Round((dobuleArea / 1000000).ToDouble(), 6); sMapUnits = "平方千米"; } this.main.Grid_Area.Visibility = System.Windows.Visibility.Visible; this.main.Grid_Length.Visibility = System.Windows.Visibility.Collapsed; main.Txt_SumArea.Text = String.Format("{0}{1}", dobuleArea, sMapUnits); } else if ((features[0].Shape as IPolyline) != null) { double dToLength = Math.Round((features[0].Shape as IPolyline).Length, 6); //解决在地图上绘制草图功能错误 if (bDoubleClickMark == true) { dToLength = 0; bDoubleClickMark = false; } for (int i = 1; i < features.Count; i++) { dToLength += (features[i].Shape as IPolyline).Length; } sMapUnits = "米"; if (dToLength > 1000) { sMapUnits = "千米"; dToLength = Math.Round((dToLength / 1000).ToDouble(), 6); } this.main.Grid_Area.Visibility = System.Windows.Visibility.Collapsed; this.main.Grid_Length.Visibility = System.Windows.Visibility.Visible; main.Txt_Length.Text = String.Format("{0}{1}", dToLength, sMapUnits); } else { main.Txt_SumArea.Text = ""; main.Txt_Length.Text = ""; } } else { main.Txt_SumArea.Text = ""; main.Txt_Length.Text = ""; } } catch (Exception ex) { //Common.Utility.LogAPI.Debug(ex); LogAPI.Debug("使用测量工具期间 鼠标抬起 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("使用测量工具期间 鼠标抬起 时异常信息结束"); } base.OnMouseUp(Button, Shift, X, Y); } public override bool Enabled { get { return true; } } /// /// 根据图形捕捉要素 /// /// /// /// public List Identify(IGeometry pGeo, List pLayers, int buffer = 5) { List result = new List(); ESRI.ArcGIS.esriSystem.IArray arrayFlush = new ESRI.ArcGIS.esriSystem.ArrayClass(); try { if (pGeo != null && !pGeo.IsEmpty && pLayers != null) { foreach (IFeatureLayer item in pLayers) { IIdentify identify = item as IIdentify; if (identify == null) continue; //ITopologicalOperator pTopo = pGeo as ITopologicalOperator; //IGeometry pGeometry = pTopo.Buffer(buffer).Envelope as IGeometry; ESRI.ArcGIS.esriSystem.IArray array = identify.Identify(pGeo); if (array == null) continue; for (int i = 0; i < array.Count; i++) { IRowIdentifyObject row = (IRowIdentifyObject)array.get_Element(i); if (row == null) continue; IFeature f = row.Row as IFeature; result.Add(f); arrayFlush.Add(f.ShapeCopy); } if (arrayFlush.Count > 0) { FlashShapeArray(m_hookHelper, arrayFlush); } break; } } } catch (Exception ex) { LogAPI.Debug("使用测量工具期间 根据图形捕捉要素 时异常,异常信息如下:"); LogAPI.Debug(ex); LogAPI.Debug("使用测量工具期间 根据图形捕捉要素 时异常信息结束"); throw ex; } return result; } /// /// 通过IHookActions闪烁要素集合 /// /// /// public static void FlashShapeArray(IHookHelper m_hookHelper, IArray geoArray) { IHookActions hookActions = (IHookActions)m_hookHelper; //hookActions.DoActionOnMultiple(geoArray, esriHookActions.esriHookActionsPan); //hookActions.DoActionOnMultiple(geoArray, esriHookActions.esriHookActionsGraphic); //hookActions.DoActionOnMultiple(geoArray, esriHookActions.esriHookActionsZoom); System.Windows.Forms.Application.DoEvents(); //m_hookHelper.ActiveView.ScreenDisplay.UpdateWindow(); hookActions.DoActionOnMultiple(geoArray, esriHookActions.esriHookActionsFlash); } } }