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

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;
}
}
}