森林草原湿地荒漠调查
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.
 
 
 

811 lines
36 KiB

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using KGIS.Framework.Utils.ExtensionMethod;
namespace Kingo.PluginServiceInterface.Helper
{
/// <summary>
/// 多边形边界对齐工具(针对ArcEngine 10.2.2优化版本)
/// 主要功能:调整目标多边形的顶点坐标,使其与相邻几何体的边界对齐
/// 优化重点:空间索引结构、COM对象管理、批量坐标操作
/// </summary>
public static class PolygonBoundaryAligner
{
#region 公共常量与接口
private const double DEFAULT_TOLERANCE = 0.001; // 默认捕捉容差(地图单位)
private static readonly object _syncRoot = new object(); // 线程安全锁
#endregion
#region 主入口方法
/// <summary>
/// 对齐多边形边界的主方法
/// </summary>
/// <param name="target">目标多边形</param>
/// <param name="adjacentGeometries">相邻几何体集合</param>
/// <param name="tolerance">捕捉容差(默认0.001)</param>
/// <returns>调整后的多边形</returns>
public static IGeometry AlignPolygonBoundary(IGeometry target, List<IGeometry> adjacentGeometries, double tolerance = DEFAULT_TOLERANCE)
{
// 参数校验
ValidateParameters(target, adjacentGeometries);
// 克隆原始几何体(避免修改输入参数)
IPolygon originalPolygon = (IPolygon)((IClone)target).Clone();
IPolygon newPolygon = new PolygonClass();
newPolygon.SpatialReference = originalPolygon.SpatialReference;
try
{
// 步骤1:收集相邻几何体的边界要素
List<IGeometry> adjacentBoundaries = CollectAdjacentBoundaries(adjacentGeometries);
// 步骤2:构建空间索引(顶点索引和线段索引)
ITopologicalOperator topological = originalPolygon as ITopologicalOperator;
var (vertexIndex, segmentIndex) = BuildSpatialIndexes(adjacentBoundaries, topological.Boundary, tolerance);
if (vertexIndex.IsEmpty && segmentIndex.IsEmpty)
{
return target;
//(vertexIndex, segmentIndex) = BuildSpatialIndexes(adjacentBoundaries, tolerance);
}
// 步骤3:调整多边形顶点
//IPointCollection points = (IPointCollection)originalPolygon;
List<IPointCollection> points = new List<IPointCollection>();
IGeometryCollection geometryCollection = (IGeometryCollection)originalPolygon;
for (int i = 0; i < geometryCollection.GeometryCount; i++)
{
IRing ring = (IRing)geometryCollection.get_Geometry(i);
IPointCollection ringPoints = (IPointCollection)ring;
points.Add(ringPoints);
}
newPolygon = AdjustWithLegacyMethod(points, vertexIndex, segmentIndex, tolerance, adjacentBoundaries);
// 步骤4:拓扑验证与简化
EnsureTopologyValidity(ref newPolygon);
return (IGeometry)newPolygon;
}
catch (Exception ex)
{
throw ex;
}
finally
{
// 显式释放COM对象(重要!防止内存泄漏)
SafeReleaseComObject(originalPolygon);
}
}
#endregion
#region 核心处理逻辑
/// <summary>
/// 获取调整后的所有环(外环+内环)
/// </summary>
private static IEnumerable<IPolygon> GetAdjustedRings(IPolygon polygon, VertexSpatialIndex vertexIndex, SegmentSpatialIndex segmentIndex, double tolerance, List<IGeometry> boundaries)
{
IGeometryCollection geomColl = (IGeometryCollection)polygon;
for (int i = 0; i < geomColl.GeometryCount; i++)
{
if (geomColl.get_Geometry(i) is IRing ring && !ring.IsEmpty)
{
yield return AdjustRingVertices(ring, vertexIndex, segmentIndex, tolerance, boundaries);
}
}
}
private static IPolygon AdjustRingVertices(IRing ring, VertexSpatialIndex vertexIndex, SegmentSpatialIndex segmentIndex, double tolerance, List<IGeometry> boundaries)
{
// 获取点集合接口(兼容10.2.2)
IPointCollection points = (IPointCollection)ring;
return AdjustWithLegacyMethod(new List<IPointCollection> { points }, vertexIndex, segmentIndex, tolerance, boundaries);
}
/// <summary>
/// 兼容方法:传统逐个点操作(ArcEngine 10.0 以下备用)
/// </summary>
private static IPolygon AdjustWithLegacyMethod(List<IPointCollection> allPoints, VertexSpatialIndex vertexIndex, SegmentSpatialIndex segmentIndex, double tolerance, List<IGeometry> boundaries)
{
IPolygon newPolygon = new PolygonClass();
IGeometryCollection newGeomColl = (IGeometryCollection)newPolygon;
for (int k = 0; k < allPoints.Count; k++)
{
int pointCount = allPoints[k].PointCount;
bool modified = false;
var coords = new List<(double X, double Y)>();
for (int i = 0; i < pointCount; i++)
{
IPoint p = allPoints[k].get_Point(i);
//string aa1 = GeometryConvertHelper.ConvertIGeoemtryToWKT(p);
try
{
coords.Add((p.X, p.Y));
}
finally
{
Marshal.ReleaseComObject(p);
}
}
// 坐标调整逻辑
Dictionary<int, (double X, double Y)> keyValuePairs = new Dictionary<int, (double X, double Y)>();
for (int i = 0; i < coords.Count; i++)
{
var (x, y) = coords[i];
var snappedPoints = vertexIndex.FindAllVertices(x, y, tolerance).Distinct().ToList();
if (snappedPoints != null && snappedPoints.Count == 2)
{
double distSq0 = (coords[i].X - snappedPoints[0].X) * (coords[i].X - snappedPoints[0].X) + (coords[i].Y - snappedPoints[0].Y) * (coords[i].Y - snappedPoints[0].Y);
double distSq1 = (coords[i].X - snappedPoints[1].X) * (coords[i].X - snappedPoints[1].X) + (coords[i].Y - snappedPoints[1].Y) * (coords[i].Y - snappedPoints[1].Y);
if (distSq0 > distSq1)
{
coords[i] = snappedPoints[1];
keyValuePairs.Add(i, snappedPoints[0]);
}
else
{
coords[i] = snappedPoints[0];
keyValuePairs.Add(i, snappedPoints[1]);
}
continue;
}
var snappedPoint = vertexIndex.FindClosestVertex(x, y, tolerance);
if (snappedPoint == null)
{
snappedPoint = segmentIndex.FindClosestPoint(x, y, tolerance);
}
else
{
var currents = coords.Where(current => current.X != x && current.Y != y).ToList();
var coordscoords = currents.FirstOrDefault(kvp => Math.Abs(kvp.X - x) < 0.001 && Math.Abs(kvp.Y - y) < 0.001);
if ((coords.Contains(snappedPoint.Value) && coords[0] != snappedPoint.Value) || (coordscoords.X != 0 && coordscoords.Y != 0))
{
snappedPoint = segmentIndex.FindClosestPoint(x, y, tolerance);
}
}
if (snappedPoint.HasValue)
{
if (coords.Contains(snappedPoint.Value) && coords[0] != snappedPoint.Value)
{
int firstIndex = coords.Select((item, idx) => new { item, idx }).
FirstOrDefault(pair => pair.item.X == snappedPoint.Value.X && pair.item.Y == snappedPoint.Value.Y)?.idx ?? -1;
if (firstIndex != -1 && i > firstIndex)
{
coords[i] = (0, 0);
continue;
}
}
var currents = coords.Where(current => current.X != x && current.Y != y).ToList();
var coordscoords = currents.FirstOrDefault(kvp => Math.Abs(kvp.X - x) < 0.1 && Math.Abs(kvp.Y - y) < 0.1);
//var dSnappedPoint = CalculateDistance(snappedPoint.Value.X, snappedPoint.Value.Y, x, y);
//var dCoordscoords = CalculateDistance(coordscoords.X, coordscoords.Y, x, y);
//var gap = Math.Abs(dSnappedPoint - dCoordscoords);
//if (coordscoords.X != 0 && coordscoords.Y != 0 && dSnappedPoint > dCoordscoords && gap > 0.001)
// continue;
coords[i] = snappedPoint.Value;
modified = true;
}
}
// 更新坐标
if (modified)
{
allPoints[k].RemovePoints(0, pointCount);
IPoint newPoint = new PointClass();
if (keyValuePairs.Count > 0)
{
foreach (var item in keyValuePairs)
{
coords.Insert(item.Key, item.Value);
}
}
foreach (var (X, Y) in coords)
{
if (X == 0 || Y == 0) continue;
newPoint.PutCoords(X, Y);
allPoints[k].AddPoint(newPoint);
}
Marshal.ReleaseComObject(newPoint);
}
newGeomColl.AddGeometry((IGeometry)allPoints[k]);
string aa = GeometryConvertHelper.ConvertIGeoemtryToWKT(newPolygon);
Addnode(newPolygon, boundaries);
}
return newPolygon;
//IGeometryCollection geomColl = (IGeometryCollection)newPolygon;
//for (int i = 0; i < geomColl.GeometryCount; i++)
//{
// IGeometry geometry = geomColl.get_Geometry(i);
// IRing ring1 = geometry as IRing;
// if (ring1 == null || ring1.IsEmpty || ring1.Length < 0.01) continue;
// return ring1;
//}
//return null;
}
public static double CalculateDistance(double x1, double y1, double x2, double y2)
{
// 计算坐标差值的平方和
double deltaX = x2 - x1;
double deltaY = y2 - y1;
double distanceSquared = deltaX * deltaX + deltaY * deltaY;
// 开平方根得到距离(使用Math.Sqrt)
return Math.Sqrt(distanceSquared);
}
#endregion
#region 空间索引构建
private static (VertexSpatialIndex vertexIndex, SegmentSpatialIndex segmentIndex) BuildSpatialIndexes(List<IGeometry> boundaries, IGeometry targetBoundary, double tolerance)
{
double xRange = targetBoundary.Envelope.XMax - targetBoundary.Envelope.XMin;
double yRange = targetBoundary.Envelope.YMax - targetBoundary.Envelope.YMin;
int totalVertices = boundaries.Sum(g => (g as IPointCollection)?.PointCount ?? 0);
double density = totalVertices / (xRange * yRange); // 顶点密度(点/单位面积)
double baseCellSize = Math.Max(xRange, yRange) / 100;
double cellSize = density > 100 ? baseCellSize / 2 : // 高密度:缩小网格
density < 10 ? baseCellSize * 2 : // 低密度:扩大网格
baseCellSize;
var vertexIndex = new VertexSpatialIndex(cellSize);
var segmentIndex = new SegmentSpatialIndex(cellSize);
double maxDistance = tolerance * 20; // 设定最大距离阈值
int threshold = Math.Max(Environment.ProcessorCount * 100, 1000); // 最小阈值1000
foreach (var geom in boundaries)
{
if (geom is IPointCollection pointColl)
{
if (pointColl.PointCount > threshold)
{
Parallel.For(0, pointColl.PointCount, i =>
{
IPoint point = pointColl.get_Point(i);
try
{
double distance = CalculateDistance(point, targetBoundary);
if (distance <= maxDistance)
{
vertexIndex.AddPoint(point); // 线程安全
}
}
finally
{
Marshal.ReleaseComObject(point);
}
});
}
else
{
for (int i = 0; i < pointColl.PointCount; i++)
{
IPoint point = pointColl.get_Point(i);
try
{
// 计算点到目标边界的距离
double distance = CalculateDistance(point, targetBoundary);
if (distance <= maxDistance)
{
vertexIndex.AddPoint(point);
}
}
finally
{
Marshal.ReleaseComObject(point);
}
}
}
}
if (geom is ISegmentCollection segColl)
{
for (int i = 0; i < segColl.SegmentCount; i++)
{
ISegment segment = segColl.get_Segment(i);
try
{
IPolyline polyline1 = new PolylineClass();
polyline1.FromPoint = segment.FromPoint;
polyline1.ToPoint = segment.ToPoint;
polyline1.SpatialReference = targetBoundary.SpatialReference;
double distancepolyline1 = CalculateDistance(polyline1, targetBoundary);
if (distancepolyline1 <= maxDistance && distancepolyline1 >= 0)
{
segmentIndex.AddSegment(segment);
}
}
catch
{
}
finally
{
Marshal.ReleaseComObject(segment);
}
}
}
}
return (vertexIndex, segmentIndex);
}
// 计算几何体到目标边界的距离
private static double CalculateDistance(IGeometry geom, IGeometry targetBoundary)
{
if (geom == null || targetBoundary == null) return double.MaxValue;
//if (geom is IPoint point && targetBoundary is IPolygon polygon)
//{
// return CalculateDistanceLocal(point, polygon); // 本地计算
//}
// 其他类型回退到COM调用
try
{
IProximityOperator proximityOp = (IProximityOperator)targetBoundary;
return proximityOp.ReturnDistance(geom);
}
catch
{
return double.MaxValue;
}
}
#endregion
#region 空间索引实现类
/// <summary>
/// 顶点空间索引(使用双层字典的网格索引)
/// 优化点:提高网格查询速度,减少距离计算次数
/// </summary>
private class VertexSpatialIndex
{
private readonly Dictionary<long, Dictionary<long, List<(double X, double Y)>>> _grid;
private readonly double _cellSize;
private int _totalPoints = 0;
public bool IsEmpty => _totalPoints == 0;
public VertexSpatialIndex(double cellSize)
{
_cellSize = cellSize;
_grid = new Dictionary<long, Dictionary<long, List<(double X, double Y)>>>();
}
/// <summary>
/// 添加顶点到索引(自动网格化)
/// </summary>
public void AddPoint(IPoint point)
{
long xCell = (long)(point.X / _cellSize);
long yCell = (long)(point.Y / _cellSize);
lock (_syncRoot)
{
if (!_grid.TryGetValue(xCell, out var yDict))
{
yDict = new Dictionary<long, List<(double X, double Y)>>();
_grid[xCell] = yDict;
}
if (!yDict.TryGetValue(yCell, out var points))
{
points = new List<(double X, double Y)>();
yDict[yCell] = points;
}
// 去重逻辑:检查容差范围内是否已有重复点
bool isDuplicate = false;
double toleranceSq = _cellSize * _cellSize; // 基于网格精度的容差
foreach (var p in points)
{
double dx = p.X - point.X;
double dy = p.Y - point.Y;
if (dx * dx + dy * dy <= toleranceSq) // 平方距离比较(避免开方)
{
isDuplicate = true;
break;
}
}
if (!isDuplicate)
{
points.Add((point.X, point.Y));
_totalPoints++;
}
}
}
/// <summary>
/// 查找最近顶点(带容差范围)
/// </summary>
public (double X, double Y)? FindClosestVertex(double x, double y, double tolerance)
{
long centerX = (long)(x / _cellSize);
long centerY = (long)(y / _cellSize);
int radius = (int)Math.Ceiling(tolerance / _cellSize);
double minDist = tolerance * tolerance;
(double X, double Y)? closest = null;
// 网格搜索范围扩展
for (long dx = -radius; dx <= radius; dx++)
{
if (!_grid.TryGetValue(centerX + dx, out var yDict)) continue;
for (long dy = -radius; dy <= radius; dy++)
{
if (!yDict.TryGetValue(centerY + dy, out var points)) continue;
foreach (var (pX, pY) in points)
{
double dxVal = pX - x;
double dyVal = pY - y;
double distSq = dxVal * dxVal + dyVal * dyVal;
if (distSq < minDist)
{
minDist = distSq;
closest = (pX, pY);
}
}
}
}
return closest;
}
/// <summary>
/// 根据坐标获取相邻范围内的所有点
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="tolerance"></param>
/// <returns></returns>
public List<(double X, double Y)> FindAllVertices(double x, double y, double tolerance)
{
long centerX = (long)(x / _cellSize);
long centerY = (long)(y / _cellSize);
int radius = (int)Math.Ceiling(tolerance / _cellSize);
var result = new List<(double X, double Y)>();
double toleranceSq = tolerance * tolerance;
// 遍历邻近网格
for (long dx = -radius; dx <= radius; dx++)
{
if (!_grid.TryGetValue(centerX + dx, out var yDict)) continue;
for (long dy = -radius; dy <= radius; dy++)
{
if (!yDict.TryGetValue(centerY + dy, out var points)) continue;
// 筛选所有容差内的点
foreach (var (pX, pY) in points)
{
double distSq = (pX - x) * (pX - x) + (pY - y) * (pY - y);
if (distSq <= toleranceSq)
{
result.Add((pX, pY));
}
}
}
}
return result;
}
}
/// <summary>
/// 线段空间索引(使用网格索引+包围盒预计算)
/// 优化点:减少不必要的线段距离计算
/// </summary>
private class SegmentSpatialIndex
{
private readonly Dictionary<long, Dictionary<long, List<SegmentData>>> _grid;
private readonly List<SegmentData> _allSegments;
private readonly double _cellSize;
public bool IsEmpty => _grid.Count == 0;
public SegmentSpatialIndex(double cellSize)
{
_cellSize = cellSize;
_grid = new Dictionary<long, Dictionary<long, List<SegmentData>>>();
_allSegments = new List<SegmentData>();
}
/// <summary>
/// 添加线段到索引(自动计算影响网格)
/// </summary>
public void AddSegment(ISegment segment)
{
var segData = new SegmentData(segment.FromPoint.X, segment.FromPoint.Y, segment.ToPoint.X, segment.ToPoint.Y);
lock (_syncRoot)
{
_allSegments.Add(segData); // 全局列表存储引用
// 计算网格范围
long minXCell = (long)(Math.Min(segData.StartX, segData.EndX) / _cellSize);
long maxXCell = (long)(Math.Max(segData.StartX, segData.EndX) / _cellSize);
long minYCell = (long)(Math.Min(segData.StartY, segData.EndY) / _cellSize);
long maxYCell = (long)(Math.Max(segData.StartY, segData.EndY) / _cellSize);
// 添加到所有覆盖的网格(引用传递,无副本)
for (long x = minXCell; x <= maxXCell; x++)
{
for (long y = minYCell; y <= maxYCell; y++)
{
if (!_grid.TryGetValue(x, out var yDict))
{
yDict = new Dictionary<long, List<SegmentData>>();
_grid[x] = yDict;
}
if (!yDict.TryGetValue(y, out var list))
{
list = new List<SegmentData>();
yDict[y] = list;
}
// 避免重复添加(若外部可能重复调用AddSegment)
if (!list.Contains(segData))
{
list.Add(segData);
}
}
}
}
}
/// <summary>
/// 查找最近线段点(两阶段查询:先网格后全局)
/// </summary>
public (double X, double Y)? FindClosestPoint(double x, double y, double tolerance)
{
long centerX = (long)(x / _cellSize);
long centerY = (long)(y / _cellSize);
int radius = (int)Math.Ceiling(tolerance / _cellSize);
var candidates = new HashSet<SegmentData>();
double minDist = tolerance * tolerance;
(double X, double Y)? closest = null;
// 阶段1:收集附近网格中的候选线段
for (long dx = -radius; dx <= radius; dx++)
{
if (!_grid.TryGetValue(centerX + dx, out var yDict)) continue;
for (long dy = -radius; dy <= radius; dy++)
{
if (yDict.TryGetValue(centerY + dy, out var segList))
{
foreach (var seg in segList)
{
candidates.Add(seg);
}
}
}
}
// 阶段2:如果附近没有候选,则遍历全部线段
if (candidates.Count == 0)
{
candidates = new HashSet<SegmentData>(_allSegments);
}
// 计算最近点
foreach (var seg in candidates)
{
var (cx, cy, distSq) = CalculateClosestPoint(x, y, seg);
if (distSq < minDist)
{
minDist = distSq;
closest = (cx, cy);
}
}
return closest;
}
/// <summary>
/// 计算点到线段的最短距离(向量投影法)
/// </summary>
private static (double X, double Y, double DistanceSq) CalculateClosestPoint(
double x, double y, SegmentData seg)
{
double dx = seg.EndX - seg.StartX;
double dy = seg.EndY - seg.StartY;
double lengthSq = dx * dx + dy * dy;
// 处理零长度线段
if (lengthSq < 1e-10)
{
double distSq1 = (x - seg.StartX) * (x - seg.StartX) + (y - seg.StartY) * (y - seg.StartY);
return (seg.StartX, seg.StartY, distSq1);
}
// 计算投影参数
double t = ((x - seg.StartX) * dx + (y - seg.StartY) * dy) / lengthSq;
t = Math.Max(0, Math.Min(1, t)); // 限制在线段范围内
double projX = seg.StartX + t * dx;
double projY = seg.StartY + t * dy;
double distSq = (x - projX) * (x - projX) + (y - projY) * (y - projY);
return (projX, projY, distSq);
}
/// <summary>
/// 线段数据结构(引用类型)
/// </summary>
private sealed class SegmentData
{
public double StartX { get; }
public double StartY { get; }
public double EndX { get; }
public double EndY { get; }
public SegmentData(double sx, double sy, double ex, double ey)
{
StartX = sx;
StartY = sy;
EndX = ex;
EndY = ey;
}
}
}
#endregion
#region 辅助方法
/// <summary>
/// 参数有效性校验
/// </summary>
private static void ValidateParameters(IGeometry target, List<IGeometry> adjacentGeometries)
{
if (target == null)
throw new ArgumentNullException(nameof(target), "目标几何体不能为空");
if (adjacentGeometries == null)
throw new ArgumentNullException(nameof(adjacentGeometries), "相邻几何体集合不能为空");
if (target.GeometryType != esriGeometryType.esriGeometryPolygon)
throw new ArgumentException("目标几何体必须是多边形类型");
}
/// <summary>
/// 收集相邻几何体的边界要素(多线程安全)
/// </summary>
private static List<IGeometry> CollectAdjacentBoundaries(IEnumerable<IGeometry> geometries)
{
var boundaries = new ConcurrentBag<IGeometry>(); // 线程安全集合
Parallel.ForEach(geometries.Where(g => g?.IsEmpty == false), geom =>
{
switch (geom.GeometryType)
{
case esriGeometryType.esriGeometryPolygon:
var polyColl = (IGeometryCollection)geom;
for (int i = 0; i < polyColl.GeometryCount; i++)
{
if (polyColl.get_Geometry(i) is IRing ring && !ring.IsEmpty)
{
ring.SpatialReference = geom.SpatialReference;
boundaries.Add(ring); // 线程安全添加
}
}
break;
case esriGeometryType.esriGeometryPolyline:
boundaries.Add(geom);
break;
}
});
return boundaries.ToList(); // 转换为普通列表
}
/// <summary>
/// 确保多边形拓扑有效性
/// </summary>
private static void EnsureTopologyValidity(ref IPolygon polygon)
{
ITopologicalOperator topoOp = (ITopologicalOperator)polygon;
if (!topoOp.IsSimple)
{
topoOp.Simplify();
}
// 二次验证几何完整性
if (polygon.IsEmpty)
{
throw new InvalidOperationException("拓扑简化导致几何体无效");
}
}
/// <summary>
/// 安全释放COM对象(带空值检查)
/// </summary>
private static void SafeReleaseComObject(object comObj)
{
if (comObj != null && Marshal.IsComObject(comObj))
{
Marshal.ReleaseComObject(comObj);
}
}
#endregion
#region MyRegion
private static void Addnode(IPolygon newPolygon, List<IGeometry> adjacentGeometries)
{
double maxDistance = 0.1; // 设定最大距离阈值
//待插入节点坐标及索引
Dictionary<int, (double X, double Y)> insertionPoints = new Dictionary<int, (double X, double Y)>();
//原始图形的点坐标及索引
Dictionary<int, (double X, double Y)> originalpoints = new Dictionary<int, (double X, double Y)>();
List<IPolyline> polylines = new List<IPolyline>();
var coords = new List<(double X, double Y)>();
try
{
IPointCollection points = (IPointCollection)newPolygon;
var pointCount = points.PointCount;
for (int i = 0; i < pointCount; i++)
{
IPoint p = points.get_Point(i);
try
{
coords.Add((p.X, p.Y));
originalpoints.Add(i, (p.X, p.Y));
}
finally
{
Marshal.ReleaseComObject(p);
}
}
if (newPolygon is ISegmentCollection segColl)
{
for (int i = 0; i < segColl.SegmentCount; i++)
{
ISegment segment = segColl.get_Segment(i);
try
{
IPolyline polyline1 = new PolylineClass();
polyline1.FromPoint = segment.FromPoint;
polyline1.ToPoint = segment.ToPoint;
polyline1.SpatialReference = newPolygon.SpatialReference;
polylines.Add(polyline1);
}
finally
{
Marshal.ReleaseComObject(segment);
}
}
}
bool isbreak = false;
foreach (IGeometry geom in adjacentGeometries)
{
if (geom is IPointCollection pointColl)
{
for (int i = 0; i < pointColl.PointCount; i++)
{
IPoint point = pointColl.get_Point(i);
try
{
foreach (var polyline in polylines)
{
double distance = CalculateDistance(point, polyline);
if (distance == 0 || distance > 1) continue;
double distanceToPoint = CalculateDistance(point, polyline.ToPoint);
double distanceFromPoint = CalculateDistance(point, polyline.FromPoint);
if (distance == distanceToPoint || distance == distanceFromPoint) continue;
if ((distance < 0.01 && (distanceToPoint < 0.01) || distanceFromPoint < 0.01))
continue;
if (distance <= maxDistance && distance.ToDouble(5) > 0.00001)
{
if (coords.Contains((point.X, point.Y))) continue;
var coordscoords = coords.FirstOrDefault(kvp => Math.Abs(kvp.X - point.X) < 0.1 && Math.Abs(kvp.Y - point.Y) < 0.1);
if (coordscoords.X != 0 && coordscoords.Y != 0) continue;
IPoint ToPoint = polyline.ToPoint;
var keyValuePair2 = originalpoints.FirstOrDefault(kvp => Math.Abs(kvp.Value.X - ToPoint.X) < 0.0001 && Math.Abs(kvp.Value.Y - ToPoint.Y) < 0.0001);
var pointindex = keyValuePair2.Equals(default(KeyValuePair<int, (double X, double Y)>)) ? -1 : keyValuePair2.Key;
if (insertionPoints.ContainsKey(pointindex)) continue;
insertionPoints.Add(pointindex, (point.X, point.Y));
isbreak = true;
break;
}
}
if (isbreak) break;
}
finally
{
Marshal.ReleaseComObject(point);
}
}
}
if (isbreak) break;
}
if (insertionPoints.Count > 0)
{
foreach (var item in insertionPoints)
coords.Insert(item.Key, item.Value);
points.RemovePoints(0, pointCount);
IPoint newPoint = new PointClass();
foreach (var (X, Y) in coords)
{
newPoint.PutCoords(X, Y);
points.AddPoint(newPoint);
}
Marshal.ReleaseComObject(newPoint);
Addnode(newPolygon, adjacentGeometries);
}
}
catch (Exception)
{
throw;
}
}
#endregion
}
}