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