using ESRI.ArcGIS.Geometry; using KGIS.Framework.AE; using KGIS.Framework.AE.GPHelper; using KGIS.Framework.Utils; using KGIS.Framework.Utils.ExtensionMethod; using Kingo.Plugin.EngineEditor.Model; using Kingo.PluginServiceInterface; using Kingo.PluginServiceInterface.Helper; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Kingo.Plugin.EngineEditor.helper { public static class BoundaryRepairHelper { public static IProjectedCoordinateSystem _SpatialReference { get; set; } public static void Execute(List repairs, List UnionList) { List ListDLTB = new List();//年末数据库 List RepairLayerZDK = new List();//边界修复多部件图斑新增的子地块 try { #region 生成年末库 for (int i = repairs.Count - 1; i >= 0; i--) { if (repairs[i].Geometry == null) repairs[i].Geometry = ConvertWKTAndSetSpatialRef(repairs[i].WKT, _SpatialReference); foreach (var item in repairs[i].ListReference) { ReferenceEntity dLTB_NMK = ListDLTB.FirstOrDefault(x => x.BSM == item.BSM); if (dLTB_NMK == null) { ReferenceEntity dLTB = DeepCopyByReflect(item); dLTB.RefGeometry = ConvertWKTAndSetSpatialRef(dLTB.RefWKT ?? GeometryConvertHelper.ConvertIGeoemtryToWKT(item.RefGeometry), _SpatialReference); ListDLTB.Add(dLTB); } } } #endregion #region 面积小于30平的,直接和相邻共边最长的图形合并,合并一整个子地块,再进行边界修复 for (int i = repairs.Count - 1; i >= 0; i--) { string dlbm = repairs[i].DLBM; if (repairs[i].Geometry == null) repairs[i].Geometry = ConvertWKTAndSetSpatialRef(repairs[i].WKT, _SpatialReference); if (repairs[i].Geometry == null || repairs[i].Geometry.IsEmpty) continue; if ((repairs[i].Geometry as IArea).Area < 30) { RepairEntity UnionZDK = null; double Unionlength = 0.00; foreach (RepairEntity currentZDK in repairs) { if (currentZDK.JCBH == repairs[i].JCBH) continue; if (currentZDK.Geometry == null) currentZDK.Geometry = ConvertWKTAndSetSpatialRef(currentZDK.WKT, _SpatialReference); if (currentZDK.Geometry == null || currentZDK.Geometry.IsEmpty) continue; ITopologicalOperator topologicalOperator1 = currentZDK.Geometry as ITopologicalOperator; if (topologicalOperator1 == null) continue; IGeometry geometryIntersect = topologicalOperator1.Intersect(repairs[i].Geometry, esriGeometryDimension.esriGeometry1Dimension); if (geometryIntersect == null || geometryIntersect.IsEmpty) continue; IPolyline polyline = geometryIntersect as IPolyline; if (polyline == null || polyline.IsEmpty) continue; double length = FeatureAPI.LengthOfSide(currentZDK.Geometry, repairs[i].Geometry); if (length < 0.01) continue; if (length > Unionlength) { Unionlength = length; UnionZDK = currentZDK; } } if (UnionZDK != null) { UnionZDK.Geometry = FeatureAPI.Union(UnionZDK.Geometry, repairs[i].Geometry); UnionZDK.WKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(UnionZDK.Geometry); UnionList.Add(repairs[i].OID); repairs.RemoveAt(i); } } } #endregion foreach (RepairEntity repair in repairs) { // 预存DLTB的Envelope(仅SHAPE非空的图斑) var dltbEnvelopes = ListDLTB.Where(jc => !string.IsNullOrEmpty(jc.RefWKT)) .Select(jc => new { DLTB = jc, Envelope = (jc.RefGeometry?.Envelope ?? ConvertWKTAndSetSpatialRef(jc.RefWKT, _SpatialReference).Envelope) }).ToList(); var candidateDLTBs = dltbEnvelopes.Where(item => AreEnvelopesIntersecting(repair.Geometry.Envelope, item.Envelope)).Select(item => item.DLTB).ToList(); foreach (ReferenceEntity jcfeature in candidateDLTBs) { if (string.IsNullOrEmpty(jcfeature.RefWKT)) continue;//图形为空的不参与后续图形的修复 IGeometry jcgeometry = jcfeature.RefGeometry == null ? ConvertWKTAndSetSpatialRef(jcfeature.RefWKT, _SpatialReference) : jcfeature.RefGeometry; if (FeatureAPI.IsInterSect(jcgeometry, repair.Geometry)) repair.ListReference.Add(new ReferenceEntity() { BSM = jcfeature.BSM, DLBM = jcfeature.DLBM, CZCSXM = jcfeature.CZCSXM, RefWKT = jcfeature.RefWKT, RefGeometry = jcgeometry }); } List entities = ExecuteRepair(repair); if (entities == null || entities.Count <= 0) { continue; } AddResultToAnalysisLayer(entities, ListDLTB, repairs, repair, RepairLayerZDK); } if (RepairLayerZDK != null && RepairLayerZDK.Count > 0) { foreach (RepairEntity item in RepairLayerZDK) { repairs.Add(item); } } } catch (Exception ex) { throw; } } public static List ExecuteRepair(RepairEntity repair) { List needAddReference = new List(); List jrjReference = new List(); try { if (repair == null) return null; #region 删除图形中的重复点(首位点除外) IGeometryCollection geomColl = repair.Geometry as IGeometryCollection; // 遍历所有子环(外环和内环) for (int i = 0; i < geomColl.GeometryCount; i++) { IGeometry subGeom = geomColl.get_Geometry(i); IRing ring = subGeom as IRing; // 环是闭合的线(IRing 继承自 IPolyline) if (ring == null) continue; // 处理当前环的重复点 RemoveDuplicatePointsInRing(ring); } #endregion #region 节点套合 #region 获取待修复图形的外接矩形并向外缓冲 IEnvelope geometryEnvelope = repair.Geometry.Envelope; double xMin = geometryEnvelope.XMin; double yMin = geometryEnvelope.YMin; double xMax = geometryEnvelope.XMax; double yMax = geometryEnvelope.YMax; IPoint lowerLeft = new PointClass(); lowerLeft.PutCoords(xMin, yMin); IPoint lowerRight = new PointClass(); lowerRight.PutCoords(xMax, yMin); IPoint upperRight = new PointClass(); upperRight.PutCoords(xMin, yMax); IPoint upperLeft = new PointClass(); upperLeft.PutCoords(xMax, yMax); IPolygon triangle = new PolygonClass(); IPointCollection trianglePoints = triangle as IPointCollection; trianglePoints.AddPoint(lowerLeft); trianglePoints.AddPoint(lowerRight); trianglePoints.AddPoint(upperLeft); trianglePoints.AddPoint(upperRight); ITopologicalOperator topo = triangle as ITopologicalOperator; topo.Simplify(); IGeometry geometry = topo.Buffer(2); #endregion List geometries = new List(); foreach (var item in repair.ListReference) { #region 获取变更图斑的外接矩形,向外缓冲 然后与基础库相交 IGeometry geo = FeatureAPI.InterSect(geometry, item.RefGeometry); if (geo != null && !geo.IsEmpty) { double area = (geo as IArea).Area; if (area > 0.1) { geometries.Add(geo); } } #endregion } repair.Geometry = PolygonBoundaryAligner.AlignPolygonBoundary(repair.Geometry, geometries, 0.1); #endregion #region 尖锐角检查与修复 List yspointList = null; double ysangle = 0; IGeometry restSharpGeo = null; if (!repair.Geometry.IsEmpty && SharpAngle.JudgmentSharpAngle(repair.Geometry, ref yspointList, ref ysangle)) { IGeometry repairGeo = SharpAngle.ProcessSharpAngles(repair.Geometry, 5); repairGeo.SpatialReference = _SpatialReference; restSharpGeo = FeatureAPI.Difference(repair.Geometry, repairGeo); repair.Geometry = repairGeo; if (restSharpGeo != null && !restSharpGeo.IsEmpty) { var area = (restSharpGeo as IArea); if (area != null && area.Area > 1) { List geometryList = FeatureAPI.DissolveGeometryByRing(restSharpGeo);//拆分多部件 foreach (IGeometry SharpGeo in geometryList) { if (SharpGeo == null || SharpGeo.IsEmpty) continue; ReferenceEntity referenceEntity = new ReferenceEntity(); referenceEntity.BSM = $"NMK_{repair.JCBH}_{Guid.NewGuid().ToTrim().Replace("-", "")}_SharpAngle"; referenceEntity.CZCSXM = repair.CZCSXM; referenceEntity.DLBM = repair.DLBM; referenceEntity.RefWKT = PluginServiceInterface.GeometryConvertHelper.ConvertIGeoemtryToWKT(SharpGeo); referenceEntity.RefGeometry = SharpGeo; referenceEntity.Modify = true; jrjReference.Add(referenceEntity); } } } } #endregion #region 狭长/局部狭长检查与修复 if (!repair.Geometry.IsEmpty) { var NarrowAreas = PolygonNarrowAreaChecker.CheckLocalNarrowAreas(repair.Geometry as IPolygon); if (NarrowAreas != null && NarrowAreas.Count > 0) { foreach (var item in NarrowAreas) { if (!FeatureAPI.IsInterSect(item, repair.Geometry)) { repair.Geometry = FeatureAPI.Union(repair.Geometry, item); } else { repair.Geometry = FeatureAPI.Difference(repair.Geometry, item); } } } } #endregion //尖锐角/狭长图形修复完以后,图形为空直接返回,删除当前子地块 if (repair.Geometry.IsEmpty) return repair.ListReference; #region 压盖带一个参考图形 if (repair.ListReference != null && repair.ListReference.Count == 1) { ReferenceEntity jcdltb = repair.ListReference[0]; #region 面积相差小于1的 直接使用基础库图形 var refmj = (jcdltb.RefGeometry as IArea).Area; var geomj = (repair.Geometry as IArea).Area; if (refmj == geomj || Math.Abs(refmj - geomj) < 1) { repair.ListReference.Add( new ReferenceEntity() { BSM = $"NMK_{repair.JCBH}", CZCSXM = repair.CZCSXM, DLBM = repair.DLBM, RefWKT = jcdltb.RefWKT, Modify = true }); jcdltb.Modify = true; jcdltb.RefWKT = ""; jcdltb.RefGeometry = null; return repair.ListReference; } #endregion #region 图形在基础数据内部 且被动变更图斑不存在尖锐角/狭长图形 IGeometry diffGeo = FeatureAPI.Difference(jcdltb.RefGeometry, repair.Geometry); List geos = FeatureAPI.DissolveGeometryByRing(diffGeo); if (geos != null && geos.Count > 0) { bool iscontinue = true; foreach (IGeometry diff in geos) { if (diff == null || diff.IsEmpty) continue; double area = (diff as IArea).Area; if (area < 1) { iscontinue = false; break; } if (SharpAngle.JudgmentSharpAngle(diff, ref yspointList, ref ysangle)) { iscontinue = false; break; } List NarrowAreas = PolygonNarrowAreaChecker.CheckLocalNarrowAreas(diff as IPolygon); if (NarrowAreas != null && NarrowAreas.Count > 0) { iscontinue = false; break; } } if (iscontinue) { if (geos.Count == 1) { jcdltb.RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(geos[0]); jcdltb.RefGeometry = geos[0]; jcdltb.Modify = true; } else { IGeometry difference = FeatureAPI.Difference(jcdltb.RefGeometry, repair.Geometry); if (difference != null && !difference.IsEmpty) { jcdltb.RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(difference); jcdltb.RefGeometry = difference; jcdltb.Modify = true; } } repair.ListReference.Add( new ReferenceEntity() { BSM = $"NMK_{repair.JCBH}", CZCSXM = repair.CZCSXM, DLBM = repair.DLBM, RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(repair.Geometry), Modify = true }); if (jrjReference.Count > 0) { foreach (ReferenceEntity item in repair.ListReference.FindAll(x => x.Modify && !x.BSM.Contains("NMK_"))) { if (item.RefGeometry == null || item.RefGeometry.IsEmpty) continue; item.RefGeometry = FeatureAPI.Difference(item.RefGeometry, restSharpGeo); if (item.RefGeometry == null || item.RefGeometry.IsEmpty) continue; item.RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(item.RefGeometry); } repair.ListReference.AddRange(jrjReference); } return repair.ListReference; } } #endregion if (repair.ListReference != null && repair.ListReference.Count >= 1) { foreach (ReferenceEntity jcfc in repair.ListReference) { #region 与基础库相交 if (repair.Geometry.IsEmpty) break; IGeometry InterArearesult = FeatureAPI.InterSect(jcfc.RefGeometry, repair.Geometry); if (InterArearesult != null) { if (InterArearesult == null || InterArearesult.IsEmpty) continue;//未相交到或相交为空图形的直接跳过 double area = (InterArearesult as IArea).Area; if (area < 1)//相交面积小于1的图形擦除 { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) //{ // jcfc.IsReference = true; continue; //} IGeometry result = FeatureAPI.Difference(repair.Geometry, InterArearesult); if (result != null && !result.IsEmpty) { repair.Geometry = result; continue; } } else if (area > 1 && area < 10) { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) //{ // jcfc.IsReference = true; continue; //} //相交面积小于10且相交图形为尖锐角或者狭长图形的擦除 if (SharpAngle.JudgmentSharpAngle(InterArearesult, ref yspointList, ref ysangle)) { IGeometry result = FeatureAPI.Difference(repair.Geometry, InterArearesult); if (result != null && !result.IsEmpty) repair.Geometry = result; continue; } else { jcfc.IsReference = true; continue; } } else { //参与图形修复的基础库 jcfc.IsReference = true; continue; } } #endregion } } else { return repair.ListReference; } } #endregion if (repair.ListReference != null && repair.ListReference.Count >= 1) { foreach (ReferenceEntity jcfc in repair.ListReference) { #region 与基础库相交 if (repair.Geometry.IsEmpty) break; IGeometry InterArearesult = FeatureAPI.InterSect(jcfc.RefGeometry, repair.Geometry); if (InterArearesult != null) { if (InterArearesult == null || InterArearesult.IsEmpty) continue;//未相交到或相交为空图形的直接跳过 double area = (InterArearesult as IArea).Area; if (area < 1)//相交面积小于1的图形擦除 { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) //{ // jcfc.IsReference = true; continue; //} IGeometry result = FeatureAPI.Difference(repair.Geometry, InterArearesult); if (result != null && !result.IsEmpty) { repair.Geometry = result; continue; } } else if (area > 1 && area < 10) { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) //{ // jcfc.IsReference = true; continue; //} //相交面积小于10且相交图形为尖锐角或者狭长图形的擦除 if (SharpAngle.JudgmentSharpAngle(InterArearesult, ref yspointList, ref ysangle)) { IGeometry result = FeatureAPI.Difference(repair.Geometry, InterArearesult); if (result != null && !result.IsEmpty) repair.Geometry = result; continue; } else { jcfc.IsReference = true; continue; } } else { //参与图形修复的基础库 jcfc.IsReference = true; continue; } } #endregion if (!jcfc.IsReference) continue; #region 与基础库不相交的面积 IGeometry diffresult = FeatureAPI.Difference(jcfc.RefGeometry, repair.Geometry); if (diffresult != null && !diffresult.IsEmpty) { List pointList1 = null; double angle = 0; double area = (diffresult as IArea).Area; if (area < 1)//未相交面积小于1的图形合并 { if (FeatureAPI.IsAdjacent(repair.Geometry, diffresult)) { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) continue;//线状地物不与碎图斑合并 IGeometry unionresult = FeatureAPI.Union(repair.Geometry, diffresult); if (unionresult != null && !unionresult.IsEmpty) { repair.Geometry = unionresult; } } } else if (area < 10 && AECommonHelper.SharpAngleDataCheck(diffresult, ref pointList1, ref angle)) { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) continue;//线状地物不与碎图斑合并 if (FeatureAPI.IsAdjacent(repair.Geometry, diffresult)) { IGeometry unionresult = FeatureAPI.Union(repair.Geometry, diffresult); if (unionresult != null && unionresult != null) { repair.Geometry = unionresult; } } } else { #region 被动变更小于30平且相邻的图斑与当前图斑合并 //小于30平的合并问题还需要验证 if (area < 30) { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) continue;//线状地物不与碎图斑合并 if (FeatureAPI.IsAdjacent(repair.Geometry, diffresult)) { IGeometry unionresult = FeatureAPI.Union(repair.Geometry, diffresult); if (unionresult != null && unionresult != null) { repair.Geometry = unionresult; } } } #endregion } } #endregion } if (repair.Geometry.IsEmpty) return repair.ListReference; if (repair.ListReference.Where(x => x.IsReference).ToList().Count == 1) { ReferenceEntity jcdltb = repair.ListReference.Where(x => x.IsReference).ToList().FirstOrDefault(); #region 压盖带一个参考图形 #region 面积相差小于1的 直接使用基础库图形 jcdltb.EllipseArea = (jcdltb.RefGeometry as IArea).Area; var geomj = (repair.Geometry as IArea).Area; if (jcdltb.EllipseArea == geomj || Math.Abs(jcdltb.EllipseArea - geomj) < 1) { //基础数据库存在多部件,且面积较小的图形,删掉对应的碎图斑 string RefWKT = jcdltb.RefWKT; jcdltb.RefWKT = ""; jcdltb.Modify = true; jcdltb.RefGeometry = null; repair.ListReference.Add(new ReferenceEntity() { BSM = $"NMK_{repair.JCBH}", CZCSXM = repair.CZCSXM, DLBM = repair.DLBM, RefWKT = RefWKT, Modify = true //IsNeedAddNewZDK = false }); return repair.ListReference; } #endregion #region 图形在基础数据内部 且被动变更图斑不存在尖锐角/狭长图形 bool iscontinue = true; IGeometry diffresult = FeatureAPI.Difference(jcdltb.RefGeometry, repair.Geometry); if (diffresult != null && !diffresult.IsEmpty) { List pointList = null; double angle = 0; if (SharpAngle.JudgmentSharpAngle(diffresult, ref pointList, ref angle) || PolygonNarrowAreaChecker.CheckLocalNarrowAreas(diffresult as IPolygon).Count > 0) { iscontinue = false; } foreach (var item in repair.ListReference) { if (item.BSM == jcdltb.BSM) continue; if (FeatureAPI.IsInterSect(item.RefGeometry, diffresult)) { iscontinue = false; break; } } if (iscontinue) { //Difference 擦除的结果与修复后的repair.Geometry 存在误差范围内的差别 //repair.Geometry = FeatureAPI.Difference(jcdltb.RefGeometry, Difference); #region 出现多部件的图形,需要进行节点修复逻辑 List geometryList = FeatureAPI.DissolveGeometryByRing(repair.Geometry);//拆分多部件 if (geometryList.Count > 1) { LogAPI.Debug($"jcbh:{repair.JCBH},的图斑,BoundaryRepairHelper.ExecuteRepair方法中的 出现多部件的图形,需要进行节点修复逻辑,geometryList.Count > 1的相关逻辑暂未处理 ! "); } else { if (diffresult.IsEmpty) { jcdltb.RefWKT = ""; jcdltb.RefGeometry = null; } else { jcdltb.RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(diffresult); jcdltb.RefGeometry = diffresult; } jcdltb.Modify = true; repair.ListReference.Add(new ReferenceEntity() { BSM = $"NMK_{repair.JCBH}", CZCSXM = repair.CZCSXM, DLBM = repair.DLBM, RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(repair.Geometry), Modify = true, //Describe = "图形修复:" }); if (jrjReference.Count > 0) { foreach (var item in repair.ListReference.FindAll(x => x.Modify && !x.BSM.Contains("NMK_"))) { if (item.RefGeometry == null || item.RefGeometry.IsEmpty) continue; item.RefGeometry = FeatureAPI.Difference(item.RefGeometry, restSharpGeo); if (item.RefGeometry == null || item.RefGeometry.IsEmpty) continue; item.RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(item.RefGeometry); } repair.ListReference.AddRange(jrjReference); } return repair.ListReference; } #endregion } } #endregion #endregion } #region 没有参考基础库 if (repair.ListReference.Where(x => x.IsReference).ToList().Count == 0) return repair.ListReference; #endregion geometries.Clear(); foreach (var item in repair.ListReference) { if (!item.IsReference) continue; geometries.Add(item.RefGeometry); } List geometrys = ExecuteBoundaryRepair(repair, geometries); if (geometrys != null) { foreach (var item in geometrys) { if (item.IsEmpty || item as IArea == null || (item as IArea).Area == 0) continue; foreach (ReferenceEntity jcdltb in repair.ListReference) { if (!jcdltb.IsReference) continue; IGeometry diff = FeatureAPI.Difference(jcdltb.RefGeometry, item); if (diff == null || diff.IsEmpty || (diff as IArea).Area == 0) { jcdltb.RefWKT = ""; jcdltb.RefGeometry = null; jcdltb.Modify = true; } else { jcdltb.RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(diff); jcdltb.RefGeometry = diff; jcdltb.Modify = true; } } ReferenceEntity referenceEntity = new ReferenceEntity { BSM = $"NMK_{repair.JCBH}", CZCSXM = repair.CZCSXM, DLBM = repair.DLBM, RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(item), RefGeometry = item, Modify = true }; if (repair.ListReference.FirstOrDefault(x => x.BSM == referenceEntity.BSM) != null) { referenceEntity.BSM = $"NMK_{repair.JCBH}_{Guid.NewGuid().ToTrim().Replace("-", "")}"; } repair.ListReference.Add(referenceEntity); } } } else { return repair.ListReference; } if (jrjReference.Count > 0) { foreach (ReferenceEntity item in repair.ListReference.FindAll(x => x.Modify && !x.BSM.Contains("NMK_"))) { if (item.RefGeometry == null || item.RefGeometry.IsEmpty) continue; item.RefGeometry = FeatureAPI.Difference(item.RefGeometry, restSharpGeo); if (item.RefGeometry == null || item.RefGeometry.IsEmpty) continue; item.RefWKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(item.RefGeometry); } repair.ListReference.AddRange(jrjReference); } } catch (Exception ex) { LogAPI.Debug("执行边界修复失败:\r\n"); LogAPI.Debug(ex); throw ex; } return repair.ListReference; } #region 节点去重 private static void RemoveDuplicatePointsInRing(IRing ring) { IPointCollection pointColl = ring as IPointCollection; if (pointColl == null) return; // 从第 1 个点开始(索引 1),向前比较(避免越界) for (int i = 1; i < pointColl.PointCount;) { IPoint currentPoint = pointColl.get_Point(i); IPoint prevPoint = pointColl.get_Point(i - 1); // 检查坐标是否完全一致(X、Y、Z、M 均相等) if (currentPoint.X == prevPoint.X && currentPoint.Y == prevPoint.Y) { // 删除当前重复点(删除后后续点索引前移,i 不递增) pointColl.RemovePoints(i, 1); } else { i++; // 无重复,继续下一个点 } } // 重新闭合环(确保最后一个点与第一个点一致,避免几何无效) ring.Close(); } #endregion private static List ExecuteBoundaryRepair(RepairEntity repair, List jcdltb_features) { List ResultgeometryList = new List(); List geometryList = null; List pointList = null; double angle = 0; try { if (IsMultipartGeometry(repair.Geometry)) { #region 拆分多部件 List Dissolves = FeatureAPI.DissolveGeometryByRing(repair.Geometry); if (Dissolves != null && Dissolves.Count > 0) { for (int i = 0; i < Dissolves.Count; i++) { IGeometry single = Dissolves[i]; if (single == null || (single as IArea).Area == 0) continue; #region 拆分多部件过后检查图形是否存在尖锐角/狭长 #region 尖锐角检查与修复 if (!single.IsEmpty && SharpAngle.JudgmentSharpAngle(single, ref pointList, ref angle)) { single = SharpAngle.ProcessSharpAngles(single, 3); single.SpatialReference = _SpatialReference; } #endregion #region 狭长/局部狭长检查与修复 if (!single.IsEmpty) { var NarrowAreas = PolygonNarrowAreaChecker.CheckLocalNarrowAreas(single as IPolygon); if (NarrowAreas != null && NarrowAreas.Count > 0) { LogAPI.Debug($"jcbh:{repair.JCBH}的图斑,BoundaryRepairHelper.ExecuteBoundaryRepair方法中的 狭长/局部狭长检查与修复,检查出来暂未处理 ! "); } } #endregion if (single.IsEmpty) continue; #endregion #region 判断当前图斑是否压盖多个图斑且存在碎图斑 foreach (IGeometry jcdltb in jcdltb_features) { #region 相交部分 IGeometry InterSect = FeatureAPI.InterSect(single, jcdltb); List InterSects = FeatureAPI.DissolveGeometryByRing(InterSect); if (InterSects != null && InterSects.Count > 0) { foreach (IGeometry intersect in InterSects) { if (intersect == null || intersect.IsEmpty || (intersect as IArea).Area == 0) continue; if ((intersect as IArea).Area < 1 || (SharpAngle.JudgmentSharpAngle(intersect, ref pointList, ref angle) && (intersect as IArea).Area < 10)) { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) continue;//线状地物不与碎图斑合并 IGeometry Difference1 = FeatureAPI.Difference(single, intersect); if (Difference1 != null && !Difference1.IsEmpty) single = Difference1; } } } else { continue; } #endregion #region 不相交部分 IGeometry Difference = FeatureAPI.Difference(jcdltb, single); List Differences = FeatureAPI.DissolveGeometryByRing(Difference); if (Differences != null && Differences.Count > 0) { for (int j = 0; j < Differences.Count; j++) { IGeometry difference = Differences[j]; if (difference == null || difference.IsEmpty || (difference as IArea).Area == 0) continue; //与基础库不相交的部分面积小于30平且相邻的情况下 合并 if (FeatureAPI.IsAdjacent(single, difference)) { double area = (difference as IArea).Area; if ((difference as IArea).Area < 10) { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) continue;//线状地物不与碎图斑合并 IGeometry unionresult = FeatureAPI.Union(single, difference); if (unionresult != null && !unionresult.IsEmpty) { single = unionresult; } continue; } else if (area > 10 && area < 30) { ResultgeometryList.Add(single); } } else { if (AECommonHelper.SharpAngleDataCheck(difference, ref pointList, ref angle)) { if (angle > 10)//狭长图形 { continue; } else { LogAPI.Debug($"jcbh:{repair.JCBH}的图斑,BoundaryRepairHelper.ExecuteBoundaryRepair方法中的 被动变更尖锐角处理 暂未处理 ! "); #region 被动变更尖锐角处理 //geometry = Passive_Sharp_Repair(pointList, geometry, item); #endregion } } } } } #endregion } #endregion List Dissolve = FeatureAPI.DissolveGeometryByRing(single);//拆分多部件 if (Dissolve != null && Dissolve.Count > 1) { foreach (IGeometry item in Dissolve) { ResultgeometryList.Add(item); } } else { ResultgeometryList.Add(single); } } } #endregion } else { #region 拆分多部件过后检查图形是否存在尖锐角/狭长 #region 尖锐角检查与修复 if (!repair.Geometry.IsEmpty && SharpAngle.JudgmentSharpAngle(repair.Geometry, ref pointList, ref angle)) { repair.Geometry = SharpAngle.ProcessSharpAngles(repair.Geometry, 3); repair.Geometry.SpatialReference = _SpatialReference; } #endregion #region 狭长/局部狭长检查与修复 if (!repair.Geometry.IsEmpty) { var NarrowAreas = PolygonNarrowAreaChecker.CheckLocalNarrowAreas(repair.Geometry as IPolygon); if (NarrowAreas != null && NarrowAreas.Count > 0) { LogAPI.Debug($"jcbh:{repair.JCBH}的图斑,BoundaryRepairHelper.ExecuteBoundaryRepair方法中的 拆分多部件过后检查图形是否存在狭长,检查出来暂未处理 ! "); } } #endregion #endregion #region 判断当前图斑是否压盖多个图斑且存在碎图斑 foreach (IGeometry jcdltb in jcdltb_features) { #region 相交部分 IGeometry InterSect = FeatureAPI.InterSect(repair.Geometry, jcdltb); List InterSects = FeatureAPI.DissolveGeometryByRing(InterSect); if (InterSects != null && InterSects.Count > 0) { foreach (IGeometry intersect in InterSects) { //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) continue; if ((!intersect.IsEmpty && (intersect as IArea).Area < 1)/* || (SharpAngle.JudgmentSharpAngle(intersect.Geometry, ref pointList, ref angle) && intersect.mj < 10)*/) { IGeometry differenceresult1 = FeatureAPI.Difference(repair.Geometry, intersect); if (differenceresult1 != null && !differenceresult1.IsEmpty) repair.Geometry = differenceresult1; } } } #endregion #region 不相交部分 IGeometry differenceresult = FeatureAPI.Difference(jcdltb, repair.Geometry); List differenceresults = FeatureAPI.DissolveGeometryByRing(differenceresult); if (differenceresults != null && differenceresults.Count > 0) { foreach (IGeometry differenc in differenceresults) { if (differenc == null || differenc.IsEmpty) { continue; } double area = (differenc as IArea).Area; if (area == 0) continue; //与基础库不相交的部分面积小于30平且相邻的情况下 合并 if (FeatureAPI.IsAdjacent(repair.Geometry, differenc)) { //线状地物不与碎图斑合并 //if (!string.IsNullOrEmpty(repair.DLBM) && XZDW_List.Contains(repair.DLBM)) continue; if (area < 10) { IGeometry unionresult = FeatureAPI.Union(repair.Geometry, differenc); if (unionresult != null && !unionresult.IsEmpty) { //假设合并之后为尖锐角或者狭长,就不合并 if (SharpAngle.JudgmentSharpAngle(unionresult, ref pointList, ref angle) || PolygonNarrowAreaChecker.CheckLocalNarrowAreas(unionresult as IPolygon).Count > 0) { continue; } repair.Geometry = unionresult; continue; } } else if (area > 10 && area < 30) { ResultgeometryList.Add(differenc); } //不相交部分,判定是否有尖锐角或者狭长图形,不相交部分的尖锐角或者狭长图形剩余部分合并给相邻的子地块 else if (SharpAngle.JudgmentSharpAngle(differenc, ref pointList, ref angle)) { IGeometry repairGeo = SharpAngle.ProcessSharpAngles(differenc, 5); repairGeo.SpatialReference = _SpatialReference; IGeometry diffresult = FeatureAPI.Difference(differenc, repairGeo); if (diffresult != null && !diffresult.IsEmpty) { double diffArea = (diffresult as IArea).Area; if (diffArea > 0) { List tempGeometryList = FeatureAPI.DissolveGeometryByRing(diffresult);//拆分多部件 foreach (IGeometry SharpGeo in tempGeometryList) { if (FeatureAPI.IsAdjacent(SharpGeo, repair.Geometry)) { IGeometry unionresult = FeatureAPI.Union(repair.Geometry, SharpGeo); if (unionresult != null && unionresult != null) { if (!SharpAngle.JudgmentSharpAngle(unionresult, ref pointList, ref angle) && PolygonNarrowAreaChecker.CheckLocalNarrowAreas(unionresult as IPolygon).Count <= 0) { repair.Geometry = unionresult; } } } } } } } else if (PolygonNarrowAreaChecker.CheckLocalNarrowAreas(differenc as IPolygon).Count > 0) { var NarrowAreas = PolygonNarrowAreaChecker.CheckLocalNarrowAreas(differenc as IPolygon); if (NarrowAreas != null && NarrowAreas.Count > 0) { foreach (var item in NarrowAreas) { if (FeatureAPI.IsAdjacent(item, repair.Geometry)) { IGeometry unionresult = FeatureAPI.Union(repair.Geometry, item); if (!SharpAngle.JudgmentSharpAngle(unionresult, ref pointList, ref angle) && PolygonNarrowAreaChecker.CheckLocalNarrowAreas(unionresult as IPolygon).Count <= 0) { repair.Geometry = unionresult; } } } } } } else { if (AECommonHelper.SharpAngleDataCheck(differenc, ref pointList, ref angle)) { if (angle > 10)//狭长图形 { continue; } else { LogAPI.Debug($"jcbh:{repair.JCBH}的图斑,BoundaryRepairHelper.ExecuteBoundaryRepair方法中的 不相交部分的被动变更尖锐角处理,检查出来暂未处理 ! "); #region 被动变更尖锐角处理 //geometry = Passive_Sharp_Repair(pointList, geometry, item); #endregion } } } } } #endregion } #endregion List Dissolve = FeatureAPI.DissolveGeometryByRing(repair.Geometry); if (Dissolve != null && Dissolve.Count > 1) { foreach (var item in Dissolve) { if (item == null || item.IsEmpty || (item as IArea).Area < 0.01) continue; ResultgeometryList.Add(item); } } else { ResultgeometryList.Add(repair.Geometry); } } } catch (Exception ex) { ResultgeometryList = geometryList; return ResultgeometryList; } return ResultgeometryList; } /// /// 判断图形是否为多部件 /// /// /// private static bool IsMultipartGeometry(IGeometry geometry) { // 检查是否为支持多部件的几何类型 if (geometry.GeometryType != esriGeometryType.esriGeometryPolygon && geometry.GeometryType != esriGeometryType.esriGeometryPolyline) { return false; } // 转换为IGeometryCollection接口 IGeometryCollection geometryCollection = geometry as IGeometryCollection; if (geometryCollection == null) { return false; } // 判断部件数量 return geometryCollection.GeometryCount > 1; } /// /// 处理边界修复后新增或修改的子地块 /// /// 边界修复结果 /// 年末数据库 /// 所有参与边界修复子地块 /// 当前修复子地块 /// 边界修复多部件图斑新增的子地块 private static void AddResultToAnalysisLayer(List entities, List ListDLTB, List repairs, RepairEntity repair, List RepairLayerZDK) { try { //所有他图形都没有被修改,删除当前子地块 if (entities.FirstOrDefault(x => x.Modify == true) == null) { //repair.JCBH = "-1"; repair.JCBH = $"{repair.JCBH}_DELETE"; return; } entities = entities.OrderBy(x => x.BSM.Contains("_New")).ToList(); bool isadd = false;//判断是否需要新增子地块 foreach (var item in entities) { if (!item.Modify) continue; var dltb = ListDLTB.FirstOrDefault(x => x.BSM == item.BSM); if (dltb != null) { if (dltb.BSM.StartsWith("NMK")) { string dkid = dltb.BSM.Split('_')[2]; var updatezdk = repairs.FirstOrDefault(x => x.JCBH.ToTrim().Replace("-", "") == dkid); if (updatezdk != null) updatezdk.WKT = item.RefWKT; } dltb.RefWKT = item.RefWKT; dltb.RefGeometry = item.RefGeometry; } else { var exist = ListDLTB.FirstOrDefault(x => x.RefWKT == item.RefWKT); if (exist != null && !item.BSM.StartsWith("NMK_")) continue; ListDLTB.Add(new ReferenceEntity() { #region 属性值 BSM = item.BSM, CZCSXM = item.CZCSXM, RefWKT = item.RefWKT, RefGeometry = item.RefGeometry, DLBM = item.DLBM, IsReference = true, oid = item.oid #endregion }); if (!isadd) { repair.WKT = item.RefWKT; repair.Geometry = item.RefGeometry; isadd = true; //只修改后续有相交子地块,先擦除掉因此子地块修改后造成的相交部分,便于点修复时的修改 for (int i = repairs.Count - 1; i >= 0; i--) { if (repairs[i].JCBH == repair.JCBH) break; IGeometry otherZDKGeo = repairs[i].Geometry == null ? ConvertWKTAndSetSpatialRef(repairs[i].WKT, _SpatialReference) : repairs[i].Geometry; if (FeatureAPI.IsInterSect(repair.Geometry, otherZDKGeo)) { IGeometry geo = FeatureAPI.InterSect(repair.Geometry, otherZDKGeo); if (geo != null) { IGeometry diffGeo = FeatureAPI.Difference(otherZDKGeo, geo); if (diffGeo != null && !diffGeo.IsEmpty) { repairs[i].Geometry = diffGeo; repairs[i].WKT = GeometryConvertHelper.ConvertIGeoemtryToWKT(diffGeo); } } } } } else { RepairEntity zDK = new RepairEntity(); zDK.WKT = item.RefWKT; zDK.CZCSXM = repair.CZCSXM; zDK.DLBM = repair.DLBM; if (item.BSM.Contains("_SharpAngle") || item.BSM.Contains("_New")) { zDK.JCBH = item.BSM; } else { zDK.JCBH = Guid.NewGuid().ToTrim().Replace("-", ""); } RepairLayerZDK.Add(zDK); } } } } catch (Exception ex) { throw; } } private static IGeometry ConvertWKTAndSetSpatialRef(string wkt, ISpatialReference spatialRef) { var geometry = GeometryConvertHelper.ConvertWKTToIGeometry(wkt); geometry.SpatialReference = spatialRef; return geometry; } /// /// 判断两个包围盒是否相交 /// /// 包围盒A /// 包围盒B /// true-相交;false-不相交 private static bool AreEnvelopesIntersecting(IEnvelope envA, IEnvelope envB) { // 任一包围盒为空时,视为不相交 if (envA == null || envB == null || envA.IsEmpty || envB.IsEmpty) return false; // X轴投影不重叠 if (envA.XMin >= envB.XMax || envA.XMax <= envB.XMin) return false; // Y轴投影不重叠 if (envA.YMin >= envB.YMax || envA.YMax <= envB.YMin) return false; // X和Y轴均重叠,包围盒相交 return true; } private static T DeepCopyByReflect(T obj) { //如果是字符串或值类型则直接返回 if (obj == null || (obj is string) || obj.GetType().IsValueType) return obj; object retval = System.Activator.CreateInstance(obj.GetType()); System.Reflection.FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); foreach (System.Reflection.FieldInfo field in fields) { try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); } catch { } } return (T)retval; } } }