using System; using System.Collections.Generic; using System.Linq; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using KGIS.Framework.AE; using KGIS.Framework.Utils; using KGIS.Framework.Utils.Enum; namespace Kingo.Plugin.EngineEditor.Commands.Tools { public class ControlsEditingTrackTool : BaseToolCommand { private IHookHelper m_hookHelper; private EngineEditorClass m_editor = new EngineEditorClass(); /// /// 画笔 /// public IEngineEditSketch editSketch { get { return m_editor as IEngineEditSketch; } } /// /// 当前显示的图层 /// private List VisibleLayers { get; set; } private IPointCollection linePoint = new PolylineClass() as IPointCollection; private IPointCollection LinePath { get { //IPointCollection temp = editSketch.Geometry as IPointCollection; if (linePoint.PointCount > 0) { linePoint.RemovePoints(0, linePoint.PointCount); } if (editSketch.GeometryType == esriGeometryType.esriGeometryPolygon) { ITopologicalOperator topo = editSketch.Geometry as ITopologicalOperator; linePoint = topo.Boundary as IPointCollection; if (linePoint.PointCount > 1) { linePoint.RemovePoints(linePoint.PointCount - 1, 1); } RemovePointStartIndex = 2; } else if (editSketch.GeometryType == esriGeometryType.esriGeometryPolyline) { linePoint = editSketch.Geometry as IPointCollection; RemovePointStartIndex = 1; } return linePoint; } } //private IPointCollection LinePath = new PolylineClass() as IPointCollection; /// /// 捕捉对象 /// private IEngineSnapEnvironment snapEnv = null; /// /// 捕捉的点 /// private IPoint snapPoint = null; int RemovePointStartIndex = 1; public override void OnCreate(object hook) { try { base.OnCreate(hook); if (m_hookHelper == null) { m_hookHelper = new HookHelperClass() { Hook = hook }; } if (m_editor == null) { m_editor = new EngineEditorClass(); } if (snapEnv == null) { snapEnv = (IEngineSnapEnvironment)m_editor; } } catch (Exception ex) { LogAPI.Debug("追踪工具OnCreate初始化异常:" + ex.Message); } } bool IsTracking = false; public override void OnClick() { try { this.OnCreate(base.hook); base.OnClick(); if (VisibleLayers == null) { VisibleLayers = new List(); } VisibleLayers.Clear(); VisibleLayers = KGIS.Framework.Maps.MapsManager.Instance.MapService.GetAllVisibleLayerInMap(); //VisibleLayers.Add(m_editor.TargetLayer as IFeatureLayer); lines.Clear(); snapLine = new KeyValuePair(); PreviousSnapLine = new KeyValuePair(); } catch (Exception ex) { LogAPI.Debug("追踪工具OnClick异常:" + ex.Message); } } public override void OnMouseDown(int button, int shift, int x, int y) { try { base.OnMouseDown(button, shift, x, y); if (IsTracking == false) { IPoint point = this.m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y); if (editSketch.Geometry == null || editSketch.Geometry.IsEmpty) { if (snapEnv != null) { this.SnapPoint(m_hookHelper.ActiveView, point, snapEnv); snapPoint = point; } if (snapPoint != null) { editSketch.AddPoint(snapPoint, false); editSketch.ModifySketch(); editSketch.RefreshSketch(); } } IsTracking = true; } else { if (snapPoint != null) { editSketch.AddPoint(snapPoint, false); editSketch.ModifySketch(); editSketch.RefreshSketch(); } IsTracking = false; } } catch (Exception ex) { LogAPI.Debug("追踪工具OnMouseDown异常:" + ex.Message); } } //private IPolyline snapLine = null; List intersectPoints = new List(); /// /// 捕捉到的所有线段集合 /// //List lines = new List(); Dictionary lines = new Dictionary(); KeyValuePair snapLine = new KeyValuePair(); KeyValuePair PreviousSnapLine = new KeyValuePair(); public override void OnMouseMove(int button, int shift, int x, int y) { try { base.OnMouseMove(button, shift, x, y); IPoint point = this.m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y); if (LinePath.PointCount == 0 || !IsTracking) { return; } int index = LinePath.PointCount - 1; if (lines.Count == 0) { //获取当前点所捕捉到的要素 lines = GeneratePolyline(snapPoint); } IPoint nearesPoint = null; //鼠标点距离线段的最短距离 double d = -1; foreach (int item in lines.Keys) { IProximityOperator operatorPr = lines[item] as IProximityOperator; IPoint TempNearesPoint = operatorPr.ReturnNearestPoint(point, esriSegmentExtension.esriNoExtension); double temp_D = operatorPr.ReturnDistance(point); if (d == -1 || d > temp_D) { d = temp_D; snapLine = new KeyValuePair(item, lines[item]); nearesPoint = TempNearesPoint; } } if (PreviousSnapLine.Value == null) { PreviousSnapLine = snapLine; } if (nearesPoint == null || snapLine.Value == null) { return; } ITopologicalOperator topo = snapLine.Value as ITopologicalOperator; topo.Simplify(); IGeometry geo = topo.Intersect(nearesPoint, esriGeometryDimension.esriGeometry0Dimension); if (geo == null || geo.IsEmpty) { //Bug-12973 霍岩 2018-11-09 频繁释放ITopologicalOperator, IGeometry等对象导致COM与RCW分离异常 //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(topo); //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(geo); snapLine = new KeyValuePair(); return; } if (snapEnv != null) { this.SnapPoint(m_hookHelper.ActiveView, nearesPoint, snapEnv); snapPoint = nearesPoint; } if (LinePath.PointCount < 1) { return; } bool IsVPoint = false; if (IsCheckPointInLine(snapPoint, PreviousSnapLine.Value, ref IsVPoint) || PreviousSnapLine.Key == snapLine.Key) { index = LinePath.PointCount - 1; if (GetSubCurveAddEdit(PreviousSnapLine.Value, LinePath.get_Point(index), snapPoint)) { PreviousSnapLine = snapLine; } else { //重新获取追踪线对象 lines = GeneratePolyline(snapPoint); } } else { lines = GeneratePolyline(snapPoint); //判断前后追踪的两条线是否存在交点 ITopologicalOperator tempTopo = PreviousSnapLine.Value as ITopologicalOperator; tempTopo.Simplify(); IGeometry tempIpoint = tempTopo.Intersect(snapLine.Value, esriGeometryDimension.esriGeometry0Dimension); if (tempIpoint != null && !tempIpoint.IsEmpty) { index = LinePath.PointCount - 1; GetSubCurveAddEdit(PreviousSnapLine.Value, LinePath.get_Point(index), (tempIpoint as IPointCollection).get_Point(0)); PreviousSnapLine = snapLine; //Bug-12973 霍岩 2018-11-09 频繁释放ITopologicalOperator, IGeometry等对象导致COM与RCW分离异常 //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(tempIpoint); //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(tempTopo); } } } catch (Exception ex) { LogAPI.Debug("追踪工具OnMouseMove异常:" + ex.Message); } } /// /// 获取指定线上两点之间的线段,并添加到当前编辑对象中 /// /// 指定的线 /// 点1 /// 点2 /// 如果未获取到线段则返回false public bool GetSubCurveAddEdit(IPolyline line, IPoint point1, IPoint point2) { bool result = false; IPolyline templine = null; IGeometry interLine = null; IPointCollection ps = null; ITopologicalOperator2 temptopo = null; try { templine = GetSubCurve(line, point1, point2);//GetSubCurve if (templine.IsEmpty || templine.Length == 0) { result = false; return result; } temptopo = templine as ITopologicalOperator2; temptopo.Simplify(); interLine = temptopo.Intersect(LinePath as IPolyline, esriGeometryDimension.esriGeometry1Dimension); if (interLine == null || interLine.IsEmpty) { ps = templine as IPointCollection; if (Math.Round(templine.FromPoint.X, 2) == Math.Round((LinePath as IPolyline).ToPoint.X, 2) && Math.Round(templine.FromPoint.Y, 2) == Math.Round((LinePath as IPolyline).ToPoint.Y, 2)) { //判断最后一个点是否是线上的节点 if (!PointIsVertexPointForLine(templine.ToPoint, line)) { ps.RemovePoints(ps.PointCount - 1, 1); } int count = ps.PointCount; for (int i = 1; i < count; i++) { editSketch.AddPoint(ps.get_Point(i), true); editSketch.ModifySketch(); editSketch.RefreshSketch(); } } else { //判断最后一个点是否是线上的节点 if (!PointIsVertexPointForLine(templine.FromPoint, line)) { ps.RemovePoints(0, 1); } int count = ps.PointCount - 1; for (int i = count; i > 0; i--) { editSketch.AddPoint(ps.get_Point(i), true); editSketch.ModifySketch(); editSketch.RefreshSketch(); } } result = true; } else { for (int i = 0; i < (templine as IPointCollection).PointCount; i++) { if (LinePath.PointCount == 1) break; int index = LinePath.PointCount - 2; bool IsVPoint = false; if (!IsCheckPointInLine(LinePath.get_Point(index), snapLine.Value, ref IsVPoint)) { break; } (editSketch.Geometry as IPointCollection).RemovePoints((editSketch.Geometry as IPointCollection).PointCount - RemovePointStartIndex, 1); editSketch.ModifySketch(); editSketch.RefreshSketch(); } } } finally { //Bug-12973 霍岩 2018-11-09 频繁释放ITopologicalOperator, IGeometry等对象导致COM与RCW分离异常 //if (templine != null) //{ // System.Runtime.InteropServices.Marshal.FinalReleaseComObject(templine); //} //if (interLine != null) //{ // System.Runtime.InteropServices.Marshal.FinalReleaseComObject(interLine); //} //if (ps != null) //{ // System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ps); //} //if (temptopo != null) //{ // System.Runtime.InteropServices.Marshal.FinalReleaseComObject(temptopo); //} } return result; } public bool PointIsVertexPointForLine(IPoint point, IPolyline line) { bool result = false; IPointCollection points = line as IPointCollection; for (int i = 0; i < points.PointCount; i++) { if (Math.Round(point.X, 2) == Math.Round(points.get_Point(i).X, 2) && Math.Round(point.Y, 2) == Math.Round(points.get_Point(i).Y, 2)) { result = true; break; } } return result; } public override void OnDblClick() { try { snapLine = new KeyValuePair(); PreviousSnapLine = new KeyValuePair(); lines.Clear(); editSketch.FinishSketch(); base.OnDblClick(); } catch (Exception ex) { LogAPI.Debug("追踪工具OnDblClick异常:" + ex.Message); } } /// /// 判断点是否在线上 /// /// 点 /// 线 /// 是否包含端点 /// private bool IsCheckPointInLine(IPoint pPoint, IPolyline pLine, ref bool pContainEndPoint) { bool result = false; pContainEndPoint = false; try { if (pPoint != null && pLine != null) { if (!pLine.IsEmpty && !pPoint.IsEmpty) { ITopologicalOperator topo = pLine as ITopologicalOperator; //Bug-12973 霍岩 2018-11-09 在拓扑操作前使其简化 topo.Simplify(); IGeometry geo = topo.Intersect(pPoint, esriGeometryDimension.esriGeometry0Dimension); if (geo != null && !geo.IsEmpty) { IPoint p = geo as IPoint; if ((Math.Round(p.X, 2) == Math.Round(pLine.FromPoint.X, 2) && Math.Round(p.Y, 2) == Math.Round(pLine.FromPoint.Y, 2)) || (Math.Round(p.X, 2) == Math.Round(pLine.ToPoint.X, 2) && Math.Round(p.Y, 2) == Math.Round(pLine.ToPoint.Y, 2))) { result = true; pContainEndPoint = true; } else { result = true; } } } } } catch (Exception ex) { throw ex; } return result; } private IPolyline GetSubCurve(IPolyline inpolyLine, IPoint pnt1, IPoint pnt2) { double d1 = GetDistAlong(inpolyLine, pnt1); double d2 = GetDistAlong(inpolyLine, pnt2); var c = inpolyLine as ICurve; ICurve outCurve; c.GetSubcurve(d1, d2, false, out outCurve); if (c == null || c.IsEmpty) throw new Exception("aa"); var outPolyline = outCurve as IPolyline; if (outPolyline == null) { outPolyline = new PolylineClass() as IPolyline; var sc = outPolyline as ISegmentCollection; sc.AddSegment((ISegment)outCurve); ((IGeometry)sc).SpatialReference = outCurve.SpatialReference; } return outPolyline; } private double GetDistAlong(IPolyline polyLine, IPoint pnt) { var outPnt = new PointClass() as IPoint; double distAlong = double.NaN; double distFrom = double.NaN; bool bRight = false; polyLine.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, pnt, false, outPnt, ref distAlong, ref distFrom, ref bRight); return distAlong; } private IPolyline BuildLine(IPolyline pLine, IPoint p1, IPoint p2) { bool isSplit; int splitIndex, segIndex; //插入第一点,segIndex记录插入点的相对线的节点位置 pLine.SplitAtPoint(p1, true, false, out isSplit, out splitIndex, out segIndex); int fIndex = segIndex; //插入第二点 pLine.SplitAtPoint(p2, true, false, out isSplit, out splitIndex, out segIndex); int sIndex = segIndex; IPointCollection pPointCol = new PolylineClass(); //IPointCollection pPointCol2 = new PolylineClass(); object o = Type.Missing; //比较一下插入第一点和第二点的节点次序 if (fIndex > sIndex) { int temp = fIndex; fIndex = sIndex; sIndex = temp; } else if (fIndex == sIndex) { pPointCol.AddPoint(p1, ref o, ref o); pPointCol.AddPoint(p2, ref o, ref o); return pPointCol as IPolyline; } //利用两点区间,获取线上区间所在的点,并将其转换为线 IPointCollection LineCol = pLine as IPointCollection; for (int i = fIndex; i <= sIndex; i++) { pPointCol.AddPoint(LineCol.get_Point(i), ref o, ref o); } //for (int i = 0; i < LineCol.PointCount; i++) //{ // if (i < fIndex || i > sIndex) // { // pPointCol2.AddPoint(LineCol.get_Point(i), ref o, ref o); // } //} return pPointCol as IPolyline; } /// /// 生成地类界线 /// /// 地类图斑要素 /// 地类界线对应的要素类对象 /// public void GenerateDLJX(IPoint point, Dictionary lines) { Dictionary dicLine = new Dictionary(); foreach (var item in lines.Keys) { dicLine.Add(item, lines[item]); } lines.Clear(); try { if (point == null || lines == null) return; List featureList = FeatureAPI.Snapping(snapPoint, VisibleLayers, 10); foreach (IFeature item in featureList) { List polylineArray = FeatureAPI.FeatureToLine(item); if (polylineArray == null) { continue; } foreach (IGeometry line in polylineArray) { if (dicLine.Count == 0) { lines.Add(lines.Count, line as IPolyline); continue; } IGeometry OtherIntersect = null; foreach (IPolyline his_Line in dicLine.Values) { //不相交部分 IGeometry No_InterGeo = FeatureAPI.Difference(his_Line, OtherIntersect); IGeometryCollection No_InterList = No_InterGeo as IGeometryCollection; if (No_InterList != null) { for (int i = 0; i < No_InterList.GeometryCount; i++) { IGeometryCollection pPolyline = new PolylineClass(); pPolyline.AddGeometry(No_InterList.get_Geometry(i)); lines.Add(lines.Count, pPolyline as IPolyline); } } //相交部分 IGeometry intersectGeo = FeatureAPI.InterSect(line, his_Line); if (OtherIntersect == null) { OtherIntersect = intersectGeo; } else { ITopologicalOperator topo = OtherIntersect as ITopologicalOperator; if (topo != null) { topo.Simplify(); OtherIntersect = topo.Union(intersectGeo); } } IGeometryCollection intersectList = intersectGeo as IGeometryCollection; if (intersectGeo != null) { for (int i = 0; i < intersectList.GeometryCount; i++) { IGeometryCollection pPolyline = new PolylineClass(); pPolyline.AddGeometry(intersectList.get_Geometry(i)); lines.Add(lines.Count, pPolyline as IPolyline); } } } if (OtherIntersect != null) { //新生成的线与之不相交 IGeometry newGeoNoInter = FeatureAPI.Difference(line, OtherIntersect); IGeometryCollection newGeoList = newGeoNoInter as IGeometryCollection; if (newGeoList != null) { for (int i = 0; i < newGeoList.GeometryCount; i++) { IGeometryCollection pPolyline = new PolylineClass(); pPolyline.AddGeometry(newGeoList.get_Geometry(i)); lines.Add(lines.Count, pPolyline as IPolyline); } } } //lines = result.Values.ToList(); } //lines = result.Values.ToList(); //if (result.Count == 0) // result = polylineArray; } return; } catch (Exception ex) { throw ex; } } public Dictionary GeneratePolyline(IPoint point, Dictionary lines) { Dictionary result = new Dictionary(); if (point == null || lines == null) return result; try { //获取当前追踪的要素多边形 List snapFeatures = FeatureAPI.Snapping(point, VisibleLayers, 10); //List snapFeatures = new List(); //if (snapFe.Count > 0) //{ // //snapFeatures.Add(snapFe[0]); // snapFeatures.AddRange(FeatureAPI.Snapping(snapFe[0].ShapeCopy, VisibleLayers, 1)); //} if (snapFeatures == null) return result; foreach (IFeature feautre in snapFeatures) { //将多边形要素转成线要素 List featureToLines = FeatureAPI.PolygonToLine(feautre.ShapeCopy); if (featureToLines == null) continue; IPolyline tempLine = null; foreach (IGeometry f_line in featureToLines) { if (lines.Count == 0) { result.Add(result.Count, f_line as IPolyline); continue; } //将线要素与已有的线要素进行打断 foreach (IPolyline line in lines.Values) { ITopologicalOperator topo = line as ITopologicalOperator; topo.Simplify(); IPolyline new_DifLine = topo.Difference(f_line) as IPolyline; if (new_DifLine != null && !new_DifLine.IsEmpty) result.Add(result.Count, new_DifLine); IPolyline new_InterLine = topo.Intersect(f_line, esriGeometryDimension.esriGeometry1Dimension) as IPolyline; if (new_InterLine != null && !new_InterLine.IsEmpty && new_DifLine != null && !new_DifLine.IsEmpty) result.Add(result.Count, new_InterLine); } foreach (IPolyline line in lines.Values) { if (tempLine == null) tempLine = f_line as IPolyline; ITopologicalOperator topo = tempLine as ITopologicalOperator; topo.Simplify(); tempLine = topo.Difference(line) as IPolyline; if (tempLine == null || tempLine.IsEmpty) break; } if (tempLine != null && !tempLine.IsEmpty) result.Add(result.Count, tempLine); } } return result; } catch (Exception ex) { LogAPI.Debug(ex); throw ex; } } public Dictionary GeneratePolyline(IPoint point) { Dictionary result = new Dictionary(); if (point == null) return result; try { //获取当前追踪的要素多边形 List snapFeatures = FeatureAPI.Snapping(point, VisibleLayers, 10); if (snapFeatures == null) return result; foreach (IFeature feautre in snapFeatures) { //将多边形要素转成线要素 List featureToLines = FeatureAPI.PolygonToLine(feautre.ShapeCopy); if (featureToLines == null) continue; IPolyline tempLine = null; foreach (IGeometry f_line in featureToLines) { tempLine = f_line as IPolyline; List LineInsertFeature = FeatureAPI.Snapping(tempLine, VisibleLayers, 0.0001); foreach (IFeature item in LineInsertFeature) { if (item.OID == feautre.OID) continue; ITopologicalOperator topo = tempLine as ITopologicalOperator; topo.Simplify(); IPolyline newline = topo.Intersect(item.ShapeCopy, esriGeometryDimension.esriGeometry1Dimension) as IPolyline; //IPolyline obj = result.Values.FirstOrDefault(f => Math.Round(f.Length, 0) == Math.Round(newline.Length, 0)); if (newline != null && !newline.IsEmpty && result.Values.FirstOrDefault(f => Math.Round(f.Length, 0) == Math.Round(newline.Length, 0)) == null) result.Add(result.Count, newline); tempLine = topo.Difference(item.ShapeCopy) as IPolyline; } if (!tempLine.IsEmpty && result.Values.FirstOrDefault(f => Math.Round(f.Length, 0) == Math.Round(tempLine.Length, 0)) == null) result.Add(result.Count, tempLine); } } return result; } catch (Exception ex) { throw ex; } } public override bool Enabled { get { if (m_editor == null || m_editor.EditState != esriEngineEditState.esriEngineStateEditing) { return false; } return true; } } public override enumProductType AttachProductType { get { return enumProductType.KDB; } } } }