using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.Geometry; using KGIS.Framework.Maps; using KGIS.Framework.Platform; using KGIS.Framework.Platform.Helper; using KGIS.Framework.Utils; using KGIS.Framework.Utils.Helper; using Kingo.PluginServiceInterface; using KUI.Windows; using System; using System.Collections.Generic; namespace Kingo.Plugin.EngineEditor.Common { public class VerificationOfFeatureNodeDensity : IVerificationOfFeatureNodeDensity { readonly double MinLength = 0.2; readonly double MaxDensityLength = 70; readonly double MinDensityLength = 1; List batches = new List(); List retGeo = new List(); Dictionary dic = new Dictionary(); double addOrDelete = 0; private IHookHelper m_hookHelper; private IMapService _MapService; public VerificationOfFeatureNodeDensity(IHookHelper hookHelper) { try { m_hookHelper = hookHelper; if (MapsManager.Instance != null) _MapService = MapsManager.Instance.MapService; } catch (Exception ex) { LogAPI.Debug(ex); } } public VerificationOfFeatureNodeDensity() { } public Dictionary Verification(IGeometry[] geometries) { dic.Clear(); try { for (int i = 0; i < geometries.Length; i++) { batches.Clear(); DrawAndShow(geometries[i]); if (VerificationDensity(geometries[i])) { System.Windows.Forms.DialogResult result = MessageHelper.ShowYesNoAndError("检测到存在节点密度小于1米或者大于70米的情况!是否自动优化"); if (result == System.Windows.Forms.DialogResult.No || result == System.Windows.Forms.DialogResult.Cancel) { continue; } else if (batches[0].MaxDensity == true) { ProgressHelper.ShowProcessBar("密度大于70米,正在为图形加点....."); geometries[i] = AddPointDensity(geometries[i], 70, ref addOrDelete); dic.Add(i, geometries[i]); } else if (batches[0].MinDensity == true) { ProgressHelper.ShowProcessBar("密度小于1米,正在处理……"); geometries[i] = DeletePointDensity(geometries[i], 1, ref addOrDelete); dic.Add(i, geometries[i]); } } batches.Clear(); if (VerificationMinLine(geometries[i])) { System.Windows.Forms.DialogResult result = MessageHelper.ShowYesNoAndError(string.Format("检测到存在线段小于{0}的线段!是否自动优化", MinLength)); if (result == System.Windows.Forms.DialogResult.No || result == System.Windows.Forms.DialogResult.Cancel) { continue; } else { ProgressHelper.ShowProcessBar("正在处理过小线段……"); geometries[i] = DeletePointByMinLength(geometries[i]); } if (dic.ContainsKey(i)) { dic[i] = geometries[i]; } else dic.Add(i, geometries[i]); } } } catch (Exception ex) { LogAPI.Debug(ex); } finally { //替换Env改动 //Env.Instance.KMap.HookHelper.ActiveView.GraphicsContainer.DeleteAllElements(); m_hookHelper.ActiveView.GraphicsContainer.DeleteAllElements(); ProgressHelper.CloseProcessBar(); } return dic; } public IGeometry Verification(IGeometry geometries) { try { ////替换Env改动 //if (!Env.Instance.IsSTWZJD)//是否自动检测图斑密度 //{ // return geometries; //} batches.Clear(); if (VerificationDensity(geometries)) { DrawAndShow(geometries); System.Windows.Forms.DialogResult result = MessageHelper.ShowYesNoAndError("检测到存在节点密度小于1米或者大于70米的情况!是否自动优化"); if (result == System.Windows.Forms.DialogResult.No || result == System.Windows.Forms.DialogResult.Cancel) { return geometries; } else if (batches[0].MaxDensity == true) { ProgressHelper.ShowProcessBar("密度大于70米,正在为图形加点....."); geometries = AddPointDensity(geometries, 70, ref addOrDelete); } else if (batches[0].MinDensity == true) { addOrDelete = 0; ProgressHelper.ShowProcessBar("密度小于1米,正在处理……"); geometries = DeletePointDensity(geometries, 1, ref addOrDelete); } } batches.Clear(); if (!VerificationMinLine(geometries)) { DrawAndShow(geometries); System.Windows.Forms.DialogResult result = MessageHelper.ShowYesNoAndError(string.Format("检测到存在线段小于{0}的线段!是否自动优化", MinLength)); if (result == System.Windows.Forms.DialogResult.No || result == System.Windows.Forms.DialogResult.Cancel) { return geometries; } else { ProgressHelper.ShowProcessBar("正在处理过小线段……"); geometries = DeletePointByMinLength(geometries); } } return geometries; } catch (Exception ex) { LogAPI.Debug(ex); } finally { //清除选择的红框 //替换Env改动 //Env.Instance.KMap.HookHelper.ActiveView.GraphicsContainer.DeleteAllElements(); m_hookHelper.ActiveView.GraphicsContainer.DeleteAllElements(); ProgressHelper.CloseProcessBar(); } return geometries; } public IGeometry RepairGeometry(IGeometry geometries) { try { batches.Clear(); if (VerificationDensity(geometries)) { if (batches[0].MaxDensity == true) { this.ShowLoading("密度大于70米,正在为图形加点.......", 0, 0); geometries = AddPointDensity(geometries, 70, ref addOrDelete); } else if (batches[0].MinDensity == true) { addOrDelete = 0; this.ShowLoading("密度小于1米,正在处理.......", 0, 0); geometries = DeletePointDensity(geometries, 1, ref addOrDelete); } } batches.Clear(); return geometries; } catch (Exception ex) { this.CloseLoading(); LogAPI.Debug(ex); } finally { this.CloseLoading(); } return geometries; } public void DrawAndShow(IGeometry geometry, bool isClear = true) { if (_MapService != null) { _MapService.DrawGraph(geometry); _MapService.Zoom(geometry); if (isClear) { //替换Env改动 //CommonAPI.ClearFeatureSelection(Env.Instance.KMap.HookHelper.Hook as IMapControlDefault); _MapService.ClearFeatureSelection(m_hookHelper.Hook as IMapControlDefault); } //替换Env改动 //Env.Instance.KMap.HookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null); m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null); } } public IGeometry DeletePointByMinLength(IGeometry geometry) { ISegmentCollection segmentCollection = geometry as ISegmentCollection; IPolyline polyline = null; IPoint pointCurr = null; IPoint pointBefore = null; IPoint pointAfter = null; int lineIndex = 0; IGeometry retgeometry = geometry; try { foreach (BatchNodeInformation item in batches) { try { lineIndex = item.oid; if (lineIndex != 0) { pointBefore = segmentCollection.Segment[lineIndex - 1].FromPoint; pointCurr = segmentCollection.Segment[lineIndex - 1].ToPoint; pointAfter = item.line.ToPoint; double angle = GetAngle(pointCurr, pointBefore, pointAfter); angle = Math.Round(angle, 0, MidpointRounding.AwayFromZero); if (angle == 180 || angle == 0) { DeletePoint(pointCurr, ref geometry, true); retgeometry = geometry; } } else if (lineIndex != (segmentCollection.SegmentCount - 1)) { pointCurr = segmentCollection.Segment[lineIndex + 1].FromPoint; pointAfter = segmentCollection.Segment[lineIndex + 1].ToPoint; pointBefore = item.line.FromPoint; double angle = GetAngle(pointCurr, pointBefore, pointAfter); angle = Math.Round(angle, 0, MidpointRounding.AwayFromZero); if (angle == 180 || angle == 0) { DeletePoint(pointCurr, ref geometry, true); retgeometry = geometry; } } } catch (Exception ex) { LogAPI.Debug(ex); } } return retgeometry; } catch (Exception ex) { LogAPI.Debug(ex); throw ex; } finally { } } public IGeometry AddPointDensity(IGeometry geometry, double distinct, ref double addPoint) { IPolyline segmentFrist = null; IPolyline[] polylines = new IPolyline[2]; ISegmentCollection segmentCurr = new PolylineClass() as ISegmentCollection; IPolyline polyline = null; IPoint point = null; IPoint BeforePoint = null; int max = 0; int partIndexMax = 0; double AddPoint = addPoint; IGeometry retgeometry = geometry; int JL = 0;//距离 try { foreach (BatchNodeInformation information in batches) { segmentCurr = geometry as ISegmentCollection; if (AddPoint == 0) { AddPoint = information.length / distinct; if (information.length % distinct > 0) { AddPoint++; } AddPoint = (int)AddPoint; AddPoint -= (information.PointCount - 1); AddPoint += 2;//多加2点,让距离不卡70; JL = (int)(information.length / AddPoint); } double temp = 0; for (int i = 0; i < segmentCurr.SegmentCount; i++) { if (AddPoint < 1) { break; } if (AddPoint == 1) { } segmentFrist = getPolylineFromSegment(segmentCurr.Segment[i]); for (int ind = 1; ind <= AddPoint; ind++) { if (segmentFrist.Length < JL && temp == 0) { temp = JL - segmentFrist.Length; temp = temp < 1 ? 0 : temp; break; } else if (temp != 0 && segmentFrist.Length < temp) { temp = temp - segmentFrist.Length; temp = temp < 1 ? 0 : temp; break; } if (temp != 0) { polylines = SpliteLineAtDistinct(segmentFrist, (int)(temp), false); temp = 0; } else { polylines = SpliteLineAtDistinct(segmentFrist, (int)JL, false); } point = repeatPoint(polylines[0], polylines[1]); if (AddPoint < 1) { break; } else { AddPoint--; } IPoint iHitPt = new ESRI.ArcGIS.Geometry.Point(); IHitTest iHitTest = geometry as IHitTest; double hitDist = 0; int partIndex = 0; int vertexIndex = 0; bool bRightSide = false; polyline = GetPolyline(geometry); IPointCollection pc = (SpliteLineAtPoint(polyline, point) as IPointCollection); for (int j = 0; j < pc.PointCount; j++) { if (j == 0) { continue; } if (pc.Point[j].X == point.X && pc.Point[j].Y == point.Y) { BeforePoint = pc.Point[j - 1]; break; } } bool isTrue = iHitTest.HitTest(BeforePoint, 0.0001, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide); if (isTrue) { max = vertexIndex; partIndexMax = partIndex; retgeometry = this.AddPoint(geometry, point, partIndexMax, max, false); break; } } } } addPoint = AddPoint; return retgeometry; } catch (Exception ex) { LogAPI.Debug(ex); return retgeometry; throw; } finally { } } /// /// 给图形加点 /// /// /// 要添加的点 /// 片段顺序 /// 点的索引 /// true:Before;false:After /// public IGeometry AddPoint(IGeometry geometry, IPoint point, int partIndex, int vertexIndex, bool beforeOrAfter = true) { IGeometryCollection collection = geometry as IGeometryCollection; IGeometry geo = collection.get_Geometry(partIndex); IPointCollection points = geo as IPointCollection; object index = vertexIndex; object mss = Type.Missing; if (beforeOrAfter) { points.AddPoint(point, ref index, ref mss); } else points.AddPoint(point, ref mss, ref index); return geometry; } public IPolyline SpliteLineAtPoint(IPolyline LineCurve, IPoint SplitePoint) { IPolyline Lines = null; bool isSplit; int splitIndex, segIndex; LineCurve.SplitAtPoint(SplitePoint, false, false, out isSplit, out splitIndex, out segIndex); if (isSplit) { Lines = LineCurve as IPolyline; } return Lines; } private IPoint repeatPoint(IPolyline polyline1, IPolyline polyline2) { IPointCollection collection1 = polyline1 as IPointCollection; IPointCollection collection2 = polyline2 as IPointCollection; IPoint CenPoint = null; try { for (int i = 0; i < collection1.PointCount; i++) { for (int j = 0; j < collection2.PointCount; j++) { if (collection1.Point[i].X == collection2.Point[j].X && collection1.Point[i].Y == collection2.Point[j].Y) { CenPoint = collection1.Point[i]; return CenPoint; } } } return CenPoint; } catch (Exception ex) { LogAPI.Debug(ex); throw ex; } finally { } } public IPolyline[] SpliteLineAtDistinct(IPolyline LineCurve, int distinct, bool IsCopy = true) { IPolyline[] Lines = new IPolyline[2]; bool isSplit; int splitIndex, segIndex; IPolyline polyline = new PolylineClass(); if (IsCopy) { polyline.FromPoint = LineCurve.FromPoint; polyline.ToPoint = LineCurve.ToPoint; polyline.SpatialReference = LineCurve.SpatialReference; } else { polyline = LineCurve; } polyline.SplitAtDistance(distinct, false, false, out isSplit, out splitIndex, out segIndex); if (isSplit) { IPolyline newLine = new PolylineClass(); ISegmentCollection lineSegCol = (ISegmentCollection)polyline; ISegmentCollection newSegCol = (ISegmentCollection)newLine; object o = Type.Missing; for (int j = segIndex; j < lineSegCol.SegmentCount; j++) { newSegCol.AddSegment(lineSegCol.get_Segment(j), ref o, ref o); } lineSegCol.RemoveSegments(segIndex, lineSegCol.SegmentCount - segIndex, true); lineSegCol.SegmentsChanged(); newSegCol.SegmentsChanged(); IPolyline oldLine = lineSegCol as IPolyline; newLine = newSegCol as IPolyline; Lines[0] = newLine; Lines[1] = oldLine; } return Lines; } public bool VerificationDensity(IGeometry geometry) { try { bool isSucc = false; //周长 ITopologicalOperator topo = geometry as ITopologicalOperator; IPolyline line = topo.Boundary as IPolyline; double zc = line.Length; //点数 int PointCount = (geometry as IPointCollection).PointCount; double Density = zc / (PointCount - 1); if (MinDensityLength > Density) { isSucc = true; batches.Add(new BatchNodeInformation() { length = zc, PointCount = PointCount, MinDensity = isSucc }); } else if (Density > MaxDensityLength) { isSucc = true; batches.Add(new BatchNodeInformation() { length = zc, PointCount = PointCount, MaxDensity = isSucc }); } return isSucc; } catch (Exception ex) { LogAPI.Debug("验证 密度 函数异常,原因: " + ex + " ; "); return false; } } public bool VerificationMinLine(IGeometry geometry) { try { bool isSucc = true; ISegmentCollection segmentCurr = geometry as ISegmentCollection; IPolyline[] polylines = new IPolyline[2]; IPolyline polyline = null; for (int i = 0; i < segmentCurr.SegmentCount; i++) { polyline = getPolylineFromSegment(segmentCurr.Segment[i]); if (polyline.Length < 0.2) { isSucc = false; batches.Add(new BatchNodeInformation() { line = polyline, length = polyline.Length, MinLength = isSucc, oid = i }); } } return isSucc; } catch (Exception ex) { LogAPI.Debug("验证 最小线段 函数异常,原因: " + ex + " ; "); return true; } } public IGeometry DeletePointDensity(IGeometry geometry, double distinct, ref double DelPoint) { IPoint point = null; double AddPoint = DelPoint; IPointCollection collection = null; double angle = 0; IGeometry Retgeometry = geometry; try { foreach (BatchNodeInformation information in batches) { if (AddPoint == 0) { AddPoint = information.length / distinct; if (information.length % distinct > 0) { AddPoint++; } if (AddPoint % 1 > 0) { AddPoint = (int)AddPoint + 1; } AddPoint = (information.PointCount - 1 - AddPoint); } collection = (geometry as IPointCollection); for (int i = 0; i < collection.PointCount - 1; i++) { if (AddPoint < 1) { break; } if (i == 0) { continue; } try { angle = GetAngle(collection.Point[i], collection.Point[i - 1], collection.Point[i + 1]); angle = Math.Round(angle, 0, MidpointRounding.AwayFromZero); if (angle == 180 || angle == 0) { DeletePoint(collection.Point[i], ref geometry, true); Retgeometry = geometry; AddPoint--; } } catch (Exception ex) { LogAPI.Debug(ex); } } } return Retgeometry; } catch (Exception ex) { LogAPI.Debug(ex); return Retgeometry; throw; } finally { } } private void DeletePoint(IPoint point, ref IGeometry geometry, bool isDelete = false) { IPointCollection collection = new PolylineClass() as IPointCollection; IPointCollection pointCollection = new PolygonClass() as IPointCollection; try { IPolyline polyline = GetPolyline(geometry); collection.AddPoint(point); geometry = RemovePointformLine(geometry, collection); } catch (Exception ex) { LogAPI.Debug(ex); throw ex; } finally { } } public IGeometry RemovePointformLine(IGeometry geometry, IPointCollection point) { IGeometryCollection collection = geometry as IGeometryCollection; IGeometry geo = null; IPointCollection pointCollection = null; try { var pHitTest = geometry as IHitTest; var ptDelete = new PointClass(); double DbHitDis = 0; int LngPrtIdx = 0; int indexDelete = 0; bool BoolHitRt = false; var points = geometry as IPointCollection; for (var j = 0; j < point.PointCount; j++) { var delpoint = point.Point[j]; var BoolHitTest = pHitTest.HitTest(delpoint, 0.0001, esriGeometryHitPartType.esriGeometryPartVertex, ptDelete, ref DbHitDis, ref LngPrtIdx, ref indexDelete, ref BoolHitRt); geo = collection.get_Geometry(LngPrtIdx); pointCollection = geo as IPointCollection; IPoint pt = points.get_Point(indexDelete); points.RemovePoints(indexDelete, 1); } return geometry; } catch (Exception ex) { LogAPI.Debug(ex); } finally { } return geometry; } public IPolyline GetPolyline(IGeometry geometry) { IPolygon polygon = geometry as IPolygon; ISegmentCollection segmentCollction = polygon as ISegmentCollection; ISegmentCollection polyline = new Polyline() as ISegmentCollection; object before = Type.Missing; object after = Type.Missing; for (int m = 0; m < segmentCollction.SegmentCount; m++) { ISegment pSeg = segmentCollction.get_Segment(m); polyline.AddSegment(pSeg, ref before, ref after); } IPolyline pGeo = polyline as IPolyline; return pGeo; } public static double GetAngle(IPoint cenPoint, IPoint firstPoint, IPoint secondPoint) { double ma_x = firstPoint.X - cenPoint.X; double ma_y = firstPoint.Y - cenPoint.Y; double mb_x = secondPoint.X - cenPoint.X; double mb_y = secondPoint.Y - cenPoint.Y; double v1 = (ma_x * mb_x) + (ma_y * mb_y); double ma_val = Math.Sqrt(ma_x * ma_x + ma_y * ma_y); double mb_val = Math.Sqrt(mb_x * mb_x + mb_y * mb_y); if (ma_val * mb_val == 0) { return -1; } double cosM = v1 / (ma_val * mb_val); double angleAMB = Math.Acos(cosM) * 180 / Math.PI; return angleAMB; } private IPolyline getPolylineFromSegment(ISegment iSegment) { IGeometryCollection pGeoCol = new PolylineClass(); ISegmentCollection pSegCol = new PathClass(); ILine pLine = new LineClass(); pLine.FromPoint = iSegment.FromPoint; pLine.ToPoint = iSegment.ToPoint; object mis = Type.Missing; pSegCol.AddSegment((ISegment)pLine, ref mis, ref mis); pGeoCol.AddGeometry((IGeometry)pSegCol, ref mis, ref mis); return (IPolyline)pGeoCol; } } class BatchNodeInformation { public double length; public int PointCount; public int oid; public IPolyline line; public bool MaxDensity; public bool MinDensity; public bool MinLength; } }