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.
160 lines
6.3 KiB
160 lines
6.3 KiB
using System; |
|
using System.Collections.Generic; |
|
using ESRI.ArcGIS.esriSystem; |
|
using ESRI.ArcGIS.Geometry; |
|
namespace Kingo.PluginServiceInterface.Helper |
|
{ |
|
public static class GeometryComparator |
|
{ |
|
// 默认空间关系检测容差(单位与几何坐标系一致) |
|
private const double DEFAULT_TOLERANCE = 0.001; |
|
|
|
// 用于坐标差异比较的极小容差(防止浮点数精度误差导致的误判) |
|
private const double COORDINATE_TOLERANCE = 1e-9; |
|
|
|
/// <summary> |
|
/// 图形对比分析:检测目标几何体与相邻几何体集合是否存在满足以下条件的顶点对: |
|
/// 1. 空间距离小于等于指定容差 |
|
/// 2. 实际坐标差异大于精度容差(排除坐标系转换导致的微小差异) |
|
/// </summary> |
|
/// <param name="targetGeometry">需要分析的目标几何体</param> |
|
/// <param name="adjacentGeometries">相邻几何体集合</param> |
|
/// <param name="tolerance">空间关系判定容差(默认1mm)</param> |
|
/// <returns> |
|
/// true: 存在符合条件的顶点对 | false: 未找到符合条件的顶点对或输入无效 |
|
/// </returns> |
|
/// <remarks> |
|
/// 算法复杂度:O(n*m) (建议对大规模数据使用空间索引优化) |
|
/// 坐标系要求:投影坐标系(保证距离计算准确) |
|
/// </remarks> |
|
public static bool SpatialRelationshipAnalysis( |
|
IGeometry targetGeometry, |
|
IEnumerable<IGeometry> adjacentGeometries, |
|
double tolerance = DEFAULT_TOLERANCE) |
|
{ |
|
// 参数有效性验证 |
|
if (targetGeometry == null || |
|
adjacentGeometries == null || |
|
tolerance < 0) |
|
return false; |
|
|
|
// 提取目标几何体的拓扑正确顶点集合 |
|
var targetVertices = ExtractTopologicalVertices(targetGeometry); |
|
if (targetVertices.Count == 0) return false; |
|
|
|
// 预计算容差平方值用于快速比较 |
|
var squaredTolerance = tolerance * tolerance; |
|
|
|
// 遍历所有相邻几何体进行对比分析 |
|
foreach (var adjacentGeometry in adjacentGeometries) |
|
{ |
|
// 跳过无效几何体 |
|
if (adjacentGeometry == null) continue; |
|
|
|
// 提取相邻几何体的拓扑正确顶点集合 |
|
var adjacentVertices = ExtractTopologicalVertices(adjacentGeometry); |
|
if (adjacentVertices.Count == 0) continue; |
|
|
|
// 双层循环比对顶点(可优化为空间索引查询) |
|
foreach (var targetVertex in targetVertices) |
|
{ |
|
foreach (var adjacentVertex in adjacentVertices) |
|
{ |
|
// 快速平方距离计算(避免Math.Sqrt开销) |
|
if (CalculateSquaredDistance(targetVertex, adjacentVertex) > squaredTolerance) |
|
continue; |
|
|
|
// 精确坐标差异验证(排除容差范围内的坐标舍入误差) |
|
if (HasSignificantCoordinateDifference(targetVertex, adjacentVertex)) |
|
{ |
|
return true; |
|
} |
|
|
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// 从几何体中提取拓扑正确的顶点集合 |
|
/// </summary> |
|
/// <param name="geometry">输入的几何对象</param> |
|
/// <returns>顶点集合(可能为空)</returns> |
|
/// <remarks> |
|
/// 处理流程: |
|
/// 1. 创建几何副本避免修改原始数据 |
|
/// 2. 执行拓扑简化确保几何有效性 |
|
/// 3. 提取顶点信息 |
|
/// </remarks> |
|
private static List<IPoint> ExtractTopologicalVertices(IGeometry geometry) |
|
{ |
|
var vertices = new List<IPoint>(); |
|
try |
|
{ |
|
// 创建几何副本(隔离原始对象) |
|
var clonedGeometry = (geometry as IClone)?.Clone() as IGeometry; |
|
if (clonedGeometry == null) return vertices; |
|
|
|
// 拓扑规范化处理 |
|
if (clonedGeometry is ITopologicalOperator topology) |
|
{ |
|
if (!topology.IsKnownSimple) |
|
topology.Simplify(); |
|
} |
|
|
|
// 顶点提取策略选择 |
|
switch (clonedGeometry) |
|
{ |
|
case IPoint point: |
|
vertices.Add(point); |
|
break; |
|
case IPointCollection pointCollection: |
|
ExtractVerticesFromCollection(pointCollection, vertices); |
|
break; |
|
// 可扩展其他几何类型(如IMultiPatch等)的处理逻辑 |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
// 实际应用中应添加日志记录 |
|
System.Diagnostics.Debug.WriteLine($"顶点提取异常:{ex.Message}"); |
|
} |
|
return vertices; |
|
} |
|
|
|
/// <summary> |
|
/// 从点集合中提取顶点信息 |
|
/// </summary> |
|
private static void ExtractVerticesFromCollection(IPointCollection source, ICollection<IPoint> destination) |
|
{ |
|
if (source == null || destination == null) return; |
|
|
|
for (int i = 0; i < source.PointCount; i++) |
|
{ |
|
var point = source.get_Point(i); |
|
if (point != null) destination.Add(point); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 计算两点间的平方平面距离(优化性能) |
|
/// </summary> |
|
private static double CalculateSquaredDistance(IPoint a, IPoint b) |
|
{ |
|
if (a == null || b == null) return double.PositiveInfinity; |
|
var dx = a.X - b.X; |
|
var dy = a.Y - b.Y; |
|
return dx * dx + dy * dy; |
|
} |
|
|
|
/// <summary> |
|
/// 验证坐标是否具有显著差异(排除浮点误差) |
|
/// </summary> |
|
private static bool HasSignificantCoordinateDifference(IPoint a, IPoint b) |
|
{ |
|
return Math.Abs(a.X - b.X) > COORDINATE_TOLERANCE || |
|
Math.Abs(a.Y - b.Y) > COORDINATE_TOLERANCE; |
|
} |
|
} |
|
} |