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.
104 lines
4.5 KiB
104 lines
4.5 KiB
using System; |
|
using System.Collections.Generic; |
|
using ESRI.ArcGIS.Geodatabase; |
|
using ESRI.ArcGIS.Geometry; |
|
using KGIS.Framework.AE.ExtensionMethod; |
|
using KGIS.Framework.AE; |
|
|
|
namespace Kingo.PluginServiceInterface.Helper |
|
{ |
|
public class PolygonNarrowCheck |
|
{ |
|
public static bool CheckNarrowArea1(IGeometry geometry) |
|
{ |
|
bool isSharpAngle = false; |
|
try |
|
{ |
|
if (geometry == null || geometry.IsEmpty) return isSharpAngle; |
|
ITopologicalOperator topo = geometry as ITopologicalOperator; |
|
IPolyline line1 = topo.Boundary as IPolyline; |
|
double length1 = line1.Length; |
|
int pointCount1 = (geometry as IPointCollection).PointCount; |
|
IGeometry geo = topo.Buffer(-0.05); |
|
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)) |
|
return true; |
|
} |
|
catch (Exception) |
|
{ |
|
|
|
} |
|
finally |
|
{ |
|
//GC.Collect(); |
|
} |
|
return isSharpAngle; |
|
} |
|
|
|
// 经验阈值判断(8倍安全系数) |
|
const double safetyFactor = 8.0; |
|
const double bufferDistance = -0.05; // 单位取决于空间参考 |
|
public static bool CheckNarrowArea(IGeometry geometry) |
|
{ |
|
// 返回值表示是否检测到狭窄区域,默认为false |
|
bool isNarrowAreaDetected = false; |
|
try |
|
{ |
|
// 输入校验:确保几何体非空且有效 |
|
if (geometry == null || geometry.IsEmpty) |
|
return isNarrowAreaDetected; |
|
// 类型检查:确保支持拓扑操作 |
|
if (!(geometry is ITopologicalOperator topoOperator)) |
|
return isNarrowAreaDetected; |
|
// 获取原始边界并验证类型 |
|
var originalBoundary = topoOperator.Boundary as IPolyline; |
|
if (originalBoundary == null) |
|
return isNarrowAreaDetected; |
|
// 计算原始几何参数 |
|
double originalLength = originalBoundary.Length; |
|
int vertexCount = (geometry as IPointCollection)?.PointCount ?? 0; |
|
// 顶点数不足3时无法构成有效多边形 |
|
if (vertexCount < 3) |
|
return isNarrowAreaDetected; |
|
// 执行负缓冲操作(缩小几何体) |
|
IGeometry bufferedGeometry = topoOperator.Buffer(bufferDistance); |
|
// 检查缓冲后几何有效性 |
|
if (bufferedGeometry?.IsEmpty != false) |
|
return isNarrowAreaDetected; |
|
// 获取缓冲后边界并验证类型 |
|
if (!(bufferedGeometry is ITopologicalOperator bufferedTopo)) |
|
return isNarrowAreaDetected; |
|
var bufferedBoundary = bufferedTopo.Boundary as IPolyline; |
|
if (bufferedBoundary == null) |
|
return isNarrowAreaDetected; |
|
// 计算缓冲后长度差异 |
|
double deltaLength = originalLength - bufferedBoundary.Length; |
|
// 计算平均内角半角(几何修正) |
|
double avgHalfAngle = 90.0 * (vertexCount - 2) / vertexCount; |
|
|
|
// 角度接近直角时跳过计算(避免tan(90°)) |
|
if (avgHalfAngle >= 89.999) |
|
return isNarrowAreaDetected; |
|
// 计算拐角缩短长度 |
|
double tanValue = Math.Tan(avgHalfAngle * Math.PI / 180.0); |
|
double cornerReduction = 2 * Math.Abs(bufferDistance) / tanValue; |
|
// 计算总预期缩短长度 |
|
double totalExpectedReduction = cornerReduction * vertexCount; |
|
isNarrowAreaDetected = deltaLength > safetyFactor * totalExpectedReduction; |
|
} |
|
catch (Exception ex) |
|
{ |
|
// 异常处理(建议记录日志) |
|
// Debug.WriteLine($"几何检测异常: {ex.Message}"); |
|
return false; |
|
} |
|
|
|
return isNarrowAreaDetected; |
|
} |
|
} |
|
}
|
|
|