using ESRI.ArcGIS.ADF; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Geometry; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace KGIS.PlatformPlugin.Commands.Tools.TraceTool { public class TraceFeedbackExClass : IDisplayFeedback, ITraceFeedback { private IScreenDisplay m_pScreenDisplay; private ILineSymbol m_pLineSymbol; private List m_pListBeTracePolyline; private int m_nPolylineCount; private IPoint m_pPointStart; private IPoint m_pPointEnd; private IPoint m_pPointFrom; private IPolyline m_pPolylineBeTraced; private IPolyline m_pPolyline; private List m_pListPolylineBeTraced; private List m_pListPolyline; private List m_pListPointStart; private bool m_bAlongPolyline = true; private bool m_bIncludeAnchorFrom = true; private double m_dTraceTolerance; public IScreenDisplay Display { set { this.m_pScreenDisplay = value; } } public ISymbol Symbol { get { return this.m_pLineSymbol as ISymbol; } set { } } public List ListBeTracePolyline { set { this.m_pListBeTracePolyline = value; this.m_nPolylineCount = this.m_pListBeTracePolyline.Count; } } public bool IncludeAnchorFrom { set { this.m_bIncludeAnchorFrom = value; } } public TraceFeedbackExClass() { this.m_pLineSymbol = new SimpleLineSymbolClass(); this.m_pLineSymbol.Width = 2.0; (this.m_pLineSymbol as ISimpleLineSymbol).Style = esriSimpleLineStyle.esriSLSSolid; IColor color = new RgbColorClass { Red = 255, Blue = 0, Green = 0 }; this.m_pLineSymbol.Color = color; (this.m_pLineSymbol as ISymbol).ROP2 = esriRasterOpCode.esriROPNotXOrPen; this.m_pListPolylineBeTraced = new List(); this.m_pListPolyline = new List(); this.m_pListPointStart = new List(); } public void Start(IPoint pPoint, IPoint pPointFrom, IPoint pPointEnd) { if (pPoint == null || pPoint.IsEmpty) { return; } if (this.m_pPolyline != null) { ComReleaser.ReleaseCOMObject(this.m_pPolyline); } this.m_pPolyline = new PolylineClass(); this.m_pPolyline.SpatialReference = this.m_pScreenDisplay.DisplayTransformation.SpatialReference; this.m_dTraceTolerance = this.GetTraceTolerance(); double num = 10000000.0; IPolyline beTracedPolyline = this.GetBeTracedPolyline(pPoint, ref num); if (num <= this.m_dTraceTolerance) { IProximityOperator proximityOperator = beTracedPolyline as IProximityOperator; this.m_pPointStart = proximityOperator.ReturnNearestPoint(pPoint, esriSegmentExtension.esriNoExtension); this.m_pPolylineBeTraced = ((beTracedPolyline as IClone).Clone() as IPolyline); this.m_pPointFrom = pPointFrom; this.m_pPointEnd = pPointEnd; if (this.m_pPointFrom == null) { this.m_pPointFrom = this.m_pPointStart; } return; } } public void MoveTo(IPoint pPoint) { try { if (this.m_pPolylineBeTraced != null) { double num = 0.0; IPolyline beTracedPolyline = this.GetBeTracedPolyline(pPoint, this.m_pPolylineBeTraced, ref num); if (num <= this.m_dTraceTolerance) { int num2 = this.IndexOf(beTracedPolyline); if (num2 >= 0) { if (num2 + 1 == this.m_pListPolyline.Count) { ComReleaser.ReleaseCOMObject(this.m_pPolyline); ComReleaser.ReleaseCOMObject(this.m_pPolylineBeTraced); ComReleaser.ReleaseCOMObject(this.m_pPointStart); this.m_pPolyline = this.m_pListPolyline[num2]; this.m_pPolylineBeTraced = this.m_pListPolylineBeTraced[num2]; this.m_pPointStart = this.m_pListPointStart[num2]; int count = this.m_pListPolyline.Count; int num3 = num2 + 1; if (num3 < count) { for (int i = num3; i < count; i++) { ComReleaser.ReleaseCOMObject(this.m_pListPolyline[i]); ComReleaser.ReleaseCOMObject(this.m_pListPolylineBeTraced[i]); ComReleaser.ReleaseCOMObject(this.m_pListPointStart[i]); } } this.m_pListPolyline.RemoveRange(num2, count - num2); this.m_pListPolylineBeTraced.RemoveRange(num2, count - num2); this.m_pListPointStart.RemoveRange(num2, count - num2); } } else { if (beTracedPolyline != this.m_pPolylineBeTraced && this.IsTouches(this.m_pPolyline, beTracedPolyline)) { IPoint intersect = this.GetIntersect(beTracedPolyline, this.m_pPolyline); if (intersect != null) { this.m_pListPolyline.Add(this.m_pPolyline); this.m_pListPolylineBeTraced.Add(this.m_pPolylineBeTraced); this.m_pListPointStart.Add(this.m_pPointStart); this.m_pPolylineBeTraced = ((beTracedPolyline as IClone).Clone() as IPolyline); this.m_pPolyline = new PolylineClass(); this.m_pPolyline.SpatialReference = this.m_pScreenDisplay.DisplayTransformation.SpatialReference; this.m_pPointStart = intersect; } } } IProximityOperator proximityOperator = this.m_pPolylineBeTraced as IProximityOperator; IPoint point = proximityOperator.ReturnNearestPoint(pPoint, esriSegmentExtension.esriNoExtension); if (point != null && !(point as IRelationalOperator).Equals(this.m_pPointStart)) { if (this.m_pPolylineBeTraced != null && !this.m_pPolylineBeTraced.IsEmpty) { if (this.m_pPolylineBeTraced.IsClosed) { IPolyline fromCloseTraced = this.GetFromCloseTraced(this.m_pPolylineBeTraced, this.m_pPointStart, point, this.m_pPolyline); if (this.m_pPolyline != null) { this.m_pPolyline.SetEmpty(); if (fromCloseTraced != null && !fromCloseTraced.IsEmpty) { (this.m_pPolyline as ISegmentCollection).AddSegmentCollection(fromCloseTraced as ISegmentCollection); } ComReleaser.ReleaseCOMObject(fromCloseTraced); } } else { IPolyline fromNotCloseTraced = this.GetFromNotCloseTraced(this.m_pPolylineBeTraced, this.m_pPointStart, point); if (this.m_pPolyline != null) { this.m_pPolyline.SetEmpty(); if (fromNotCloseTraced != null && !fromNotCloseTraced.IsEmpty) { (this.m_pPolyline as ISegmentCollection).AddSegmentCollection(fromNotCloseTraced as ISegmentCollection); } ComReleaser.ReleaseCOMObject(fromNotCloseTraced); } } } this.Refresh(0); } } } } catch (Exception ex) { //KGIS.Framework.Utils.LogAPI.Debug(ex); } } public void Refresh(int hDC) { this.m_pScreenDisplay.StartDrawing(this.m_pScreenDisplay.hDC, -1); IPolyline polyline = null; try { polyline = new PolylineClass(); this.m_pPolyline.SpatialReference = this.m_pScreenDisplay.DisplayTransformation.SpatialReference; int count = this.m_pListPolyline.Count; for (int i = 0; i < count; i++) { (polyline as ISegmentCollection).AddSegmentCollection(this.m_pListPolyline[i] as ISegmentCollection); } if (this.m_pPolyline != null && !this.m_pPolyline.IsEmpty) { (polyline as ISegmentCollection).AddSegmentCollection(this.m_pPolyline as ISegmentCollection); } if (polyline != null && !polyline.IsEmpty) { IPointCollection pointCollection = polyline as IPointCollection; if (this.m_pPointEnd != null && !this.m_pPointEnd.IsEmpty) { pointCollection.InsertPoints(0, 1, ref this.m_pPointEnd); } if (this.m_bIncludeAnchorFrom && this.m_pPointFrom != null && !this.m_pPointFrom.IsEmpty) { IPointCollection arg_104_0 = pointCollection; IPoint arg_104_1 = this.m_pPointFrom; object value = Missing.Value; object value2 = Missing.Value; arg_104_0.AddPoint(arg_104_1, ref value, ref value2); } polyline.SimplifyNetwork(); } if (this.m_pLineSymbol != null) { this.m_pScreenDisplay.SetSymbol(this.m_pLineSymbol as ISymbol); this.m_pScreenDisplay.DrawPolyline(polyline); } } catch (Exception ex) { //KGIS.Framework.Utils.LogAPI.Debug(ex); } finally { ComReleaser.ReleaseCOMObject(polyline); } this.m_pScreenDisplay.FinishDrawing(); } public IPolyline Stop(IPoint pPoint) { if (pPoint == null) { ComReleaser.ReleaseCOMObject(this.m_pPolyline); this.m_pPolyline = null; return null; } try { IPolyline polyline = new PolylineClass(); this.m_pPolyline.SpatialReference = this.m_pScreenDisplay.DisplayTransformation.SpatialReference; int count = this.m_pListPolyline.Count; for (int i = 0; i < count; i++) { (polyline as ISegmentCollection).AddSegmentCollection(this.m_pListPolyline[i] as ISegmentCollection); } if (this.m_pPolyline != null && !this.m_pPolyline.IsEmpty) { (polyline as ISegmentCollection).AddSegmentCollection(this.m_pPolyline as ISegmentCollection); } polyline.SimplifyNetwork(); return polyline; } catch (Exception ex) { //KGIS.Framework.Utils.LogAPI.Debug(ex); } finally { ComReleaser.ReleaseCOMObject(this.m_pPolyline); this.m_pPolyline = null; foreach (IPolyline current in this.m_pListPolyline) { ComReleaser.ReleaseCOMObject(current); } this.m_pListPolyline.Clear(); } return null; } private IPolyline GetFromNotCloseTraced(IPolyline pPolyline, IPoint pPointStart, IPoint pPointEnd) { IRelationalOperator relationalOperator = pPointStart as IRelationalOperator; IRelationalOperator relationalOperator2 = pPointEnd as IRelationalOperator; if (relationalOperator.Equals(pPointEnd)) { return null; } IPolyline polyline = (pPolyline as IClone).Clone() as IPolyline; bool flag = false; int num = -1; int num2 = -1; polyline.SplitAtPoint(pPointStart, true, false, out flag, out num, out num2); bool flag2 = false; int num3 = -1; int num4 = -1; polyline.SplitAtPoint(pPointEnd, true, false, out flag2, out num3, out num4); IPointCollection pointCollection = polyline as IPointCollection; int pointCount = pointCollection.PointCount; num2 = -1; num4 = -1; int num5 = 0; while (num5 < pointCount && (num2 < 0 || num4 < 0)) { IPoint other = pointCollection.get_Point(num5); if (!relationalOperator.Equals(other)) { if (relationalOperator2.Equals(other)) { num4 = num5; } } else { num2 = num5; } num5++; } IPolyline polyline2 = new PolylineClass(); polyline2.SpatialReference = this.m_pScreenDisplay.DisplayTransformation.SpatialReference; ISegmentCollection segmentCollection = polyline as ISegmentCollection; if (num2 <= num4) { if (num2 < num4) { for (int i = num2; i <= num4 - 1; i++) { ISegmentCollection arg_10E_0 = polyline2 as ISegmentCollection; ISegment arg_10E_1 = segmentCollection.get_Segment(i); object value = Missing.Value; object value2 = Missing.Value; arg_10E_0.AddSegment(arg_10E_1, ref value, ref value2); } } } else { for (int j = num2 - 1; j >= num4; j--) { ISegmentCollection arg_14D_0 = polyline2 as ISegmentCollection; ISegment arg_14D_1 = segmentCollection.get_Segment(j); object value3 = Missing.Value; object value4 = Missing.Value; arg_14D_0.AddSegment(arg_14D_1, ref value3, ref value4); } } ComReleaser.ReleaseCOMObject(polyline); polyline2.SimplifyNetwork(); return polyline2; } private IPolyline GetFromCloseTraced(IPolyline pPolyline, IPoint pPointStart, IPoint pPointEnd, IPolyline pPolylinePre) { if (pPolyline == null || pPolyline.IsEmpty) { return null; } IRelationalOperator relationalOperator = pPointStart as IRelationalOperator; IRelationalOperator relationalOperator2 = pPointEnd as IRelationalOperator; IPolyline polyline = (pPolyline as IClone).Clone() as IPolyline; bool flag = false; int num = -1; int num2 = -1; polyline.SplitAtPoint(pPointStart, true, false, out flag, out num, out num2); bool flag2 = false; int num3 = -1; int num4 = -1; polyline.SplitAtPoint(pPointEnd, true, false, out flag2, out num3, out num4); IPointCollection pointCollection = polyline as IPointCollection; int num5 = -1; int num6 = -1; int pointCount = pointCollection.PointCount; int num7 = 0; while (num7 < pointCount && (num5 < 0 || num6 < 0)) { IPoint other = pointCollection.get_Point(num7); if (!relationalOperator.Equals(other)) { if (relationalOperator2.Equals(other)) { num6 = num7; } } else { num5 = num7; } num7++; } if (num5 == num6) { return null; } double num8 = 0.0; if (pPolylinePre != null || !pPolylinePre.IsEmpty) { num8 = pPolylinePre.Length / pPolyline.Length; } IPolyline result; if (num8 < 0.01) { if (num5 != num6) { IPolyline fromClosedPolyline = PolylineEx.GetFromClosedPolyline(polyline, num5, num6, true); IPolyline fromClosedPolyline2 = PolylineEx.GetFromClosedPolyline(polyline, num5, num6, false); if (fromClosedPolyline2.Length >= fromClosedPolyline.Length) { ComReleaser.ReleaseCOMObject(fromClosedPolyline2); this.m_bAlongPolyline = true; result = fromClosedPolyline; } else { ComReleaser.ReleaseCOMObject(fromClosedPolyline); this.m_bAlongPolyline = false; result = fromClosedPolyline2; } } else { result = null; } } else { result = PolylineEx.GetFromClosedPolyline(polyline, num5, num6, this.m_bAlongPolyline); } ComReleaser.ReleaseCOMObject(polyline); return result; } private IPolyline GetBeTracedPolyline(IPoint pPoint, ref double dMinDistanceRtn) { double num = 10000000.0; IPolyline result = null; for (int i = 0; i < this.m_nPolylineCount; i++) { IPolyline polyline = this.m_pListBeTracePolyline[i]; IProximityOperator proximityOperator = polyline as IProximityOperator; double num2 = proximityOperator.ReturnDistance(pPoint); if (num2 < num) { num = num2; result = polyline; } } dMinDistanceRtn = num; return result; } private IPolyline GetBeTracedPolyline(IPoint pPoint, IPolyline pPolylineBeTraced, ref double dMinDistanceRtn) { double num = 10000000.0; IPolyline result = null; IRelationalOperator relationalOperator = pPolylineBeTraced as IRelationalOperator; for (int i = 0; i < this.m_nPolylineCount; i++) { IPolyline polyline = this.m_pListBeTracePolyline[i]; if (!relationalOperator.Equals(polyline)) { IProximityOperator proximityOperator = polyline as IProximityOperator; double num2 = proximityOperator.ReturnDistance(pPoint); if (num2 < num) { num = num2; result = polyline; } } } IProximityOperator proximityOperator2 = pPolylineBeTraced as IProximityOperator; double num3 = proximityOperator2.ReturnDistance(pPoint); if (num3 <= num) { dMinDistanceRtn = num3; return pPolylineBeTraced; } dMinDistanceRtn = num; return result; } private bool IsTouches(IPolyline pPolyline1, IPolyline pPolyline2) { IProximityOperator proximityOperator = pPolyline1 as IProximityOperator; return proximityOperator.ReturnDistance(pPolyline2) < 1E-05; } private IPoint GetIntersect(IPolyline pPolyline1, IPolyline pPolyline2) { ITopologicalOperator topologicalOperator = pPolyline1 as ITopologicalOperator; IGeometry geometry = topologicalOperator.Intersect(pPolyline2, esriGeometryDimension.esriGeometry0Dimension); if (geometry == null || geometry.IsEmpty) { return null; } if (geometry is IMultipoint) { return (geometry as IPointCollection).get_Point(0); } return null; } private double GetTraceTolerance() { double num = 20.0; int num2 = this.m_pScreenDisplay.DisplayTransformation.get_DeviceFrame().right - this.m_pScreenDisplay.DisplayTransformation.get_DeviceFrame().left; double width = this.m_pScreenDisplay.DisplayTransformation.VisibleBounds.Width; double num3 = width / (double)num2; return num * num3; } private int IndexOf(IPolyline pPolylineNearest) { IRelationalOperator relationalOperator = pPolylineNearest as IRelationalOperator; int count = this.m_pListPolylineBeTraced.Count; for (int i = count - 1; i >= 0; i--) { if (relationalOperator.Equals(this.m_pListPolylineBeTraced[i])) { return i; } } return -1; } private bool IsAlongPolyline(IPolyline pPolylineNearest, IPolyline pPolylinePre, int nPointIndex1, int nPointIndex2) { IPoint fromPoint = pPolylineNearest.FromPoint; IRelationalOperator relationalOperator = fromPoint as IRelationalOperator; if (!relationalOperator.Within(pPolylinePre)) { return nPointIndex1 <= nPointIndex2; } return nPointIndex1 > nPointIndex2; } private bool IsAlongPolyline(IPolyline pPolylineNearest, IPolyline pPolylinePre) { IPolyline o = null; IPolyline o2 = null; IPoint point = null; bool result = false; try { o = ((pPolylineNearest as IClone).Clone() as IPolyline); o2 = ((pPolylinePre as IClone).Clone() as IPolyline); point = new PointClass(); double dTraceTolerance = this.m_dTraceTolerance; double num = 0.0; int item = 0; int num2 = 0; bool flag = false; IHitTest hitTest = pPolylineNearest as IHitTest; IPointCollection pointCollection = pPolylinePre as IPointCollection; int pointCount = pointCollection.PointCount; List list = new List(); for (int i = 0; i < pointCount; i++) { IPoint queryPoint = pointCollection.get_Point(i); if (hitTest.HitTest(queryPoint, dTraceTolerance, esriGeometryHitPartType.esriGeometryPartVertex, point, ref num, ref num2, ref item, ref flag) && !list.Contains(item)) { list.Add(item); if (list.Count == 3) { result = this.IsAlong(list); break; } } } } catch (Exception ex) { throw new Exception(ex.Message, ex); } finally { ComReleaser.ReleaseCOMObject(o); ComReleaser.ReleaseCOMObject(o2); ComReleaser.ReleaseCOMObject(point); } return result; } private bool IsAlong(List pListVertexIndex) { return false; } } }