using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using KGIS.Framework.AE; using KGIS.Framework.AE.ExtensionMethod; using KGIS.Framework.Maps; using KGIS.Framework.Utils; using KGIS.Framework.Utils.ExtensionMethod; using NPOI.SS.Formula.Functions; using NPOI.Util; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Shapes; namespace Kingo.PluginServiceInterface.Helper { /// /// 边界修复 /// public static class BoundaryRepairHelper { /// /// 执行边界套合修复逻辑 /// /// 待修复的图斑 /// 修复图层 /// 参考图层 /// public static IGeometry ExecuteBoundaryRepair(IGeometry geometry, IFeatureLayer RepairLayer, IFeatureLayer ReferenceLayer, double distance) { try { IGeometryCollection geometryCollection = geometry as IGeometryCollection; IGeometry insidegeo = null; ISegmentCollection final = new PolygonClass(); for (int p = 0; p < geometryCollection.GeometryCount; p++) { insidegeo = geometryCollection.get_Geometry(p); List repairpoints = LayerHelper.GetMultipleRingPoints(insidegeo); var count = 0; foreach (var point in repairpoints) { count++; if (count == 8) { var x = point.X; var Y = point.Y; } var UpdatePoint = GetSnappingpoint(point, ReferenceLayer, distance); if (UpdatePoint.Count == 0) { UpdatePoint = GetSnappingpoint(point, RepairLayer, distance); } if (UpdatePoint.Count == 0) continue; var Listpoint = UpdatePoint.OrderByDescending(x => x.Value).ToList(); IPoint moveToPoint = null; if (Listpoint.Count > 0) { #region 如果存在共点>1的,则删除共点=1的 var where = Listpoint.Where(x => x.Value > 1).ToList(); if (where.Count > 0) { where = Listpoint.Where(x => x.Value == 1).ToList(); foreach (var item in where) { Listpoint.Remove(item); } } #endregion #region 共点个数相同的情况下,取距离最近的点 var GroupBy = Listpoint.GroupBy(x => x.Value).ToList(); if (Listpoint.Count > 1) { double refdistance = -1; double mindistance = -1; var index = -1; for (int i = 0; i < Listpoint.Count; i++) { refdistance = Math.Sqrt((point.X - Listpoint[i].Key.X) * (point.X - Listpoint[i].Key.X) + (point.Y - Listpoint[i].Key.Y) * (point.Y - Listpoint[i].Key.Y)); if (mindistance == -1) { mindistance = refdistance; index = i; } else if (refdistance < mindistance) { mindistance = refdistance; index = i; } } if (index != -1) { moveToPoint = Listpoint[index].Key; Listpoint.RemoveAt(index); } } else { moveToPoint = Listpoint[0].Key; Listpoint.RemoveAt(0); } #endregion } if (moveToPoint != null) { IPointCollection points = insidegeo as IPointCollection; var index = -1; for (int i = 0; i < points.PointCount - 1; i++) { IPoint tPoint = points.Point[i]; var refdistance = Math.Sqrt((point.X - tPoint.X) * (point.X - tPoint.X) + (point.Y - tPoint.Y) * (point.Y - tPoint.Y)); if (refdistance == 0 || Math.Abs(refdistance) < (1e-5)) { index = i; break; } } if (index > -1) { var refdistance = Math.Sqrt((point.X - moveToPoint.X) * (point.X - moveToPoint.X) + (point.Y - moveToPoint.Y) * (point.Y - moveToPoint.Y)); if (refdistance == 0) continue; points.UpdatePoint(index, moveToPoint); } List firstSnapPointList = Snapping(point, RepairLayer, distance); if (firstSnapPointList != null && firstSnapPointList.Count > 1) { foreach (var item in firstSnapPointList) { IGeometryCollection collection = item.Geometry as IGeometryCollection; IGeometry geo = collection.get_Geometry(item.PartIndex); points = geo as IPointCollection; IPoint pt = points.get_Point(item.VertexIndex); points.UpdatePoint(item.VertexIndex, moveToPoint); item.Feature.Shape = item.Geometry; item.Feature.Store(); } } } if (Listpoint.Count > 0) { IGeometry line = PolygonToPolyline(insidegeo); if (line.GeometryType == esriGeometryType.esriGeometryPolyline) { bool SplitHappened; int newPartIndex; int newSegmentIndex; for (int i = 0; i < Listpoint.Count; i++) { if (Listpoint[i].Value > 1) { IPolyline polyline = line as IPolyline; IPoint point1 = new PointClass(); var DistanceAlongCurve = 0.0001; var distanceFromCurve = 0.0001; bool bRightSide = true; polyline.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, Listpoint[i].Key, false, point1, ref DistanceAlongCurve, ref distanceFromCurve, bRightSide); var pointdistance = Math.Sqrt((Listpoint[i].Key.X - point1.X) * (Listpoint[i].Key.X - point1.X) + (Listpoint[i].Key.Y - point1.Y) * (Listpoint[i].Key.Y - point1.Y)); if (pointdistance > 0.1 || pointdistance < 0.01) continue; (line as IPolyline).SplitAtPoint(Listpoint[i].Key, true, true, out SplitHappened, out newPartIndex, out newSegmentIndex); insidegeo = ConstructPolygonFromPolyline((line as IPolyline)); break; } } } } } final.AddSegmentCollection(insidegeo as ISegmentCollection); } geometry = final as IPolygon; #region 判断当前图斑是否压盖多个图斑且存在碎图斑 var Identify2 = FeatureAPI.Identify2(geometry, ReferenceLayer); if (Identify2 != null && Identify2.Count > 0) { foreach (var feature1 in Identify2) { #region 相交部分 var geo = FeatureAPI.InterSect(geometry, feature1.ShapeCopy); List geometries = FeatureAPI.DissolveGeometryByRing(geo); if (geometries != null && geometries.Count > 0) { foreach (var item in geometries) { ITopologicalOperator topoOpr = item as ITopologicalOperator; topoOpr.Simplify(); var mj = item.GetEllipseArea(); if (mj < 1 && !item.IsEmpty && mj != 0 && mj > 0.01) geometry = FeatureAPI.Difference(geometry, item); } } else { continue; } #endregion #region 不相交部分 geo = FeatureAPI.Difference(feature1.ShapeCopy, geometry); geometries = FeatureAPI.DissolveGeometryByRing(geo); if (geometries != null && geometries.Count > 0) { foreach (var item in geometries) { ITopologicalOperator topoOpr = item as ITopologicalOperator; topoOpr.Simplify(); var mj = item.GetEllipseArea(); if (mj < 1 && !item.IsEmpty) { if (FeatureAPI.LengthOfSide(geometry, item) > 0) geometry = FeatureAPI.Union(geometry, item); } } } #endregion } } #endregion } catch (Exception ex) { LogAPI.Debug("执行ExecuteRepair异常:" + ex.Message + ex.StackTrace); return geometry; } return geometry; } /// /// 执行边界套合修复逻辑 /// /// 待修复的图斑 /// 修复图层 /// 参考图层 /// public static IGeometry ExecuteBoundaryRepair1(IGeometry geometry, IFeatureLayer RepairLayer, IFeatureLayer ReferenceLayer, double distance) { try { List Identify = FeatureAPI.Identify(geometry, ReferenceLayer); double MaxOccupyArea = -1;//图形占基础图斑面积 int ReferenceOID = -1; foreach (IFeature feature in Identify) { var InterSectgeo = FeatureAPI.InterSect(geometry, feature.ShapeCopy); double mj = InterSectgeo.GetEllipseArea(); if (MaxOccupyArea == -1) { MaxOccupyArea = mj; ReferenceOID = feature.OID; } else if (mj > MaxOccupyArea) { MaxOccupyArea = mj; ReferenceOID = feature.OID; } } IGeometryCollection geometryCollection = geometry as IGeometryCollection; IGeometry insidegeo = null; ISegmentCollection final = new PolygonClass(); List RepairdPoint = new List();//已修复的点 for (int p = 0; p < geometryCollection.GeometryCount; p++) { insidegeo = geometryCollection.get_Geometry(p); List repairpoints = LayerHelper.GetMultipleRingPoints(insidegeo); var count = 0; foreach (var point in repairpoints) { count++; if (count == 7) { var x = point.X; var Y = point.Y; } var UpdatePoint = GetSnappingpoint1(point, ReferenceLayer, distance); if (UpdatePoint.Count == 0) { UpdatePoint = GetSnappingpoint1(point, RepairLayer, 0.01); } if (UpdatePoint.Count == 0) continue; var Listpoint = UpdatePoint.OrderByDescending(x => x.ConcurrentCount).ToList(); IPoint moveToPoint = null; if (Listpoint.Count > 0) { #region 如果存在共点>1的,则删除共点=1的 var where = Listpoint.Where(x => x.ConcurrentCount > 1).ToList(); if (where.Count > 0) { where = Listpoint.Where(x => x.ConcurrentCount == 1).ToList(); foreach (var item in where) { Listpoint.Remove(item); } } #endregion #region 取距离最近的点 if (Listpoint.Count > 1) { double mindistance = -1; var index = -1; for (int i = 0; i < Listpoint.Count; i++) { if (!Listpoint[i].ListObjectID.Contains(ReferenceOID)) continue; double refdistance = Math.Sqrt((point.X - Listpoint[i].Point.X) * (point.X - Listpoint[i].Point.X) + (point.Y - Listpoint[i].Point.Y) * (point.Y - Listpoint[i].Point.Y)); if (mindistance == -1) { mindistance = refdistance; index = i; } else if (refdistance < mindistance) { mindistance = refdistance; index = i; } } if (index == -1) { for (int i = 0; i < Listpoint.Count; i++) { var ReferenceIdentify = FeatureAPI.Identify2(point, ReferenceLayer); if (ReferenceIdentify.Count == 1) { foreach (var item in ReferenceIdentify) { if (Listpoint[i].ListObjectID.Contains(item.OID)) { index = i; break; } } } } if (index == -1) { for (int i = 0; i < Listpoint.Count; i++) { double refdistance = Math.Sqrt((point.X - Listpoint[i].Point.X) * (point.X - Listpoint[i].Point.X) + (point.Y - Listpoint[i].Point.Y) * (point.Y - Listpoint[i].Point.Y)); if (mindistance == -1) { mindistance = refdistance; index = i; } else if (refdistance < mindistance) { mindistance = refdistance; index = i; } } } } if (index != -1) { moveToPoint = Listpoint[index].Point; Listpoint.RemoveAt(index); RepairdPoint.Add(moveToPoint); } } else { moveToPoint = Listpoint[0].Point; Listpoint.RemoveAt(0); RepairdPoint.Add(moveToPoint); } #endregion } if (moveToPoint != null) { IPointCollection points = insidegeo as IPointCollection; var index = -1; for (int i = 0; i < points.PointCount - 1; i++) { IPoint tPoint = points.Point[i]; var refdistance = Math.Sqrt((point.X - tPoint.X) * (point.X - tPoint.X) + (point.Y - tPoint.Y) * (point.Y - tPoint.Y)); if (refdistance == 0 || Math.Abs(refdistance) < (1e-5)) { index = i; break; } } if (index > -1) { var refdistance = Math.Sqrt((point.X - moveToPoint.X) * (point.X - moveToPoint.X) + (point.Y - moveToPoint.Y) * (point.Y - moveToPoint.Y)); if (refdistance == 0) continue; points.UpdatePoint(index, moveToPoint); } List firstSnapPointList = Snapping(point, RepairLayer, distance); if (firstSnapPointList != null && firstSnapPointList.Count > 1) { foreach (var item in firstSnapPointList) { IGeometryCollection collection = item.Geometry as IGeometryCollection; IGeometry geo = collection.get_Geometry(item.PartIndex); points = geo as IPointCollection; IPoint pt = points.get_Point(item.VertexIndex); points.UpdatePoint(item.VertexIndex, moveToPoint); item.Feature.Shape = item.Geometry; item.Feature.Store(); } } } if (Listpoint.Count > 0) { IGeometry line = PolygonToPolyline(insidegeo); if (line.GeometryType == esriGeometryType.esriGeometryPolyline) { bool SplitHappened; int newPartIndex; int newSegmentIndex; for (int i = 0; i < Listpoint.Count; i++) { if (Listpoint[i].ConcurrentCount > 1) { IPolyline polyline = line as IPolyline; IPoint point1 = new PointClass(); var DistanceAlongCurve = 0.0001; var distanceFromCurve = 0.0001; bool bRightSide = true; polyline.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, Listpoint[i].Point, false, point1, ref DistanceAlongCurve, ref distanceFromCurve, bRightSide); var pointdistance = Math.Sqrt((Listpoint[i].Point.X - point1.X) * (Listpoint[i].Point.X - point1.X) + (Listpoint[i].Point.Y - point1.Y) * (Listpoint[i].Point.Y - point1.Y)); if (pointdistance > 0.1 || pointdistance < 0.01) continue; IPolyline polyline1 = new PolylineClass(); polyline1.FromPoint = point1; polyline1.ToPoint = moveToPoint; polyline1.SpatialReference = moveToPoint.SpatialReference; if (FeatureAPI.IsContains(line, polyline1)) continue; (line as IPolyline).SplitAtPoint(Listpoint[i].Point, true, true, out SplitHappened, out newPartIndex, out newSegmentIndex); insidegeo = ConstructPolygonFromPolyline((line as IPolyline)); break; } } } } } final.AddSegmentCollection(insidegeo as ISegmentCollection); } geometry = final as IPolygon; #region 判断当前图斑是否压盖多个图斑且存在碎图斑 var Identify2 = FeatureAPI.Identify2(geometry, ReferenceLayer); if (Identify2 != null && Identify2.Count > 0) { foreach (var feature1 in Identify2) { #region 相交部分 var geo = FeatureAPI.InterSect(geometry, feature1.ShapeCopy); List geometries = FeatureAPI.DissolveGeometryByRing(geo); if (geometries != null && geometries.Count > 0) { foreach (var item in geometries) { ITopologicalOperator topoOpr = item as ITopologicalOperator; topoOpr.Simplify(); var mj = item.GetEllipseArea(); if (mj < 1 && !item.IsEmpty) geometry = FeatureAPI.Difference(geometry, item); } } else { continue; } #endregion #region 不相交部分 geo = FeatureAPI.Difference(feature1.ShapeCopy, geometry); geometries = FeatureAPI.DissolveGeometryByRing(geo); if (geometries != null && geometries.Count > 0) { foreach (var item in geometries) { ITopologicalOperator topoOpr = item as ITopologicalOperator; topoOpr.Simplify(); var mj = item.GetEllipseArea(); if (mj < 1 && !item.IsEmpty) { if (FeatureAPI.LengthOfSide(geometry, item) > 0) geometry = FeatureAPI.Union(geometry, item); } } } #endregion } } #endregion } catch (Exception ex) { LogAPI.Debug("执行ExecuteRepair异常:" + ex.Message + ex.StackTrace); return geometry; } return geometry; } /// /// 执行边界套合修复逻辑 /// /// 待修复的图斑 /// 修复图层 /// 参考图层 /// public static IGeometry ExecuteBoundaryRepair2(IGeometry geometry, List RepairLayer, List ReferenceLayer, double distance) { try { IGeometryCollection geometryCollection = geometry as IGeometryCollection; IGeometry insidegeo = null; ISegmentCollection final = new PolygonClass(); List RepairdPoint = new List();//已修复的点 for (int p = 0; p < geometryCollection.GeometryCount; p++) { insidegeo = geometryCollection.get_Geometry(p); List repairpoints = LayerHelper.GetMultipleRingPoints(insidegeo); var count = 0; foreach (var point in repairpoints) { count++; if (count == 7) { var x = point.X; var Y = point.Y; } var UpdatePoint = GetSnappingpoint2(point, ReferenceLayer, null, distance); if (UpdatePoint.Count == 0) { UpdatePoint = GetSnappingpoint2(point, RepairLayer, null, 0.01); } if (UpdatePoint.Count == 0) continue; var Listpoint = UpdatePoint.OrderByDescending(x => x.ConcurrentCount).ToList(); IPoint moveToPoint = null; if (Listpoint.Count > 0) { #region 如果存在共点>1的,则删除共点=1的 var where = Listpoint.Where(x => x.ConcurrentCount > 1).ToList(); if (where.Count > 0) { where = Listpoint.Where(x => x.ConcurrentCount == 1).ToList(); foreach (var item in where) { Listpoint.Remove(item); } } #endregion #region 取距离最近的点 if (Listpoint.Count > 1) { double mindistance = -1; var index = -1; for (int i = 0; i < Listpoint.Count; i++) { double refdistance = Math.Sqrt((point.X - Listpoint[i].Point.X) * (point.X - Listpoint[i].Point.X) + (point.Y - Listpoint[i].Point.Y) * (point.Y - Listpoint[i].Point.Y)); if (mindistance == -1) { mindistance = refdistance; index = i; } else if (refdistance < mindistance) { mindistance = refdistance; index = i; } } if (index == -1) { for (int i = 0; i < Listpoint.Count; i++) { //var ReferenceIdentify = FeatureAPI.Identify2(point, ReferenceLayer); //if (ReferenceIdentify.Count == 1) //{ // foreach (var item in ReferenceIdentify) // { // if (Listpoint[i].ListObjectID.Contains(item.OID)) // { // index = i; // break; // } // } //} } if (index == -1) { for (int i = 0; i < Listpoint.Count; i++) { double refdistance = Math.Sqrt((point.X - Listpoint[i].Point.X) * (point.X - Listpoint[i].Point.X) + (point.Y - Listpoint[i].Point.Y) * (point.Y - Listpoint[i].Point.Y)); if (mindistance == -1) { mindistance = refdistance; index = i; } else if (refdistance < mindistance) { mindistance = refdistance; index = i; } } } } if (index != -1) { moveToPoint = Listpoint[index].Point; Listpoint.RemoveAt(index); RepairdPoint.Add(moveToPoint); } } else { moveToPoint = Listpoint[0].Point; Listpoint.RemoveAt(0); RepairdPoint.Add(moveToPoint); } #endregion } if (moveToPoint != null) { IPointCollection points = insidegeo as IPointCollection; var index = -1; for (int i = 0; i < points.PointCount - 1; i++) { IPoint tPoint = points.Point[i]; var refdistance = Math.Sqrt((point.X - tPoint.X) * (point.X - tPoint.X) + (point.Y - tPoint.Y) * (point.Y - tPoint.Y)); if (refdistance == 0 || Math.Abs(refdistance) < (1e-5)) { index = i; break; } } if (index > -1) { var refdistance = Math.Sqrt((point.X - moveToPoint.X) * (point.X - moveToPoint.X) + (point.Y - moveToPoint.Y) * (point.Y - moveToPoint.Y)); if (refdistance == 0) continue; points.UpdatePoint(index, moveToPoint); } List firstSnapPointList = Snapping2(point, RepairLayer, distance); if (firstSnapPointList != null && firstSnapPointList.Count > 1) { foreach (var item in firstSnapPointList) { IGeometryCollection collection = item.Geometry as IGeometryCollection; IGeometry geo = collection.get_Geometry(item.PartIndex); points = geo as IPointCollection; IPoint pt = points.get_Point(item.VertexIndex); points.UpdatePoint(item.VertexIndex, moveToPoint); item.Feature.Shape = item.Geometry; item.Feature.Store(); } } } if (Listpoint.Count > 0) { IGeometry line = PolygonToPolyline(insidegeo); if (line.GeometryType == esriGeometryType.esriGeometryPolyline) { bool SplitHappened; int newPartIndex; int newSegmentIndex; for (int i = 0; i < Listpoint.Count; i++) { if (Listpoint[i].ConcurrentCount > 1) { IPolyline polyline = line as IPolyline; IPoint point1 = new PointClass(); var DistanceAlongCurve = 0.0001; var distanceFromCurve = 0.0001; bool bRightSide = true; polyline.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, Listpoint[i].Point, false, point1, ref DistanceAlongCurve, ref distanceFromCurve, bRightSide); var pointdistance = Math.Sqrt((Listpoint[i].Point.X - point1.X) * (Listpoint[i].Point.X - point1.X) + (Listpoint[i].Point.Y - point1.Y) * (Listpoint[i].Point.Y - point1.Y)); if (pointdistance > 0.1 || pointdistance < 0.01) continue; IPolyline polyline1 = new PolylineClass(); polyline1.FromPoint = point1; polyline1.ToPoint = moveToPoint; polyline1.SpatialReference = moveToPoint.SpatialReference; if (FeatureAPI.IsContains(line, polyline1)) continue; (line as IPolyline).SplitAtPoint(Listpoint[i].Point, true, true, out SplitHappened, out newPartIndex, out newSegmentIndex); insidegeo = ConstructPolygonFromPolyline((line as IPolyline)); break; } } } } } final.AddSegmentCollection(insidegeo as ISegmentCollection); } geometry = final as IPolygon; #region 判断当前图斑是否压盖多个图斑且存在碎图斑 foreach (IGeometry geometry1 in ReferenceLayer) { #region 相交部分 var geo = FeatureAPI.InterSect(geometry, geometry1); List geometries = FeatureAPI.DissolveGeometryByRing(geo); if (geometries != null && geometries.Count > 0) { foreach (var item in geometries) { ITopologicalOperator topoOpr = item as ITopologicalOperator; topoOpr.Simplify(); var mj = item.GetEllipseArea(); if (mj < 1 && !item.IsEmpty) geometry = FeatureAPI.Difference(geometry, item); } } else { continue; } #endregion #region 不相交部分 geo = FeatureAPI.Difference(geometry1, geometry); geometries = FeatureAPI.DissolveGeometryByRing(geo); if (geometries != null && geometries.Count > 0) { foreach (var item in geometries) { ITopologicalOperator topoOpr = item as ITopologicalOperator; topoOpr.Simplify(); var mj = item.GetEllipseArea(); if (mj < 1 && !item.IsEmpty) { geometry = FeatureAPI.Union(geometry, item); } } } #endregion } #endregion } catch (Exception ex) { LogAPI.Debug("执行ExecuteRepair异常:" + ex.Message + ex.StackTrace); return geometry; } return geometry; } public static List ExecuteBoundaryRepair3(IGeometry OriginalGeo, List ReferenceLayer, List jcdltb_features, double distance) { List ResultgeometryList = new List(); List geometryList = null; try { geometryList = FeatureAPI.DissolveGeometryByRing(OriginalGeo);//拆分多部件 foreach (IGeometry Splitgeo in geometryList) { IGeometry geometry = Splitgeo; if (geometry == null || geometry.IsEmpty || geometry.GetEllipseArea() == 0) continue; IGeometry repaird = NodeRepair(geometry, ReferenceLayer, distance); if (repaird != null && !repaird.IsEmpty) { geometry = repaird; geometry.SpatialReference = OriginalGeo.SpatialReference; } ITopologicalOperator geotopoOpr1 = geometry as ITopologicalOperator; geotopoOpr1.Simplify(); if (geometry == null || geometry.IsEmpty) continue; #region 节点修复完成后,删除多部件中面积小于1的 var multi = FeatureAPI.DissolveGeometryByRing(geometry);//拆分多部件 if (multi != null && multi.Count > 1) { foreach (IGeometry geo in multi) { var mj = geo.GetEllipseArea(); if (mj < 1) { geometry = FeatureAPI.Difference(geometry, geo); } } } else if (multi == null) continue; #endregion #region 检查图形是否存在尖锐角/狭长图形等问题 List pointList = null; double angle = 0; if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle)) { if (pointList != null && angle < 10) { if (ReferenceLayer.Count == 1) { geometry = ResolveAcuteAngle(geometry, pointList, angle, ReferenceLayer[0], true); } else { geometry = ResolveAcuteAngle(geometry, pointList, angle); } } } #endregion #region 判断当前图斑是否压盖多个图斑且存在碎图斑 foreach (IGeometry jcgeometry in jcdltb_features) { #region 相交部分 var geo = FeatureAPI.InterSect(geometry, jcgeometry); List geometries = FeatureAPI.DissolveGeometryByRing(geo); if (geometries != null && geometries.Count > 0) { foreach (var item in geometries) { ITopologicalOperator topoOpr = item as ITopologicalOperator; topoOpr.Simplify(); var mj = item.GetEllipseArea(); if (mj < 1 && !item.IsEmpty) geometry = FeatureAPI.Difference(geometry, item); } } else { continue; } #endregion #region 不相交部分 geo = FeatureAPI.Difference(jcgeometry, geometry); geometries = FeatureAPI.DissolveGeometryByRing(geo); if (geometries != null && geometries.Count > 0) { foreach (var item in geometries) { ITopologicalOperator topoOpr = item as ITopologicalOperator; topoOpr.Simplify(); List pointList1 = null; double angle1 = 0; var mj = item.GetEllipseArea(); //与基础库不想交的部分面积小于30平且相邻的情况下 合并 if (mj < 30 && !item.IsEmpty && FeatureAPI.IsAdjacent(geometry, item)) { geometry = FeatureAPI.Union(geometry, item); continue; } else { if (AECommonHelper.SharpAngleDataCheck(item, ref pointList1, ref angle1)) { if (angle1 > 10)//狭长图形 { continue; } else { var completedgeo = SharpAngleMerge(item, pointList1); if (FeatureAPI.IsAdjacent(geometry, completedgeo)) { if (completedgeo.GetEllipseArea() > 30) { } var uniongeo = FeatureAPI.Union(geometry, completedgeo); if (AECommonHelper.SharpAngleDataCheck(uniongeo, ref pointList, ref angle)) { geometry = ResolveAcuteAngle(uniongeo, pointList, angle, item, true); } } else { } } } } } } #endregion } #endregion #region 检查图形是否存在尖锐角/狭长图形等问题 if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle)) { geometry = BoundaryRepairHelper.ResolveAcuteAngle(geometry, pointList, angle); } #endregion var Dissolve = FeatureAPI.DissolveGeometryByRing(geometry);//拆分多部件 if (Dissolve != null && Dissolve.Count > 1) { foreach (var item in Dissolve) { ResultgeometryList.Add(item); } } else { ResultgeometryList.Add(geometry); } } } catch (Exception ex) { ResultgeometryList = geometryList; LogAPI.Debug("执行ExecuteRepair异常:" + ex.Message + ex.StackTrace); return ResultgeometryList; } return ResultgeometryList; } private static IGeometry NodeRepair(IGeometry OriginalGeo, List ReferenceLayer, double distance) { IGeometry geometry = OriginalGeo; try { List repairpoints = LayerHelper.GetMultipleRingPoints(geometry); var count = 0; List listmoveToPoint = new List(); foreach (var point in repairpoints) { count++; var xx = point.X; var yy = point.Y; IPoint PrevPoint = null; IPoint NextPoint = null; var pointangle = GetRelativeAngle(geometry, point, ref PrevPoint, ref NextPoint); var UpdatePoint = GetSnappingpoint2(point, ReferenceLayer, listmoveToPoint, distance); if (UpdatePoint.Count == 0) continue; var Listpoint = UpdatePoint.OrderByDescending(x => x.ConcurrentCount).ToList(); IPoint moveToPoint = null; if (Listpoint.Count > 0) { bool isContains = true; foreach (var item in Listpoint) { if (!listmoveToPoint.Contains($"{item.Point.X},{item.Point.Y}")) { bool isbreak = false; foreach (var iPoint in listmoveToPoint) { var x = iPoint.Split(',')[0].ToDouble(); var y = iPoint.Split(',')[1].ToDouble(); //两个距离相近的点修复到同一个位置时,删除当前图形中的一个点 var refdistance = Math.Sqrt((item.Point.X - x) * (item.Point.X - x) + (item.Point.Y - y) * (item.Point.Y - y)); if (refdistance == 0 || Math.Abs(refdistance) < (1e-3)) { isbreak = true; break; } } if (isbreak) break; isContains = false; break; } } if (isContains) { IPointCollection points = geometry as IPointCollection; var index = -1; for (int i = 0; i < points.PointCount - 1; i++) { IPoint tPoint = points.Point[i]; var refdistance = Math.Sqrt((point.X - tPoint.X) * (point.X - tPoint.X) + (point.Y - tPoint.Y) * (point.Y - tPoint.Y)); if (refdistance == 0 || Math.Abs(refdistance) < (1e-5)) { index = i; break; } } if (index > -1) { points.RemovePoints(index, 1); continue; } } if (Listpoint.Count > 1) { if (Listpoint.FirstOrDefault(x => x.FootPoint == false) != null) { for (int i = 0; i < Listpoint.Count; i++) { if (Listpoint[i].FootPoint == true) { Listpoint.RemoveAt(i); i = 0; continue; } } } //多个相近的参考点在不同的参考图形上,根据距离最近的取参考点 if (ReferenceLayer.Count > 1) { double mindistance = -1; var index = -1; for (int i = 0; i < Listpoint.Count; i++) { double refdistance = Math.Sqrt((point.X - Listpoint[i].Point.X) * (point.X - Listpoint[i].Point.X) + (point.Y - Listpoint[i].Point.Y) * (point.Y - Listpoint[i].Point.Y)); if (mindistance == -1) { mindistance = refdistance; index = i; } else if (refdistance < mindistance) { mindistance = refdistance; index = i; } } if (index != -1) { moveToPoint = Listpoint[index].Point; Listpoint.RemoveAt(index); } } else { #region 出现多个相近的点 var nearUpdatePoint = Listpoint.OrderBy(n => Math.Abs(n.angle - pointangle)).FirstOrDefault(); moveToPoint = nearUpdatePoint.Point; #endregion } } else if (Listpoint.Count == 1) { //if (Listpoint[0].FootPoint) //{ // IPolyline polyline = new PolylineClass(); // try // { // double refdistance = Math.Sqrt((point.X - Listpoint[0].Point.X) * (point.X - Listpoint[0].Point.X) + (point.Y - Listpoint[0].Point.Y) * (point.Y - Listpoint[0].Point.Y)); // if (Math.Abs(refdistance) < (1e-5)) // { // continue; // } // polyline.SpatialReference = geometry.SpatialReference; // polyline.FromPoint = point; // polyline.ToPoint = Listpoint[0].Point; // polyline = getExtendLine(polyline, 2, 1); // if (FeatureAPI.IsInterSect(geometry, polyline)) // { // //List Cutgeometries = FeatureAPI.CutGeometry(geometry, polyline); // //if (Cutgeometries != null && Cutgeometries.Count > 1) // //{ // // bool isbreak = false; // // foreach (var item in Cutgeometries) // // { // // if (item.IsEmpty || item.GetEllipseArea() == 0) // // { // // isbreak = true; break; // // } // // } // // if (!isbreak) // // continue; // //} // } // } // catch (Exception ex) { } // finally // { // if (polyline != null) // Marshal.ReleaseComObject(polyline); // } //} moveToPoint = Listpoint[0].Point; Listpoint.RemoveAt(0); } } if (moveToPoint != null) { IPointCollection points = geometry as IPointCollection; var index = -1; for (int i = 0; i < points.PointCount - 1; i++) { IPoint tPoint = points.Point[i]; var refdistance = Math.Sqrt((point.X - tPoint.X) * (point.X - tPoint.X) + (point.Y - tPoint.Y) * (point.Y - tPoint.Y)); if (refdistance == 0 || Math.Abs(refdistance) < (1e-5)) { index = i; break; } } if (index > -1) { var refdistance = Math.Sqrt((point.X - moveToPoint.X) * (point.X - moveToPoint.X) + (point.Y - moveToPoint.Y) * (point.Y - moveToPoint.Y)); if (refdistance == 0) continue; points.UpdatePoint(index, moveToPoint); listmoveToPoint.Add($"{moveToPoint.X},{moveToPoint.Y}"); } } } } catch (Exception ex) { return null; } return geometry; } /// /// 延长线段 /// /// 传入去的线 /// 模式,1为从FromPoint处延长,2为从ToPint处延长,3为两端延长 /// 延长的距离 /// /// 创建人:懒羊羊 public static IPolyline getExtendLine(IPolyline passLine, int mode, double dis) { IPointCollection pPointCol = passLine as IPointCollection; switch (mode) { case 1: IPoint fromPoint = new PointClass(); passLine.QueryPoint(esriSegmentExtension.esriExtendAtFrom, -1 * dis, false, fromPoint); pPointCol.InsertPoints(0, 1, ref fromPoint); break; case 2: IPoint endPoint = new PointClass(); object missing = Type.Missing; passLine.QueryPoint(esriSegmentExtension.esriExtendAtTo, dis + passLine.Length, false, endPoint); pPointCol.AddPoint(endPoint, ref missing, ref missing); break; case 3: IPoint fPoint = new PointClass(); IPoint ePoint = new PointClass(); object missing2 = Type.Missing; passLine.QueryPoint(esriSegmentExtension.esriExtendAtFrom, -1 * dis, false, fPoint); pPointCol.InsertPoints(0, 1, ref fPoint); passLine.QueryPoint(esriSegmentExtension.esriExtendAtTo, dis + passLine.Length, false, ePoint); pPointCol.AddPoint(ePoint, ref missing2, ref missing2); break; default: return pPointCol as IPolyline; } return pPointCol as IPolyline; } /// /// 捕捉 /// /// /// /// /// /// private static List Snapping(IPoint point, IFeatureLayer m_featureLayer, double distance) { double tol = 0.1; ITopologicalOperator pTopo = point as ITopologicalOperator; IGeometry pGeometry = pTopo.Buffer(tol).Envelope as IGeometry; IIdentify indentify = m_featureLayer as IIdentify; if (indentify == null) return null; IArray pIDs = indentify.Identify(pGeometry); if (pIDs == null || pIDs.Count == 0) return null; List pointList = new List(); for (int index = 0; index < pIDs.Count; index++) { IFeatureIdentifyObj pFeatIdObj = pIDs.get_Element(index) as IFeatureIdentifyObj; IRowIdentifyObject pRowObj = pFeatIdObj as IRowIdentifyObject; IFeature iF = pRowObj.Row as IFeature; IPoint iHitPt = new ESRI.ArcGIS.Geometry.Point(); IHitTest iHitTest = iF.Shape as IHitTest; double hitDist = 0; int partIndex = 0; int vertexIndex = 0; bool bRightSide = false; if (iHitTest.HitTest(point, tol, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { //var distance1 = Math.Sqrt((point.X - iHitPt.X) * (point.X - iHitPt.X) + (point.Y - iHitPt.Y) * (point.Y - iHitPt.Y)); //if (distance1 == 0) continue; point = iHitPt; pointList.Add(new MovePointStruct() { Feature = iF, Geometry = iF.Shape, PartIndex = partIndex, VertexIndex = vertexIndex }); } } //this.m_hookHelper.ActiveView.Refresh(); return pointList; } private static List Snapping2(IPoint point, List m_featureLayer, double distance) { double tol = 0.1; ITopologicalOperator pTopo = point as ITopologicalOperator; IGeometry pGeometry = pTopo.Buffer(tol).Envelope as IGeometry; IIdentify indentify = m_featureLayer as IIdentify; if (indentify == null) return null; IArray pIDs = indentify.Identify(pGeometry); if (pIDs == null || pIDs.Count == 0) return null; List pointList = new List(); foreach (IGeometry geometry in m_featureLayer) { IPoint iHitPt = new ESRI.ArcGIS.Geometry.Point(); IHitTest iHitTest = geometry as IHitTest; double hitDist = 0; int partIndex = 0; int vertexIndex = 0; bool bRightSide = false; if (iHitTest.HitTest(point, tol, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { point = iHitPt; pointList.Add(new MovePointStruct() { Geometry = geometry, PartIndex = partIndex, VertexIndex = vertexIndex }); } } return pointList; } private static Dictionary GetSnappingpoint(IPoint point, IFeatureLayer m_featureLayer, double distance = 1) { Dictionary pointList = new Dictionary(); try { ITopologicalOperator pTopo = point as ITopologicalOperator; IGeometry pGeometry = pTopo.Buffer(distance).Envelope as IGeometry; IIdentify indentify = m_featureLayer as IIdentify; if (indentify == null) return pointList; IArray pIDs = indentify.Identify(pGeometry); if (pIDs == null || pIDs.Count == 0) return pointList; for (int index = 0; index < pIDs.Count; index++) { IFeatureIdentifyObj pFeatIdObj = pIDs.get_Element(index) as IFeatureIdentifyObj; IRowIdentifyObject pRowObj = pFeatIdObj as IRowIdentifyObject; IFeature iF = pRowObj.Row as IFeature; IPoint iHitPt = new Point(); IHitTest iHitTest = iF.Shape as IHitTest; double hitDist = 0; int partIndex = 0; int vertexIndex = 0; bool bRightSide = false; if (iHitTest.HitTest(point, distance, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { //point = iHitPt; IPolyline tempLine = new PolylineClass(); tempLine.FromPoint = iHitPt; bool isExit = false; foreach (var tempPoint in pointList.Keys) { tempLine.ToPoint = tempPoint; if (tempLine.Length < 0.00005) isExit = true; } if (!isExit) { IArray pTempIDs = indentify.Identify(iHitPt); int num = 0; for (int i = 0; i < pTempIDs.Count; i++) { pFeatIdObj = pTempIDs.get_Element(i) as IFeatureIdentifyObj; pRowObj = pFeatIdObj as IRowIdentifyObject; iHitTest = ((pRowObj.Row as IFeature).Shape) as IHitTest; IPoint iHitPt1 = new ESRI.ArcGIS.Geometry.Point(); if (iHitTest.HitTest(iHitPt, 0.0001, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt1, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { if (hitDist == 0) num++; } } if (iHitPt.X == point.X && point.Y == iHitPt.Y) continue; pointList.Add(iHitPt, num); } } else if (iHitTest.HitTest(point, distance, esriGeometryHitPartType.esriGeometryPartBoundary, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { //取距离boundary最近的点 IGeometryCollection collection = iF.ShapeCopy as IGeometryCollection; IGeometry geo = collection.get_Geometry(partIndex); ISegmentCollection points = geo as ISegmentCollection; ISegment pt = points.Segment[vertexIndex]; IPoint point1 = new PointClass(); var DistanceAlongCurve = 0.0001; var distanceFromCurve = 0.0001; bRightSide = true; pt.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, point, false, point1, ref DistanceAlongCurve, ref distanceFromCurve, bRightSide); IPolyline tempLine = new PolylineClass(); tempLine.FromPoint = iHitPt; bool isExit = false; foreach (var tempPoint in pointList.Keys) { tempLine.ToPoint = tempPoint; if (tempLine.Length < 0.00005) isExit = true; } if (!isExit) { pointList.Add(point1, 1); } } } } catch (Exception ex) { LogAPI.Debug($"GetSnappingpoint异常:{ex.Message + ex.StackTrace}"); } return pointList; } private static List GetSnappingpoint1(IPoint point, IFeatureLayer m_featureLayer, double distance = 1) { List pointList = new List(); try { ITopologicalOperator pTopo = point as ITopologicalOperator; IGeometry pGeometry = pTopo.Buffer(distance).Envelope as IGeometry; IIdentify indentify = m_featureLayer as IIdentify; if (indentify == null) return pointList; IArray pIDs = indentify.Identify(pGeometry); if (pIDs == null || pIDs.Count == 0) return pointList; for (int index = 0; index < pIDs.Count; index++) { List listoid = new List(); IFeatureIdentifyObj pFeatIdObj = pIDs.get_Element(index) as IFeatureIdentifyObj; IRowIdentifyObject pRowObj = pFeatIdObj as IRowIdentifyObject; IFeature iF = pRowObj.Row as IFeature; IPoint iHitPt = new Point(); IHitTest iHitTest = iF.Shape as IHitTest; double hitDist = 0; int partIndex = 0; int vertexIndex = 0; bool bRightSide = false; if (iHitTest.HitTest(point, distance, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { //point = iHitPt; IPolyline tempLine = new PolylineClass(); tempLine.FromPoint = iHitPt; bool isExit = false; foreach (var tempPoint in pointList) { tempLine.ToPoint = tempPoint.Point; if (tempLine.Length < 0.00005) { listoid.Add(iF.OID); isExit = true; } } if (!isExit) { IArray pTempIDs = indentify.Identify(iHitPt); int num = 0; for (int i = 0; i < pTempIDs.Count; i++) { pFeatIdObj = pTempIDs.get_Element(i) as IFeatureIdentifyObj; pRowObj = pFeatIdObj as IRowIdentifyObject; IFeature iF1 = pRowObj.Row as IFeature; iHitTest = ((pRowObj.Row as IFeature).Shape) as IHitTest; IPoint iHitPt1 = new ESRI.ArcGIS.Geometry.Point(); if (iHitTest.HitTest(iHitPt, 0.0001, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt1, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { if (hitDist == 0) { listoid.Add(iF1.OID); num++; } } } if (iHitPt.X == point.X && point.Y == iHitPt.Y) continue; pointList.Add(new ConcurrentClass() { Point = iHitPt, ConcurrentCount = num, ListObjectID = listoid }); } } else if (iHitTest.HitTest(point, distance, esriGeometryHitPartType.esriGeometryPartBoundary, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { //取距离boundary最近的点 IGeometryCollection collection = iF.ShapeCopy as IGeometryCollection; IGeometry geo = collection.get_Geometry(partIndex); ISegmentCollection points = geo as ISegmentCollection; ISegment pt = points.Segment[vertexIndex]; IPoint point1 = new PointClass(); var DistanceAlongCurve = 0.0001; var distanceFromCurve = 0.0001; bRightSide = true; pt.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, point, false, point1, ref DistanceAlongCurve, ref distanceFromCurve, bRightSide); IPolyline tempLine = new PolylineClass(); tempLine.FromPoint = iHitPt; bool isExit = false; foreach (var tempPoint in pointList) { tempLine.ToPoint = tempPoint.Point; if (tempLine.Length < 0.00005) isExit = true; } if (!isExit) { listoid.Add(iF.OID); pointList.Add(new ConcurrentClass() { Point = point1, ConcurrentCount = 1, ListObjectID = listoid }); } } } } catch (Exception ex) { LogAPI.Debug($"GetSnappingpoint异常:{ex.Message + ex.StackTrace}"); } return pointList; } private static List GetSnappingpoint2(IPoint point, List m_featureLayer, List listmoveToPoint = null, double distance = 1) { List pointList = new List(); try { foreach (IGeometry geometry in m_featureLayer) { IPoint iHitPt = new Point(); IHitTest iHitTest = geometry as IHitTest; double hitDist = 0; int partIndex = 0; int vertexIndex = 0; bool bRightSide = false; if (iHitTest.HitTest(point, distance, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { IPolyline tempLine = new PolylineClass(); tempLine.FromPoint = iHitPt; bool isExit = false; foreach (var tempPoint in pointList) { tempLine.ToPoint = tempPoint.Point; if (tempLine.Length < 0.00005) { isExit = true; } } if (!isExit) { int num = 0; foreach (IGeometry item in m_featureLayer) { iHitTest = item as IHitTest; IPoint iHitPt1 = new ESRI.ArcGIS.Geometry.Point(); if (iHitTest.HitTest(iHitPt, 0.0001, esriGeometryHitPartType.esriGeometryPartVertex, iHitPt1, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { if (hitDist == 0) num++; } } if (iHitPt.X == point.X && point.Y == iHitPt.Y) continue; IPoint PrevPoint = null; IPoint NextPoint = null; pointList.Add(new ConcurrentClass() { Point = iHitPt, ConcurrentCount = num, FootPoint = false, angle = GetRelativeAngle(geometry, iHitPt, ref PrevPoint, ref NextPoint) }); if (listmoveToPoint.Contains($"{iHitPt.X}{iHitPt.Y}")) { IPoint PrevPoint1 = null; IPoint NextPoint1 = null; var pointdistance = Math.Sqrt((point.X - PrevPoint.X) * (point.X - PrevPoint.X) + (point.Y - PrevPoint.Y) * (point.Y - PrevPoint.Y)); if (pointdistance < 1) pointList.Add(new ConcurrentClass() { Point = PrevPoint, ConcurrentCount = num, FootPoint = false, angle = GetRelativeAngle(geometry, PrevPoint, ref PrevPoint1, ref NextPoint1) }); pointdistance = Math.Sqrt((point.X - NextPoint.X) * (point.X - NextPoint.X) + (point.Y - NextPoint.Y) * (point.Y - NextPoint.Y)); if (pointdistance < 1) pointList.Add(new ConcurrentClass() { Point = NextPoint, ConcurrentCount = num, FootPoint = false, angle = GetRelativeAngle(geometry, NextPoint, ref PrevPoint1, ref NextPoint1) }); } } } else if (iHitTest.HitTest(point, distance, esriGeometryHitPartType.esriGeometryPartBoundary, iHitPt, ref hitDist, ref partIndex, ref vertexIndex, ref bRightSide)) { //取距离boundary最近的点 IGeometryCollection collection = geometry as IGeometryCollection; IGeometry geo = collection.get_Geometry(partIndex); ISegmentCollection points = geo as ISegmentCollection; ISegment pt = points.Segment[vertexIndex]; IPoint point1 = new PointClass(); var DistanceAlongCurve = 0.0001; var distanceFromCurve = 0.0001; bRightSide = true; pt.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, point, false, point1, ref DistanceAlongCurve, ref distanceFromCurve, bRightSide); IPolyline tempLine = new PolylineClass(); tempLine.FromPoint = iHitPt; bool isExit = false; foreach (var tempPoint in pointList) { tempLine.ToPoint = tempPoint.Point; if (tempLine.Length < 0.00005) isExit = true; } if (!isExit) { pointList.Add(new ConcurrentClass() { Point = point1, ConcurrentCount = 1, FootPoint = true }); } } } } catch (Exception ex) { LogAPI.Debug($"GetSnappingpoint异常:{ex.Message + ex.StackTrace}"); } return pointList; } /// /// 线转面 /// /// 线对象 /// IGeometry 面对象 public static IGeometry ConstructPolygonFromPolyline(IPolyline pPolyline) { IGeometry newGeometry = null; try { IGeometryCollection pPolygonGeoCol = new PolygonClass(); if (pPolyline == null || pPolyline.IsEmpty) { return pPolygonGeoCol as IGeometry; } IGeometryCollection pPolylineGeoCol = pPolyline as IGeometryCollection; ISegmentCollection pSegCol = new RingClass(); ISegment pSegment = null; object missing = Type.Missing; for (int i = 0; i < pPolylineGeoCol.GeometryCount; i++) { ISegmentCollection pPolylineSegCol = pPolylineGeoCol.get_Geometry(i) as ISegmentCollection; for (int j = 0; j < pPolylineSegCol.SegmentCount; j++) { pSegment = pPolylineSegCol.get_Segment(j); pSegCol.AddSegment(pSegment, ref missing, ref missing); } pPolygonGeoCol.AddGeometry(pSegCol as IGeometry, ref missing, ref missing); } newGeometry = pPolygonGeoCol as IGeometry; if (newGeometry != null && !newGeometry.IsEmpty) { ITopologicalOperator topologicalOperator = newGeometry as ITopologicalOperator; if (!topologicalOperator.IsKnownSimple) { topologicalOperator.Simplify(); } } } catch (Exception ex) { throw ex; } return newGeometry; } private static IGeometry PolygonToPolyline(IGeometry pGeo) { try { if (pGeo == null) { return null; } if (!(pGeo is Ring ring)) { return null; } IPointCollection pointCollection = ring; IGeometryCollection geometryCollection = new PolylineClass(); for (int i = 1; i < pointCollection.PointCount; i++) { LineClass lineClass = new LineClass(); ((ILine)lineClass).SpatialReference = pGeo.SpatialReference; ((ILine)lineClass).PutCoords(pointCollection.get_Point(i - 1), pointCollection.get_Point(i)); ISegment inSegment = lineClass as ISegment; ISegmentCollection segmentCollection = new PathClass(); object before = Type.Missing; segmentCollection.AddSegment(inSegment, ref before, ref before); geometryCollection.AddGeometry(segmentCollection as IGeometry, ref before, ref before); } return geometryCollection as IGeometry; } catch (Exception ex) { throw ex; } } #region 尖锐角处理 /// /// 尖锐角处理 /// /// /// /// /// public static IGeometry ResolveAcuteAngle(IGeometry geometry, List pointList, double angle, IGeometry Repairgeometry = null, bool isjcdltb = false) { try { if (pointList != null && angle > 0 && pointList.Count > 0) { IPolyline polyline1 = new PolylineClass(); IPolyline polyline1_vertical = null; IPolyline polyline2_vertical = null; IPolyline polyline2 = new PolylineClass(); if (pointList.Count == 3) { polyline1.SpatialReference = pointList[0].SpatialReference; polyline1.FromPoint = pointList[1]; polyline1.ToPoint = pointList[0]; polyline1_vertical = GetPerpendicularLine(polyline1, true);//垂线 polyline2.SpatialReference = pointList[0].SpatialReference; polyline2.FromPoint = pointList[1]; polyline2.ToPoint = pointList[0]; polyline2_vertical = GetPerpendicularLine(polyline2, false); } #region 计算点位置 IPoint length1Point = new PointClass(); if (polyline1_vertical != null) length1Point = polyline1_vertical.ToPoint; IPoint length2Point = new PointClass(); if (polyline2_vertical != null) length2Point = polyline2_vertical.ToPoint; #endregion IPointCollection pointCollection1 = new MultipointClass(); pointCollection1.AddPoint(length1Point); pointCollection1.AddPoint(pointList[1]); pointCollection1.AddPoint(pointList[0]); IGeometry geometry1 = GenerateGeometryFromPoints(pointCollection1); geometry1.SpatialReference = geometry.SpatialReference; IPointCollection pointCollection2 = new MultipointClass(); pointCollection2.AddPoint(length2Point); pointCollection2.AddPoint(pointList[1]); pointCollection2.AddPoint(pointList[0]); IGeometry geometry2 = GenerateGeometryFromPoints(pointCollection2); geometry2.SpatialReference = geometry.SpatialReference; if (Repairgeometry != null) { Repairgeometry.SpatialReference = geometry.SpatialReference; if (isjcdltb) { if (FeatureAPI.IsContains(Repairgeometry, geometry1)) { } else { geometry1 = geometry2; } } else { IGeometry InterSect = FeatureAPI.InterSect(Repairgeometry, geometry1); if (InterSect != null && InterSect.GetEllipseArea() == 0) { geometry1 = geometry2; } } } if (FeatureAPI.IsContains(geometry, geometry1)) { geometry = FeatureAPI.Difference(geometry, geometry1 as IPolygon); } else { geometry = FeatureAPI.Union(geometry, geometry1 as IPolygon); } } pointList = null; angle = 0; if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle)) { if (angle < 10) geometry = ResolveAcuteAngle(geometry, pointList, angle, Repairgeometry); } else { return geometry; } } catch (Exception ex) { throw ex; } return geometry; } /// /// 解决狭长图形问题 /// /// /// public static IGeometry ResolveLongAndNarrow(IGeometry geometry) { List pointList = null; double angle = 0; try { ///向内缓冲,如果还存在狭长的图形,暂不做处理 ITopologicalOperator topo = geometry as ITopologicalOperator; IGeometry geo = topo.Buffer(-0.05); if (AECommonHelper.SharpAngleDataCheck(geo, ref pointList, ref angle)) { } else { geometry = geo; } } catch (Exception ex) { return geometry; } return geometry; } public static IGeometry SharpAngleMerge(IGeometry geometry, List points, IGeometry uniongeo = null) { List pointList = null; double angle = 0; try { if (geometry != null && !geometry.IsEmpty && points != null && points.Count == 3) { IPointCollection pointCollection2 = new MultipointClass(); pointCollection2.AddPoint(points[0]); pointCollection2.AddPoint(points[1]); pointCollection2.AddPoint(points[2]); IGeometry sharpgeo = GenerateGeometryFromPoints(pointCollection2); sharpgeo.SpatialReference = geometry.SpatialReference; var mj = sharpgeo.GetEllipseArea(); var geomj = geometry.GetEllipseArea(); if (!sharpgeo.IsEmpty && mj < geomj) { geometry = FeatureAPI.Difference(geometry, sharpgeo); if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle)) { if (uniongeo == null) { uniongeo = sharpgeo; uniongeo.SpatialReference = geometry.SpatialReference; } else { if (FeatureAPI.IsAdjacent(uniongeo, sharpgeo)) { uniongeo = FeatureAPI.Union(uniongeo, sharpgeo); } else { } } geometry = SharpAngleMerge(geometry, pointList, uniongeo); } else { if (uniongeo != null) { uniongeo = FeatureAPI.Union(uniongeo, sharpgeo); geometry = uniongeo; } return sharpgeo; } } } } catch (Exception ex) { return geometry; } return geometry; } /// /// 擦除图形本身存在的尖锐角 /// /// /// /// /// public static IGeometry SharpAngleErase(IGeometry geometry, List points, IGeometry Erasegeo = null) { List pointList = null; double angle = 0; try { if (geometry != null && !geometry.IsEmpty && points != null && points.Count == 3) { IPointCollection pointCollection2 = new MultipointClass(); pointCollection2.AddPoint(points[0]); pointCollection2.AddPoint(points[1]); pointCollection2.AddPoint(points[2]); IGeometry sharpgeo = GenerateGeometryFromPoints(pointCollection2); sharpgeo.SpatialReference = geometry.SpatialReference; var mj = sharpgeo.GetEllipseArea(); var geomj = geometry.GetEllipseArea(); if (!sharpgeo.IsEmpty && mj < geomj) { geometry = FeatureAPI.Difference(geometry, sharpgeo); if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle)) { if (Erasegeo == null) { Erasegeo = sharpgeo; Erasegeo.SpatialReference = geometry.SpatialReference; } else { if (FeatureAPI.IsAdjacent(Erasegeo, sharpgeo)) { Erasegeo = FeatureAPI.Union(Erasegeo, sharpgeo); } else { } } geometry = SharpAngleErase(geometry, pointList, Erasegeo); } } } } catch (Exception ex) { return geometry; } return geometry; } /// /// /// /// /// clockwise顺时针 true为顺时针/false为逆时针 /// public static IPolyline GetPerpendicularLine(IPolyline baseLine, bool clockwise) { // 获取baseLine的第一个点作为起点 IPoint startPoint = baseLine.FromPoint; if (!startPoint.IsEmpty) { // 获取非起点的任一点 IPoint endPoint = baseLine.ToPoint; // 计算向量 double vectorX = endPoint.X - startPoint.X; double vectorY = endPoint.Y - startPoint.Y; // 旋转90度得到垂直向量 double perpendicularX = 0; double perpendicularY = 0; if (clockwise) { perpendicularX = -vectorY; perpendicularY = vectorX; } else { perpendicularX = vectorY; perpendicularY = -vectorX; } // 设置垂直向量的长度,这里假设为1 double length = 1; perpendicularX *= length / Math.Sqrt(perpendicularX * perpendicularX + perpendicularY * perpendicularY); perpendicularY *= length / Math.Sqrt(perpendicularX * perpendicularX + perpendicularY * perpendicularY); // 计算垂直线的终点 IPoint perpendicularEndPoint = new PointClass(); perpendicularEndPoint.X = startPoint.X + perpendicularX; perpendicularEndPoint.Y = startPoint.Y + perpendicularY; // 创建并返回垂直线 IPolyline perpendicularLine = new PolylineClass(); IPointCollection pointCollection = perpendicularLine as IPointCollection; pointCollection.AddPoint(startPoint); pointCollection.AddPoint(perpendicularEndPoint); return perpendicularLine; } return null; } /// /// 根据点集合生成图形 /// /// /// public static IGeometry GenerateGeometryFromPoints(IPointCollection Points) { Ring ring = new RingClass(); object missing = Type.Missing; ring.AddPointCollection(Points); IGeometryCollection pointPolygon = new PolygonClass(); pointPolygon.AddGeometry(ring as IGeometry, ref missing, ref missing); IPolygon polyGonGeo = pointPolygon as IPolygon; //polyGonGeo.Close(); polyGonGeo.SimplifyPreserveFromTo(); return polyGonGeo as IGeometry; } #endregion #region GetRelativeAngle /// /// 获取当前点与前后两个点之间的夹角的角度 /// /// /// /// private static double GetRelativeAngle(IGeometry geometry, IPoint point, ref IPoint PrevPoint, ref IPoint NextPoint) { double angle = -1; try { IPointCollection pointCollection = geometry as IPointCollection; var index = -1; for (int i = 0; i < pointCollection.PointCount - 1; i++) { if (Math.Abs(point.X - pointCollection.Point[i].X) < 0.0001 && Math.Abs(point.Y - pointCollection.Point[i].Y) < 0.0001) { index = i; break; } } PrevPoint = new Point(); if (index > 0) pointCollection.QueryPoint(index - 1, PrevPoint); if (index == 0) pointCollection.QueryPoint(pointCollection.PointCount - 2, PrevPoint); NextPoint = new Point(); if (index < pointCollection.PointCount) pointCollection.QueryPoint(index + 1, NextPoint); if (PrevPoint != null && !PrevPoint.IsEmpty) angle = AECommonHelper.GetAngle(PrevPoint, point, NextPoint); } catch (Exception ex) { angle = -1; } return angle; } #endregion } public class MovePointStruct { public IFeature Feature { get; set; } public IGeometry Geometry { get; set; } public int PartIndex { get; set; } public int VertexIndex { get; set; } } public class ConcurrentClass { /// /// 共点 /// public IPoint Point { get; set; } /// /// 共点个数 /// public int ConcurrentCount { get; set; } /// /// 所在图形 /// public List ListObjectID { get; set; } public bool FootPoint { get; set; } public double angle { get; set; } } }