You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1634 lines
80 KiB
1634 lines
80 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using DevExpress.Mvvm.Native; |
|
using ESRI.ArcGIS.esriSystem; |
|
using ESRI.ArcGIS.Geometry; |
|
using KGIS.Framework.AE; |
|
using KGIS.Framework.AE.ExtensionMethod; |
|
using KGIS.Framework.Utils.ExtensionMethod; |
|
using NetTopologySuite.IO; |
|
|
|
namespace Kingo.PluginServiceInterface.Helper |
|
{ |
|
/// <summary> |
|
/// 边界修复 |
|
/// </summary> |
|
public static class BoundaryRepairHelperNew |
|
{ |
|
private static List<string> XZDW_List = new List<string>() { "1001", "1002", "1003", "1004", "1006", "1009", "1107", "1107A", "1101", "1203" }; |
|
|
|
#region 执行边界修复 |
|
public static List<BoundaryRepairGeometryMessages> ExecuteRepair(BoundaryRepairEntity parameter, ISpatialReference SpatialReference) |
|
{ |
|
BoundaryRepairEntity repair = null; |
|
try |
|
{ |
|
repair = parameter; |
|
IGeometry geometry = parameter.Geometry; |
|
if (geometry == null || geometry.IsEmpty) |
|
{ |
|
return null; |
|
} |
|
|
|
#region 原始图形存在尖锐角/狭长 |
|
List<IPoint> yspointList = null; |
|
double ysangle = 0; |
|
#region 尖锐角 |
|
//尖锐角检查与修复 |
|
if (SharpAngle.JudgmentSharpAngle(repair.Geometry, ref yspointList, ref ysangle)) |
|
{ |
|
repair.Geometry = SharpAngle.ProcessSharpAngles(repair.Geometry, 3); |
|
} |
|
#endregion |
|
#region 局部狭长 |
|
//if (PolygonNarrowCheck.IsNarrowGeometry(repair.Geometry)) |
|
//{ |
|
// List<NetTopologySuite.Geometries.Geometry> geometries = new List<NetTopologySuite.Geometries.Geometry>(); |
|
// foreach (var item in parameter.ListReference) |
|
// { |
|
// var wkb = GeometryConvertHelper.ConvertGeometryToWKB(item.Geometry); |
|
// NetTopologySuite.Geometries.Geometry ntsGeometry = (NetTopologySuite.Geometries.Geometry)new WKBReader().Read(wkb); |
|
// geometries.Add(ntsGeometry); |
|
// } |
|
// TopologyRepairEngine.FullRepair(geometries); |
|
//} |
|
//else |
|
//{ |
|
// return null; |
|
//} |
|
#endregion |
|
|
|
//狭长图斑检查与修复 |
|
if (SharpAngleDataCheck(repair.Geometry, ref yspointList, ref ysangle)) |
|
{ |
|
//子地块为小于10平且为狭长或尖锐角的图形直接删除 |
|
if (repair.Geometry.GetEllipseArea() < 30) return repair.ListReference; |
|
if (ysangle > 10) |
|
{ |
|
//狭长图形,向内缓冲0.05 |
|
repair.Geometry = ResolveLongAndNarrow(repair.Geometry); |
|
} |
|
else |
|
{ |
|
//尖锐角 |
|
if (yspointList != null && yspointList.Count == 3) |
|
{ |
|
//repair.Geometry = SharpAngleErase(repair.Geometry, yspointList); |
|
#region 2024.1014新增逻辑 尖锐角位置外扩1米 |
|
{ |
|
repair.Geometry = Scale_Out(repair.Geometry, yspointList, parameter.ListReference); |
|
//尖锐角修复完成后 面积小于30平的子地块删除 |
|
|
|
} |
|
#endregion |
|
} |
|
} |
|
} |
|
#endregion |
|
//尖锐角/狭长图形修复完以后,图形为空直接返回,删除当前子地块 |
|
if (repair.Geometry.IsEmpty) return repair.ListReference; |
|
//尖锐角与狭长图形修复完成后,面积小于10平的 且 |
|
if (repair.Geometry.GetEllipseArea() < 10 && !XZDW_List.Contains(repair.DLBM)) return repair.ListReference; |
|
|
|
#region 压盖带一个参考图形 |
|
if (repair.ListReference != null && repair.ListReference.Count == 1) |
|
{ |
|
BoundaryRepairGeometryMessages jcdltb = repair.ListReference[0]; |
|
#region 面积相差小于1的 直接使用基础库图形 |
|
var refmj = jcdltb.Geometry.GetEllipseArea(); |
|
var geomj = repair.Geometry.GetEllipseArea(); |
|
if (refmj == geomj || Math.Abs(refmj - geomj) < 1) |
|
{ |
|
if (!string.IsNullOrEmpty(repair.DLBM)) |
|
{ |
|
jcdltb.DLBM = repair.DLBM; |
|
jcdltb.CZCSXM = repair.CZCSXM; |
|
jcdltb.Modify = true; |
|
jcdltb.BSM = $"NMK_{parameter.DKID}"; |
|
} |
|
return repair.ListReference; |
|
} |
|
#endregion |
|
|
|
#region 图形在基础数据内部 且被动变更图斑不存在尖锐角/狭长图形 |
|
var Difference = FeatureAPI.Difference(jcdltb.Geometry, repair.Geometry); |
|
var Differences = FeatureAPI.DissolveGeometryByRing(Difference); |
|
bool iscontinue = true; |
|
foreach (var diff in Differences) |
|
{ |
|
if (diff.IsEmpty) continue; |
|
var mj = diff.GetEllipseArea(); |
|
if (mj < 1) |
|
{ |
|
iscontinue = false; break; |
|
} |
|
List<IPoint> pointList = null; |
|
double angle = 0; |
|
if (AECommonHelper.SharpAngleDataCheck(diff, ref pointList, ref angle)) |
|
{ |
|
iscontinue = false; break; |
|
} |
|
} |
|
if (iscontinue) |
|
{ |
|
//地类编码为空的 不更新年末数据库 |
|
if (!string.IsNullOrEmpty(repair.DLBM)) |
|
{ |
|
jcdltb.Geometry = Difference; |
|
jcdltb.Modify = true; |
|
} |
|
repair.ListReference.Add( |
|
new BoundaryRepairGeometryMessages() |
|
{ |
|
Objectid = -1, |
|
BSM = $"NMK_{parameter.DKID}", |
|
CZCSXM = repair.CZCSXM, |
|
DLBM = repair.DLBM, |
|
Geometry = repair.Geometry, |
|
Modify = true |
|
}); |
|
return repair.ListReference; |
|
} |
|
#endregion |
|
|
|
} |
|
#endregion |
|
|
|
if (repair.ListReference != null && repair.ListReference.Count >= 1) |
|
{ |
|
foreach (var jcfc in repair.ListReference) |
|
{ |
|
#region 与基础库相交 |
|
if (repair.Geometry.IsEmpty) break; |
|
ITopologicalOperator topoOpr_jc = jcfc.Geometry as ITopologicalOperator; |
|
topoOpr_jc.Simplify(); |
|
IGeometry InterArea = FeatureAPI.InterSect(jcfc.Geometry, repair.Geometry); |
|
if (InterArea == null || InterArea.IsEmpty) continue;//未相交到或相交为空图形的直接跳过 |
|
List<IGeometry> InterAreas = FeatureAPI.DissolveGeometryByRing(InterArea); |
|
if (InterAreas == null || InterAreas.Count == 0) continue; |
|
InterAreas = InterAreas.OrderBy(x => x.GetEllipseArea()).ToList(); |
|
foreach (var area in InterAreas) |
|
{ |
|
ITopologicalOperator topoOpr = area as ITopologicalOperator; |
|
topoOpr.Simplify(); |
|
if (area.IsEmpty) continue;//空图形不处理 |
|
var mj = area.GetEllipseArea(); |
|
if (mj < 1)//相交面积小于1的图形擦除 |
|
{ |
|
repair.Geometry = FeatureAPI.Difference(repair.Geometry, area); continue; |
|
} |
|
else if (mj < 10) |
|
{ |
|
List<IPoint> pointList = null; |
|
double angle = 0; |
|
//相交面积小于10且相交图形为尖锐角或者狭长图形的擦除 |
|
if (AECommonHelper.SharpAngleDataCheck(area, ref pointList, ref angle)) |
|
{ |
|
repair.Geometry = FeatureAPI.Difference(repair.Geometry, area); continue; |
|
} |
|
else |
|
{ |
|
//if (jcfc.BSM.StartsWith("NMK")) |
|
// repair.Geometry = FeatureAPI.Difference(repair.Geometry, area); |
|
//参与图形修复的基础库 |
|
jcfc.IsReference = true; |
|
continue; |
|
} |
|
} |
|
else |
|
{ |
|
//if (jcfc.BSM.StartsWith("NMK")) |
|
// repair.Geometry = FeatureAPI.Difference(repair.Geometry, area); |
|
//参与图形修复的基础库 |
|
jcfc.IsReference = true; |
|
continue; |
|
} |
|
} |
|
#endregion |
|
|
|
if (!jcfc.IsReference) continue; |
|
|
|
#region 与基础库不相交的面积 |
|
IGeometry DifferenceArea = FeatureAPI.Difference(jcfc.Geometry, repair.Geometry); |
|
List<IGeometry> DifferenceAreas = FeatureAPI.DissolveGeometryByRing(DifferenceArea); |
|
if (DifferenceAreas != null && DifferenceAreas.Count > 0) |
|
{ |
|
foreach (var diff in DifferenceAreas) |
|
{ |
|
ITopologicalOperator topoOpr = diff as ITopologicalOperator; |
|
topoOpr.Simplify(); |
|
if (diff.IsEmpty) continue; |
|
var mj = diff.GetEllipseArea(); |
|
List<IPoint> pointList1 = null; |
|
double angle = 0; |
|
if (mj < 1)//未相交面积小于1的图形合并 |
|
{ |
|
if (FeatureAPI.IsAdjacent(repair.Geometry, diff)) |
|
repair.Geometry = FeatureAPI.Union(repair.Geometry, diff); |
|
} |
|
else if (!diff.IsEmpty && mj < 10 && AECommonHelper.SharpAngleDataCheck(diff, ref pointList1, ref angle)) |
|
{ |
|
if (FeatureAPI.IsAdjacent(repair.Geometry, diff)) |
|
repair.Geometry = FeatureAPI.Union(repair.Geometry, diff); |
|
} |
|
else |
|
{ |
|
#region 被动变更小于30平且相邻的图斑与当前图斑合并 |
|
if (mj <= 30 && FeatureAPI.IsAdjacent(repair.Geometry, diff)) |
|
{ |
|
repair.Geometry = FeatureAPI.Union(repair.Geometry, diff); |
|
} |
|
#endregion |
|
} |
|
} |
|
} |
|
#endregion |
|
} |
|
if (repair.Geometry.IsEmpty) return repair.ListReference; |
|
if (repair.ListReference.Where(x => x.IsReference).ToList().Count == 1) |
|
{ |
|
BoundaryRepairGeometryMessages jcdltb = repair.ListReference.Where(x => x.IsReference).ToList().FirstOrDefault(); |
|
|
|
#region 压盖带一个参考图形 |
|
|
|
#region 面积相差小于1的 直接使用基础库图形 |
|
var refmj = jcdltb.Geometry.GetEllipseArea(); |
|
var geomj = repair.Geometry.GetEllipseArea(); |
|
if (refmj == geomj || Math.Abs(refmj - geomj) < 1) |
|
{ |
|
repair.ListReference.Add(new BoundaryRepairGeometryMessages() |
|
{ |
|
Objectid = -1, |
|
BSM = $"NMK_{parameter.DKID.ToTrim().Replace("-", "")}", |
|
CZCSXM = repair.CZCSXM, |
|
DLBM = repair.DLBM, |
|
Geometry = jcdltb.Geometry, |
|
Modify = true, |
|
Describe = "图形修复:变更图斑与基础数据库图形差异较小,直接使用基础数据库图形" |
|
}); |
|
if (!string.IsNullOrEmpty(repair.DLBM)) |
|
{ |
|
jcdltb.Geometry = null; |
|
jcdltb.Modify = true; |
|
} |
|
return repair.ListReference; |
|
} |
|
#endregion |
|
|
|
#region 图形在基础数据内部 且被动变更图斑不存在尖锐角/狭长图形 |
|
var Difference = FeatureAPI.Difference(jcdltb.Geometry, repair.Geometry); |
|
var Differences = FeatureAPI.DissolveGeometryByRing(Difference); |
|
bool iscontinue = true; |
|
if (Differences != null && Differences.Count > 0) |
|
foreach (var diff in Differences) |
|
{ |
|
if (diff.IsEmpty) continue; |
|
var mj = diff.GetEllipseArea(); |
|
if (mj < 1) |
|
{ |
|
iscontinue = false; break; |
|
} |
|
List<IPoint> pointList = null; |
|
double angle = 0; |
|
if (AECommonHelper.SharpAngleDataCheck(diff, ref pointList, ref angle)) |
|
{ |
|
iscontinue = false; break; |
|
} |
|
foreach (var item in repair.ListReference) |
|
{ |
|
if (item.BSM == jcdltb.BSM) continue; |
|
if (FeatureAPI.IsInterSect(item.Geometry, diff)) |
|
{ |
|
iscontinue = false; break; |
|
} |
|
} |
|
} |
|
if (iscontinue) |
|
{ |
|
repair.Geometry = FeatureAPI.Difference(jcdltb.Geometry, Difference); |
|
#region 出现多部件的图形,需要进行节点修复逻辑 |
|
List<IGeometry> geometryList = FeatureAPI.DissolveGeometryByRing(repair.Geometry);//拆分多部件 |
|
if (geometryList.Count > 1) |
|
{ |
|
|
|
} |
|
else |
|
{ |
|
//地类编码为空的 不更新年末数据库 |
|
if (!string.IsNullOrEmpty(repair.DLBM)) |
|
{ |
|
if (Difference.IsEmpty) |
|
{ |
|
jcdltb.Geometry = null; |
|
} |
|
else |
|
{ |
|
jcdltb.Geometry = Difference; |
|
} |
|
jcdltb.Modify = true; |
|
} |
|
|
|
repair.ListReference.Add(new BoundaryRepairGeometryMessages() |
|
{ |
|
Objectid = -1, |
|
BSM = $"NMK_{parameter.DKID.ToTrim().Replace("-", "")}", |
|
CZCSXM = repair.CZCSXM, |
|
DLBM = repair.DLBM, |
|
Geometry = repair.Geometry, |
|
Modify = true, |
|
Describe = "图形修复:" |
|
}); |
|
return repair.ListReference; |
|
} |
|
#endregion |
|
|
|
} |
|
#endregion |
|
|
|
#endregion |
|
|
|
} |
|
#region 没有参考基础库 |
|
if (repair.ListReference.Where(x => x.IsReference).ToList().Count == 0) return repair.ListReference; |
|
#endregion |
|
|
|
var geometrys = ExecuteBoundaryRepair(repair, repair.ListReference, 0.618); |
|
foreach (var item in geometrys) |
|
{ |
|
if (item == null || item.IsEmpty || item.GetEllipseArea() == 0) |
|
continue; |
|
if (geometrys.Count > 1 && item.GetEllipseArea() < 30) |
|
continue; |
|
foreach (BoundaryRepairGeometryMessages jcdltb in repair.ListReference) |
|
{ |
|
if (!jcdltb.IsReference) continue; |
|
IGeometry diff = FeatureAPI.Difference(jcdltb.Geometry, item); |
|
if (diff == null || diff.IsEmpty || diff.GetEllipseArea() == 0) |
|
{ |
|
if (!string.IsNullOrEmpty(repair.DLBM)) |
|
{ |
|
jcdltb.Geometry = null; |
|
jcdltb.Modify = true; |
|
} |
|
} |
|
else |
|
{ |
|
if (!string.IsNullOrEmpty(repair.DLBM)) |
|
{ |
|
jcdltb.Geometry = diff; |
|
jcdltb.Modify = true; |
|
} |
|
} |
|
} |
|
BoundaryRepairGeometryMessages referenceEntity = new BoundaryRepairGeometryMessages(); |
|
referenceEntity.Objectid = -1; |
|
referenceEntity.BSM = $"NMK_{repair.DKID.ToTrim().Replace("-", "")}"; |
|
referenceEntity.CZCSXM = repair.CZCSXM; |
|
referenceEntity.DLBM = repair.DLBM; |
|
referenceEntity.Geometry = item; |
|
referenceEntity.Modify = true; |
|
referenceEntity.Describe = "图形修复:节点修复"; |
|
if (repair.ListReference.FirstOrDefault(x => x.BSM == referenceEntity.BSM) != null) |
|
{ |
|
referenceEntity.BSM = $"NMK_{Guid.NewGuid().ToTrim().Replace("-", "")}"; |
|
} |
|
repair.ListReference.Add(referenceEntity); |
|
} |
|
} |
|
else |
|
{ |
|
return repair.ListReference; |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw; |
|
} |
|
return repair.ListReference; |
|
} |
|
#endregion |
|
|
|
#region 尖锐角修复---向外扩1米 |
|
private static IGeometry Scale_Out(IGeometry ysgeometry, List<IPoint> points, List<BoundaryRepairGeometryMessages> referenceLayersGeometryMessages) |
|
{ |
|
List<IPoint> pointList = null; |
|
double angle = 0; |
|
IGeometry geometry = null; |
|
try |
|
{ |
|
IPolyline polyline1 = new PolylineClass(); |
|
IPolyline polyline1_vertical = null; |
|
IPolyline polyline2_vertical = null; |
|
IPolyline polyline2 = new PolylineClass(); |
|
if (points.Count == 3) |
|
{ |
|
polyline1.SpatialReference = points[0].SpatialReference; |
|
polyline1.FromPoint = points[1]; |
|
polyline1.ToPoint = points[0]; |
|
polyline1_vertical = GetPerpendicularLine(polyline1, true); |
|
|
|
polyline2.SpatialReference = points[0].SpatialReference; |
|
polyline2.FromPoint = points[1]; |
|
polyline2.ToPoint = points[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 |
|
List<IPoint> points1 = new List<IPoint>() { length1Point, points[1], points[0] }; |
|
IGeometry geometry1 = GenerateGeometryFromPoints(points1); |
|
geometry1.SpatialReference = ysgeometry.SpatialReference; |
|
|
|
List<IPoint> points2 = new List<IPoint>() { length2Point, points[1], points[0] }; |
|
IGeometry geometry2 = GenerateGeometryFromPoints(points2); |
|
geometry2.SpatialReference = ysgeometry.SpatialReference; |
|
var IsInterSectcount1 = 0; |
|
var IsInterSectcount2 = 0; |
|
foreach (BoundaryRepairGeometryMessages entity in referenceLayersGeometryMessages) |
|
{ |
|
if (FeatureAPI.IsInterSect(geometry1, entity.Geometry)) |
|
{ |
|
IsInterSectcount1++; |
|
} |
|
if (FeatureAPI.IsInterSect(geometry2, entity.Geometry)) |
|
{ |
|
IsInterSectcount2++; |
|
} |
|
} |
|
if (IsInterSectcount1 <= IsInterSectcount2) |
|
{ |
|
geometry = FeatureAPI.Union(ysgeometry, geometry1); |
|
} |
|
else |
|
{ |
|
geometry = FeatureAPI.Union(ysgeometry, geometry2); |
|
} |
|
if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle)) |
|
{ |
|
if (angle > 10) |
|
{ |
|
geometry = ResolveLongAndNarrow(geometry); |
|
} |
|
else |
|
{ |
|
//geometry = Scale_Out(geometry, pointList, referenceLayersGeometryMessages); |
|
} |
|
} |
|
else |
|
{ |
|
return geometry; |
|
} |
|
|
|
} |
|
catch (Exception) |
|
{ |
|
return ysgeometry; |
|
} |
|
return geometry; |
|
} |
|
#endregion |
|
|
|
#region 根据点集合生成图形 |
|
/// <summary> |
|
/// 根据点集合生成图形 |
|
/// </summary> |
|
/// <param name="Points"></param> |
|
/// <returns></returns> |
|
private static IGeometry GenerateGeometryFromPoints(List<IPoint> Points) |
|
{ |
|
try |
|
{ |
|
Ring ring = new RingClass(); |
|
object missing = Type.Missing; |
|
IPointCollection pointCollection2 = new MultipointClass(); |
|
if (Points != null && Points.Count == 3) |
|
{ |
|
if (Points[0] != null && Points[1] != null && Points[2] != null)//Points中不为空 |
|
{ |
|
pointCollection2.AddPoint(Points[0]); |
|
pointCollection2.AddPoint(Points[1]); |
|
pointCollection2.AddPoint(Points[2]); |
|
} |
|
} |
|
ring.AddPointCollection(pointCollection2); |
|
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; |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
} |
|
#endregion |
|
|
|
#region MyRegion |
|
private static List<IGeometry> ExecuteBoundaryRepair(BoundaryRepairEntity repair, List<BoundaryRepairGeometryMessages> jcdltb_features, double distance) |
|
{ |
|
List<IGeometry> ResultgeometryList = new List<IGeometry>(); |
|
List<IGeometry> geometryList = null; |
|
try |
|
{ |
|
geometryList = FeatureAPI.DissolveGeometryByRing(repair.Geometry);//拆分多部件 |
|
foreach (IGeometry Splitgeo in geometryList) |
|
{ |
|
//IGeometry geometry = Splitgeo; |
|
IClone clone = Splitgeo as IClone; |
|
IGeometry geometry = clone?.Clone() as IGeometry; |
|
if (geometry == null || geometry.IsEmpty || geometry.GetEllipseArea() == 0) continue; |
|
IGeometry repaird = NodeRepair(geometry, jcdltb_features, distance); |
|
if (repaird != null && !repaird.IsEmpty) |
|
{ |
|
geometry = repaird; |
|
geometry.SpatialReference = repair.Geometry.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 < 10) |
|
{ |
|
geometry = FeatureAPI.Difference(geometry, geo); |
|
} |
|
} |
|
} |
|
else if (multi == null) |
|
continue; |
|
#endregion |
|
|
|
#region 检查图形是否存在尖锐角/狭长图形等问题 |
|
//List<IPoint> pointList = null; |
|
//double angle = 0; |
|
//if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle)) |
|
//{ |
|
// if (geometry.GetEllipseArea() > 10) |
|
// { |
|
// if (pointList != null && angle < 10) |
|
// { |
|
// if (jcdltb_features.Where(x => x.IsReference).ToList().Count == 1) |
|
// { |
|
// var Reference = jcdltb_features.Where(x => x.IsReference).ToList(); |
|
// geometry = ResolveAcuteAngle(geometry, pointList, angle, Reference[0].RefGeometry, true); |
|
// } |
|
// else |
|
// { |
|
// //var completedgeo = SharpAngleMerge(geometry, pointList); |
|
// geometry = ResolveAcuteAngle(geometry, pointList, angle); |
|
// } |
|
// } |
|
// } |
|
// else |
|
// { |
|
// //节点修复完成后,面积小于10 且为尖锐角的图形 |
|
// continue; |
|
// } |
|
//} |
|
#endregion |
|
|
|
#region 判断当前图斑是否压盖多个图斑且存在碎图斑 |
|
foreach (BoundaryRepairGeometryMessages jcdltb in jcdltb_features) |
|
{ |
|
#region 相交部分 |
|
var geo = FeatureAPI.InterSect(geometry, jcdltb.Geometry); |
|
List<IGeometry> 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(); |
|
List<IPoint> pointList2 = null; |
|
double angle2 = 0; |
|
if (mj < 1 && !item.IsEmpty) |
|
{ |
|
geometry = FeatureAPI.Difference(geometry, item); |
|
} |
|
else if (!item.IsEmpty && mj < 10 && AECommonHelper.SharpAngleDataCheck(item, ref pointList2, ref angle2)) |
|
{ |
|
geometry = FeatureAPI.Difference(geometry, item); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
continue; |
|
} |
|
#endregion |
|
|
|
#region 不相交部分 |
|
geo = FeatureAPI.Difference(jcdltb.Geometry, geometry); |
|
geometries = FeatureAPI.DissolveGeometryByRing(geo); |
|
if (geometries != null && geometries.Count > 0) |
|
{ |
|
foreach (var item in geometries) |
|
{ |
|
ITopologicalOperator topoOpr = item as ITopologicalOperator; |
|
topoOpr.Simplify(); |
|
List<IPoint> pointList = null; |
|
double angle = 0; |
|
var mj = item.GetEllipseArea(); |
|
if (item.IsEmpty) continue; |
|
//与基础库不相交的部分面积小于30平且相邻的情况下 合并 |
|
if (mj < 30 && FeatureAPI.IsAdjacent(geometry, item)) |
|
{ |
|
//线状地物不与碎图斑合并 |
|
//if (!string.IsNullOrEmpty(repair.DLBM) && DL.Contains(repair.DLBM)) continue; |
|
|
|
#region 避免合并后是镂空的多环图形 |
|
//bool isMultiRing = false; |
|
//IGeometry multiRingGeo = FeatureAPI.Union(repair.Geometry, item); |
|
//IPolygon4 poly4 = multiRingGeo as IPolygon4; |
|
//GeometryBag geoBag = poly4.ExteriorRingBag as GeometryBag; |
|
//if (geoBag != null) |
|
//{ |
|
// IGeometryCollection geoCollection = geoBag as IGeometryCollection; |
|
// for (int j = 0; j < geoCollection.GeometryCount; j++) |
|
// { |
|
// IGeometry geoExterior = geoCollection.get_Geometry(j); |
|
// //内环图形 |
|
// IGeometryBag InteriorBag = (multiRingGeo as IPolygon4).get_InteriorRingBag(geoExterior as IRing); |
|
// if (InteriorBag != null) |
|
// { |
|
// if (!(InteriorBag is IGeometryCollection InteriorRingGeometryCollection)) continue; |
|
// if (InteriorRingGeometryCollection.GeometryCount > 0) |
|
// { |
|
// isMultiRing = true; |
|
// break; |
|
// } |
|
// } |
|
// } |
|
// if (isMultiRing) continue; |
|
//} |
|
#endregion |
|
|
|
geometry = FeatureAPI.Union(geometry, item); |
|
continue; |
|
} |
|
else |
|
{ |
|
if (AECommonHelper.SharpAngleDataCheck(item, ref pointList, ref angle)) |
|
{ |
|
if (angle > 10)//狭长图形 |
|
{ |
|
continue; |
|
} |
|
else |
|
{ |
|
#region 被动变更尖锐角处理 |
|
geometry = Passive_Sharp_Repair(pointList, geometry, item); |
|
//if (pointList1.Count != 3 || angle1 == -1) continue; |
|
//var completedgeo = SharpAngleMerge(item, pointList1);//获取被动变更尖锐角的组成部分,与当前变更图斑合并 |
|
//var InterSect = FeatureAPI.InterSect(item, completedgeo);//仅合并与被动变更相交的部分 |
|
//completedgeo = InterSect; |
|
//var passive = FeatureAPI.Difference(item, completedgeo); |
|
//if (passive.GetEllipseArea() < 30) completedgeo = item;//与尖锐角合并后剩余被动变更图斑面积小于30, |
|
//var completedgeoMJ = completedgeo.GetEllipseArea(); |
|
//if (FeatureAPI.IsAdjacent(geometry, completedgeo) && completedgeoMJ < 30) |
|
//{ |
|
// var uniongeo = FeatureAPI.Union(geometry, completedgeo); |
|
// if (AECommonHelper.SharpAngleDataCheck(uniongeo, ref pointList, ref angle)) |
|
// { |
|
// geometry = ResolveAcuteAngle(uniongeo, pointList, angle, item, true); |
|
// } |
|
// else |
|
// { |
|
// geometry = uniongeo; |
|
// } |
|
//} |
|
//else |
|
//{ |
|
//} |
|
#endregion |
|
|
|
} |
|
} |
|
} |
|
} |
|
} |
|
#endregion |
|
} |
|
#endregion |
|
|
|
#region 检查图形是否存在尖锐角/狭长图形等问题 |
|
List<IPoint> pointList1 = null; |
|
double angle1 = 0; |
|
if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList1, ref angle1)) |
|
{ |
|
#region 擦除尖锐角 |
|
if (pointList1 != null && pointList1.Count == 3) |
|
{ |
|
try |
|
{ |
|
//构成尖锐角的两条边 |
|
IPolyline polylinemax = new PolylineClass(); |
|
polylinemax.SpatialReference = geometry.SpatialReference; |
|
polylinemax.FromPoint = pointList1[0]; |
|
polylinemax.ToPoint = pointList1[1]; |
|
|
|
IPolyline polylinemin = new PolylineClass(); |
|
polylinemin.SpatialReference = geometry.SpatialReference; |
|
polylinemin.FromPoint = pointList1[2]; |
|
polylinemin.ToPoint = pointList1[1]; |
|
|
|
IPolyline polyline_vertical = null;//获取较短的边做垂线 |
|
if (polylinemax.Length < polylinemin.Length) |
|
{ |
|
IPolyline temppolylinemin = new PolylineClass(); |
|
temppolylinemin = polylinemax; |
|
polylinemax = polylinemin; |
|
polylinemin = temppolylinemin; |
|
} |
|
polyline_vertical = GetPerpendicularLine(polylinemin, true, polylinemin.Length); |
|
IPointCollection pPointCol = polyline_vertical as IPointCollection; |
|
IPoint fPoint = new PointClass(); |
|
IPoint ePoint = new PointClass(); |
|
object missing2 = Type.Missing; |
|
polyline_vertical.QueryPoint(esriSegmentExtension.esriExtendAtFrom, -1 * polylinemin.Length, false, fPoint); |
|
pPointCol.InsertPoints(0, 1, ref fPoint); |
|
polyline_vertical.QueryPoint(esriSegmentExtension.esriExtendAtTo, polylinemin.Length + polylinemin.Length, false, ePoint); |
|
pPointCol.AddPoint(ePoint, ref missing2, ref missing2); |
|
IPolyline polyline = pPointCol as IPolyline; |
|
ITopologicalOperator topo = polyline_vertical as ITopologicalOperator; |
|
IGeometry extendgeo = topo.Intersect(polylinemax, esriGeometryDimension.esriGeometry0Dimension); |
|
IPoint point = null; |
|
if (extendgeo.GeometryType == esriGeometryType.esriGeometryPoint) |
|
{ |
|
point = extendgeo as IPoint; |
|
} |
|
else |
|
{ |
|
if (extendgeo.GeometryType == esriGeometryType.esriGeometryMultipoint) |
|
{ |
|
IPointCollection pointCollection = extendgeo as IPointCollection; |
|
if (pointCollection.PointCount > 0) |
|
{ |
|
point = pointCollection.get_Point(0); |
|
} |
|
} |
|
} |
|
List<IPoint> points1 = new List<IPoint>() { point, pointList1[1], pointList1[0] }; |
|
IGeometry geometry1 = GenerateGeometryFromPoints(points1); |
|
geometry1.SpatialReference = geometry.SpatialReference; |
|
geometry = FeatureAPI.Difference(geometry, geometry1); |
|
} |
|
catch (Exception ex) |
|
{ |
|
|
|
} |
|
} |
|
#endregion |
|
//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; |
|
return ResultgeometryList; |
|
} |
|
return ResultgeometryList; |
|
} |
|
#endregion |
|
|
|
#region MyRegion |
|
private static IGeometry NodeRepair(IGeometry OriginalGeo, List<BoundaryRepairGeometryMessages> ReferenceLayer, double distance) |
|
{ |
|
IGeometry geometry = OriginalGeo; |
|
try |
|
{ |
|
List<IPoint> repairpoints = GetMultipleRingPoints(geometry); |
|
var count = 0; |
|
List<string> listmoveToPoint = new List<string>(); |
|
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<IGeometry> 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; |
|
} |
|
#endregion |
|
|
|
#region Passive_Sharp_Repair |
|
/// <summary> |
|
/// 构成尖锐角较短的边与较长的边做垂线,构成一个直角三角形,将直角三角形擦除 |
|
/// </summary> |
|
/// <param name="pointList"></param> |
|
/// <param name="bg_geometry"></param> |
|
/// <param name="diffgeo"></param> |
|
/// <returns></returns> |
|
private static IGeometry Passive_Sharp_Repair(List<IPoint> pointList, IGeometry bg_geometry, IGeometry diffgeo) |
|
{ |
|
List<IPoint> pointList1 = null; |
|
double angle1 = 0; |
|
try |
|
{ |
|
if (pointList != null && pointList.Count == 3) |
|
{ |
|
//构成尖锐角的两条边 |
|
IPoint pointmax = pointList[0]; |
|
IPolyline polylinemax = new PolylineClass(); |
|
polylinemax.SpatialReference = bg_geometry.SpatialReference; |
|
polylinemax.FromPoint = pointList[0]; |
|
polylinemax.ToPoint = pointList[1]; |
|
|
|
IPoint pointmin = pointList[2]; |
|
IPolyline polylinemin = new PolylineClass(); |
|
polylinemin.SpatialReference = bg_geometry.SpatialReference; |
|
polylinemin.FromPoint = pointList[2]; |
|
polylinemin.ToPoint = pointList[1]; |
|
|
|
IPolyline polyline_vertical = null;//获取较短的边做垂线 |
|
if (polylinemax.Length < polylinemin.Length) |
|
{ |
|
IPolyline temppolylinemin = new PolylineClass(); |
|
temppolylinemin = polylinemax; |
|
polylinemax = polylinemin; |
|
polylinemin = temppolylinemin; |
|
IPoint temppoint = new PointClass(); |
|
temppoint = pointmax; |
|
pointmax = pointmin; |
|
pointmin = temppoint; |
|
} |
|
polyline_vertical = GetPerpendicularLine(polylinemin, true, polylinemin.Length); |
|
IPointCollection pPointCol = polyline_vertical as IPointCollection; |
|
IPoint fPoint = new PointClass(); |
|
IPoint ePoint = new PointClass(); |
|
object missing2 = Type.Missing; |
|
polyline_vertical.QueryPoint(esriSegmentExtension.esriExtendAtFrom, -1 * polylinemin.Length, false, fPoint); |
|
pPointCol.InsertPoints(0, 1, ref fPoint); |
|
polyline_vertical.QueryPoint(esriSegmentExtension.esriExtendAtTo, polylinemin.Length + polylinemin.Length, false, ePoint); |
|
pPointCol.AddPoint(ePoint, ref missing2, ref missing2); |
|
IPolyline polyline = pPointCol as IPolyline; |
|
ITopologicalOperator topo = polyline_vertical as ITopologicalOperator; |
|
IGeometry extendgeo = topo.Intersect(polylinemax, esriGeometryDimension.esriGeometry0Dimension); |
|
IPoint point = null; |
|
if (extendgeo.GeometryType == esriGeometryType.esriGeometryPoint) |
|
{ |
|
point = extendgeo as IPoint; |
|
} |
|
else |
|
{ |
|
if (extendgeo.GeometryType == esriGeometryType.esriGeometryMultipoint) |
|
{ |
|
IPointCollection pointCollection = extendgeo as IPointCollection; |
|
if (pointCollection.PointCount > 0) |
|
{ |
|
point = pointCollection.get_Point(0); |
|
} |
|
else |
|
{ |
|
point = pointmax; |
|
} |
|
} |
|
} |
|
List<IPoint> points1 = new List<IPoint>() { point, pointList[1], pointmin }; |
|
IGeometry geometry1 = GenerateGeometryFromPoints(points1); |
|
geometry1.SpatialReference = bg_geometry.SpatialReference; |
|
diffgeo = FeatureAPI.Difference(diffgeo, geometry1); |
|
if (AECommonHelper.SharpAngleDataCheck(diffgeo, ref pointList1, ref angle1)) |
|
{ |
|
bg_geometry = FeatureAPI.Union(bg_geometry, geometry1); |
|
//bg_geometry = Passive_Sharp_Repair(pointList1, bg_geometry, diffgeo); |
|
} |
|
else |
|
{ |
|
bg_geometry = FeatureAPI.Union(bg_geometry, geometry1); |
|
if (diffgeo.GetEllipseArea() < 30) |
|
{ |
|
bg_geometry = FeatureAPI.Union(bg_geometry, diffgeo); |
|
} |
|
return bg_geometry; |
|
} |
|
} |
|
return bg_geometry; |
|
} |
|
catch (Exception ex) |
|
{ |
|
return bg_geometry; |
|
} |
|
} |
|
#endregion |
|
|
|
#region MyRegion |
|
/// <summary> |
|
/// 获取图形中的所有节点 |
|
/// </summary> |
|
/// <param name="geometry"></param> |
|
/// <returns></returns> |
|
private static List<IPoint> GetMultipleRingPoints(IGeometry geometry) |
|
{ |
|
List<IPoint> dicOPnts = new List<IPoint>(); |
|
try |
|
{ |
|
if (geometry == null) return dicOPnts; |
|
IGeometryCollection geometryCollection = geometry as IGeometryCollection; |
|
IRing ring = null; |
|
if (geometryCollection == null) |
|
{ |
|
IPointCollection iPntCollection = geometry as IPointCollection; |
|
if (iPntCollection == null || iPntCollection.PointCount <= 0) return dicOPnts; |
|
for (int j = 0; j < iPntCollection.PointCount - 1; j++) |
|
{ |
|
dicOPnts.Add(iPntCollection.Point[j]); |
|
} |
|
} |
|
else |
|
{ |
|
for (int i = 0; i < geometryCollection.GeometryCount; i++) |
|
{ |
|
ring = geometryCollection.get_Geometry(i) as IRing; |
|
IPointCollection iPntCollection = ring as IPointCollection; |
|
if (iPntCollection == null || iPntCollection.PointCount <= 0) return dicOPnts; |
|
for (int j = 0; j < iPntCollection.PointCount - 1; j++) |
|
{ |
|
dicOPnts.Add(iPntCollection.Point[j]); |
|
} |
|
} |
|
} |
|
|
|
} |
|
catch (System.Exception ex) |
|
{ |
|
|
|
} |
|
return dicOPnts; |
|
} |
|
#endregion |
|
|
|
#region GetPerpendicularLine |
|
/// <summary> |
|
/// 获取尖锐角顶点位置外扩一段距离的垂线 |
|
/// </summary> |
|
/// <param name="baseLine"></param> |
|
/// <param name="direction">clockwise顺时针 true为顺时针/false为逆时针</param> |
|
/// <returns></returns> |
|
private static IPolyline GetPerpendicularLine(IPolyline baseLine, bool clockwise, double length = 1) |
|
{ |
|
// 获取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; |
|
} |
|
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; |
|
} |
|
#endregion |
|
|
|
#region MyRegion |
|
private static List<ConcurrentClass> GetSnappingpoint2(IPoint point, List<BoundaryRepairGeometryMessages> m_featureLayer, List<string> listmoveToPoint = null, double distance = 1) |
|
{ |
|
List<ConcurrentClass> pointList = new List<ConcurrentClass>(); |
|
try |
|
{ |
|
foreach (BoundaryRepairGeometryMessages jcdltb in m_featureLayer) |
|
{ |
|
if (!jcdltb.IsReference) continue; |
|
IPoint iHitPt = new Point(); |
|
IHitTest iHitTest = jcdltb.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 (BoundaryRepairGeometryMessages item in m_featureLayer) |
|
{ |
|
if (!jcdltb.IsReference) continue; |
|
iHitTest = item.Geometry 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(jcdltb.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(jcdltb.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(jcdltb.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 = jcdltb.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) |
|
{ |
|
|
|
} |
|
return pointList; |
|
} |
|
#endregion |
|
|
|
#region 解决狭长图形问题 |
|
/// <summary> |
|
/// 解决狭长图形问题 |
|
/// </summary> |
|
/// <param name="geometry"></param> |
|
/// <returns></returns> |
|
private static IGeometry ResolveLongAndNarrow(IGeometry geometry) |
|
{ |
|
List<IPoint> pointList = null; |
|
double angle = 0; |
|
try |
|
{ |
|
///向内缓冲,如果还存在狭长的图形,暂不做处理 |
|
ITopologicalOperator topo = geometry as ITopologicalOperator; |
|
IGeometry tempgeometry = topo.Buffer(-0.06); |
|
// 消除缓冲区后的狭长部分 |
|
ITopologicalOperator bufferTopologicalOperator = tempgeometry as ITopologicalOperator; |
|
IGeometry geo = bufferTopologicalOperator.Buffer(0.05); |
|
geo.SpatialReference = geometry.SpatialReference; |
|
topo = geo as ITopologicalOperator; |
|
topo.Simplify(); |
|
//删除相邻节点距离较近的点 |
|
IPointCollection points = geo as IPointCollection; |
|
for (int i = 0; i < points.PointCount - 1; i++) |
|
{ |
|
IPoint tPoint = points.Point[i]; |
|
IPoint point = points.Point[i + 1]; |
|
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)) continue; |
|
if (Math.Abs(refdistance) < 1) |
|
{ |
|
points.RemovePoints(i + 1, 1); |
|
i = 0; |
|
points = geo as IPointCollection; |
|
continue; |
|
} |
|
} |
|
points.AddPoint(points.Point[points.PointCount - 1]); |
|
topo = geo as ITopologicalOperator; |
|
topo.Simplify(); |
|
if (SharpAngleDataCheck(geo, ref pointList, ref angle)) |
|
{ |
|
//狭长图形未处理 |
|
return geometry; |
|
} |
|
else |
|
{ |
|
geometry = geo; |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
return geometry; |
|
} |
|
return geometry; |
|
} |
|
|
|
public static IGeometry ResolveLongAndNarrow(IGeometry geometry, double distance) |
|
{ |
|
try |
|
{ |
|
///向内缓冲,如果还存在狭长的图形,暂不做处理 |
|
ITopologicalOperator topo = geometry as ITopologicalOperator; |
|
IGeometry tempgeometry = topo.Buffer(distance); |
|
// 消除缓冲区后的狭长部分 |
|
ITopologicalOperator bufferTopologicalOperator = tempgeometry as ITopologicalOperator; |
|
IGeometry geo = bufferTopologicalOperator.Buffer(Math.Abs(distance)); |
|
geo.SpatialReference = geometry.SpatialReference; |
|
topo = geo as ITopologicalOperator; |
|
topo.Simplify(); |
|
IGeometry geometryDis = FeatureAPI.Difference(geometry, geo); |
|
if (geometryDis == null || geometryDis.IsEmpty) |
|
{ |
|
//狭长图形未处理 |
|
return geometry; |
|
} |
|
else if (geometryDis.GetEllipseArea() < 5) |
|
{ |
|
return geo; |
|
} |
|
return geometry; |
|
} |
|
catch (Exception) |
|
{ |
|
return geometry; |
|
} |
|
} |
|
#endregion |
|
|
|
#region 要素存在尖锐角和局部狭长图形(即不允许存在一个角度小于10度,或局部图形狭长的情况) |
|
private static bool SharpAngleDataCheck(IGeometry geometry, ref List<IPoint> pointList, ref double angle) |
|
{ |
|
bool isSharpAngle = false; |
|
try |
|
{ |
|
if (geometry == null) return isSharpAngle; |
|
angle = GetMinAngle(geometry, ref pointList);//获取图形的最小角度 |
|
ITopologicalOperator topo = geometry as ITopologicalOperator; |
|
IPolyline line1 = topo.Boundary as IPolyline; |
|
double length1 = line1.Length;//原始图形的周长 |
|
int pointCount1 = (geometry as IPointCollection).PointCount; |
|
IGeometry geo = null; |
|
if (geometry.GetEllipseArea() < 30) |
|
geo = topo.Buffer(-0.05); |
|
else |
|
geo = topo.Buffer(-0.5); |
|
#region 向内缓冲后形成了多个图斑,则认定存在狭长 |
|
var geometry_diff = FeatureAPI.DissolveGeometryByRing(geometry); |
|
var Differences = FeatureAPI.DissolveGeometryByRing(geo); |
|
if (Differences != null && geometry_diff != null) |
|
{ |
|
if (Differences.Count > geometry_diff.Count) |
|
{ |
|
return true; |
|
} |
|
} |
|
#endregion |
|
ITopologicalOperator topo2 = geo as ITopologicalOperator; |
|
IPolyline line2 = topo2.Boundary as IPolyline; |
|
double length2 = line2.Length;//向内缓冲后的图形的周长 |
|
double delta_length = length1 - length2;//周长差 |
|
double avg_halfangle = 180 * (pointCount1 - 1 - 2) / (pointCount1 - 1) / 2;//平均 |
|
double conner_normal_length = 2 * 0.05 / Math.Tan(avg_halfangle * (Math.PI / 180)); |
|
if ((delta_length > 8 * conner_normal_length * (pointCount1 - 1)) || angle < 10) |
|
{ |
|
if ((delta_length > 8 * conner_normal_length * (pointCount1 - 1)) && angle < 10) |
|
return true; |
|
else if (delta_length > 8 * conner_normal_length * (pointCount1 - 1)) |
|
return true; |
|
else if (angle < 10) |
|
return true; |
|
} |
|
} |
|
catch (Exception) |
|
{ |
|
|
|
} |
|
finally |
|
{ |
|
//GC.Collect(); |
|
} |
|
return isSharpAngle; |
|
} |
|
/// <summary> |
|
/// 获取最小角度 |
|
/// </summary> |
|
/// <param name="pGeo"></param> |
|
/// <returns></returns> |
|
private static double GetMinAngle(IGeometry pGeo, ref List<IPoint> pointlist) |
|
{ |
|
double result = -1; |
|
IPolygon4 poly4 = null; |
|
ITopologicalOperator topo = null; |
|
GeometryBag geoBag = null; |
|
IGeometryCollection geoCollection = null; |
|
pointlist = new List<IPoint>(); |
|
try |
|
{ |
|
if (pGeo == null || pGeo.IsEmpty) |
|
return result; |
|
poly4 = pGeo as IPolygon4; |
|
topo = poly4 as ITopologicalOperator; |
|
topo?.Simplify(); |
|
geoBag = poly4.ExteriorRingBag as GeometryBag; |
|
if (geoBag == null) return result; |
|
geoCollection = geoBag as IGeometryCollection; |
|
List<IGeometry> rings = new List<IGeometry>(); |
|
for (int j = 0; j < geoCollection.GeometryCount; j++) |
|
{ |
|
IGeometry geo = geoCollection.get_Geometry(j); |
|
rings.Add(geo); |
|
//内环图形 |
|
IGeometryBag InteriorBag = (pGeo as IPolygon4).get_InteriorRingBag(geo as IRing); |
|
if (InteriorBag != null) |
|
{ |
|
IGeometryCollection InteriorRingGeometryCollection = InteriorBag as IGeometryCollection; |
|
for (int IR = 0; IR < InteriorRingGeometryCollection.GeometryCount; IR++) |
|
{ |
|
rings.Add(InteriorRingGeometryCollection.get_Geometry(IR)); |
|
} |
|
} |
|
} |
|
foreach (IGeometry ring in rings) |
|
{ |
|
if (ring.IsEmpty) continue; |
|
IPointCollection points = ring as IPointCollection; |
|
int num = points.PointCount - 1; |
|
for (int i = 0; i < num; i++) |
|
{ |
|
IPoint p1 = null; |
|
IPoint p2 = points.get_Point(i); |
|
IPoint p3 = null; |
|
if (i == 0) |
|
{ |
|
p1 = points.get_Point(num - 1); |
|
p3 = points.get_Point(i + 1); |
|
} |
|
else if (i == num - 1) |
|
{ |
|
p1 = points.get_Point(i - 1); |
|
p3 = points.get_Point(0); |
|
} |
|
else |
|
{ |
|
p1 = points.get_Point(i - 1); |
|
p3 = points.get_Point(i + 1); |
|
} |
|
if ((p2.X == p1.X && p2.Y == p1.Y) || (p2.X == p3.X && p2.Y == p3.Y)) |
|
continue; |
|
|
|
double angle = GetAngle(p2, p1, p3); |
|
if (result == -1) |
|
{ |
|
result = angle; |
|
pointlist.Add(p1); |
|
pointlist.Add(p2); |
|
pointlist.Add(p3); |
|
} |
|
else |
|
{ |
|
if (result > angle) |
|
{ |
|
result = angle; |
|
if (pointlist.Count > 0) pointlist.Clear(); |
|
pointlist.Add(p1); |
|
pointlist.Add(p2); |
|
pointlist.Add(p3); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw ex; |
|
} |
|
finally |
|
{ |
|
} |
|
return result; |
|
} |
|
/// <summary> |
|
/// 计算角度 |
|
/// </summary> |
|
/// <param name="cenPoint"></param> |
|
/// <param name="firstPoint"></param> |
|
/// <param name="secondPoint"></param> |
|
/// <returns></returns> |
|
private 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; |
|
} |
|
#endregion |
|
|
|
#region GetRelativeAngle |
|
/// <summary> |
|
/// 获取当前点与前后两个点之间的夹角的角度 |
|
/// </summary> |
|
/// <param name="geometry"></param> |
|
/// <param name="point"></param> |
|
/// <returns></returns> |
|
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 BoundaryRepairGeometryMessages |
|
{ |
|
public int Objectid { get; set; } |
|
public string DLBM { get; set; } |
|
public string CZCSXM { get; set; } |
|
public string BSM { get; set; } |
|
public IGeometry Geometry { get; set; } |
|
public bool IsReference { get; set; } |
|
public bool Modify { get; set; } |
|
public string Describe { get; set; } |
|
} |
|
|
|
public class BoundaryRepairEntity |
|
{ |
|
public IGeometry Geometry { get; set; } |
|
public string DLBM { get; set; } |
|
public string CZCSXM { get; set; } |
|
public int MJ { get; set; } |
|
public List<BoundaryRepairGeometryMessages> ListReference { get; set; } |
|
public string DKID { get; set; } |
|
} |
|
|
|
}
|
|
|