using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ESRI.ArcGIS.Geometry;
using KGIS.Framework.AE;
namespace Kingo.PluginServiceInterface.Helper
{
    /// 
    /// 尖锐角检查与处理逻辑
    /// 
    public class SharpAngle
    {
        /// 
        /// 处理几何图形中的尖锐角(小于指定角度阈值)
        /// 
        /// 
        /// 
        /// 默认小于10度为尖锐角
        /// 
        public static IGeometry ProcessSharpAngles(IGeometry geometry, double distance, double angleThreshold = 10, int recursionCount = 0)
        {
            // 预处理:移除几何图形中的重复顶点,确保顶点唯一性
            //geometry = RemoveDuplicatePoints(geometry);
            // 存储构成最小角度顶点集合的列表(通常包含三个顶点:构成尖角的三个点)
            List pointList = new List();
            double angle = 0;
            // 获取当前几何图形中的最小内角,并获取对应的三个顶点(尖角顶点及其相邻顶点)
            double internalAngle = GetMinAngle1(geometry, ref pointList);
            // 仅当找到有效三角形顶点时处理(三点构成一个尖角)
            if (pointList.Count == 3)
            {
                // 获取构成尖角的三个顶点
                // a - 前驱顶点,b - 尖角顶点,c - 后继顶点
                IPoint a = pointList[0];
                IPoint b = pointList[1];
                IPoint c = pointList[2];
                IPolygon triangle = CreateTriangle(a, b, c);
                if (triangle != null)
                {
                    var area = triangle as IArea;
                    if (area != null && area.Area < 0.1)
                    {
                        if (!FeatureAPI.IsInterSect(triangle, geometry))
                        {
                            geometry = FeatureAPI.Union(geometry, triangle);
                        }
                        else
                        {
                            // 从原始几何体中减去三角形区域,实现尖角切割
                            geometry = FeatureAPI.Difference(geometry, triangle);
                        }
                    }
                    else
                    {
                        // 在ab边上距离顶点b指定距离的位置生成新点d
                        IPoint d = GetPointAlongEdge(a, b, distance);
                        // 在cb边上距离顶点b指定距离的位置生成新点e
                        //IPoint e = GetPointAlongEdge(c, b, distance);
                        // 计算向量db的分量
                        double dbX = b.X - d.X;
                        double dbY = b.Y - d.Y;
                        // 计算分子和分母
                        double numerator = dbX * (b.X - d.X) + dbY * (b.Y - d.Y);
                        double denominator = dbX * (c.X - b.X) + dbY * (c.Y - b.Y);
                        // 避免分母为0(若分母为0,说明bc边与db向量平行,无法形成直角)
                        if (Math.Abs(denominator) < 1e-9)
                        {
                            // 处理边界:无法在bc边上找到e点,可返回原逻辑或抛出异常
                            return CreateTriangle(d, b, GetPointAlongEdge(c, b, distance)); // 原逻辑生成e点
                        }
                        double t = -numerator / denominator;
                        // 限制t在[0,1]范围内(确保e点在bc边上)
                        t = Math.Max(0, Math.Min(1, t));
                        // 生成e点(位于bc边上)
                        IPoint e = new PointClass()
                        {
                            X = b.X + t * (c.X - b.X),
                            Y = b.Y + t * (c.Y - b.Y)
                        };
                        // 用d-b-e三点创建三角形几何体(用于切割尖角区域)
                        triangle = CreateTriangle(d, b, e);
                        // 从原始几何体中减去三角形区域,实现尖角切割
                        //geometry = FeatureAPI.Difference(geometry, triangle);
                        if (triangle != null)
                        {
                            if (!FeatureAPI.IsInterSect(triangle, geometry))
                            {
                                geometry = FeatureAPI.Union(geometry, triangle);
                            }
                            else
                            {
                                // 从原始几何体中减去三角形区域,实现尖角切割
                                geometry = FeatureAPI.Difference(geometry, triangle);
                            }
                        }
                    }
                }
                // 检测处理后的几何体是否仍存在需要处理的尖角
                if (JudgmentSharpAngle(geometry, ref pointList, ref angle))
                {
                    if (recursionCount < 10)
                    {
                        // 递归调用时,计数器加1
                        geometry = ProcessSharpAngles(geometry, distance, angleThreshold, recursionCount + 1);
                    }
                    else
                    {
                        triangle = CreateTriangle(a, b, c);
                        if (!FeatureAPI.IsInterSect(triangle, geometry))
                        {
                            geometry = FeatureAPI.Union(geometry, triangle);
                        }
                        else
                        {
                            // 从原始几何体中减去三角形区域,实现尖角切割
                            geometry = FeatureAPI.Difference(geometry, triangle);
                        }
                    }
                }
            }
            // 返回处理后的几何体
            return geometry;
        }
        private static double GetMinAngle(IGeometry pGeo, ref List pointlist)
        {
            double result = -1;
            IPolygon4 poly4 = null;
            ITopologicalOperator topo = null;
            GeometryBag geoBag = null;
            IGeometryCollection geoCollection = null;
            pointlist = new List();
            try
            {
                if (pGeo == null || pGeo.IsEmpty)
                    return result;
                poly4 = pGeo as IPolygon4;
                topo = poly4 as ITopologicalOperator;
                topo?.Simplify();
                geoBag = poly4.ExteriorRingBag as GeometryBag;
                if (geoBag == null) return result;
                geoCollection = geoBag as IGeometryCollection;
                List rings = new List();
                for (int j = 0; j < geoCollection.GeometryCount; j++)
                {
                    IGeometry geo = geoCollection.get_Geometry(j);
                    rings.Add(geo);
                    //内环图形
                    IGeometryBag InteriorBag = (pGeo as IPolygon4).get_InteriorRingBag(geo as IRing);
                    if (InteriorBag != null)
                    {
                        IGeometryCollection InteriorRingGeometryCollection = InteriorBag as IGeometryCollection;
                        for (int IR = 0; IR < InteriorRingGeometryCollection.GeometryCount; IR++)
                        {
                            rings.Add(InteriorRingGeometryCollection.get_Geometry(IR));
                        }
                    }
                }
                foreach (IGeometry ring in rings)
                {
                    if (ring.IsEmpty) continue;
                    IPointCollection points = ring as IPointCollection;
                    int num = points.PointCount - 1;
                    for (int i = 0; i < num; i++)
                    {
                        IPoint p1 = null;
                        IPoint p2 = points.get_Point(i);
                        IPoint p3 = null;
                        if (i == 0)
                        {
                            p1 = points.get_Point(num - 1);
                            p3 = points.get_Point(i + 1);
                        }
                        else if (i == num - 1)
                        {
                            p1 = points.get_Point(i - 1);
                            p3 = points.get_Point(0);
                        }
                        else
                        {
                            p1 = points.get_Point(i - 1);
                            p3 = points.get_Point(i + 1);
                        }
                        if ((p2.X == p1.X && p2.Y == p1.Y) || (p2.X == p3.X && p2.Y == p3.Y) || (p1.X == p3.X && p1.Y == p3.Y))
                            continue;
                        double angle = GetAngle(p2, p1, p3);
                        if (double.IsNaN(angle)) continue;
                        if (result == -1)
                        {
                            result = angle;
                            pointlist.Add(p1);
                            pointlist.Add(p2);
                            pointlist.Add(p3);
                        }
                        else
                        {
                            if (double.IsNaN(result))
                            {
                                result = angle;
                            }
                            if (result > angle)
                            {
                                result = angle;
                                if (pointlist.Count > 0) pointlist.Clear();
                                pointlist.Add(p1);
                                pointlist.Add(p2);
                                pointlist.Add(p3);
                            }
                        }
                        //Marshal.ReleaseComObject(p1);
                        //Marshal.ReleaseComObject(p2);
                        //Marshal.ReleaseComObject(p3);
                    }
                    //Marshal.ReleaseComObject(ring);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                //if (poly4 != null)
                //    Marshal.ReleaseComObject(poly4);
                //if (topo != null)
                //    Marshal.ReleaseComObject(topo);
                //if (geoBag != null)
                //    Marshal.ReleaseComObject(geoBag);
                //if (geoCollection != null)
                //    Marshal.ReleaseComObject(geoCollection);
            }
            return result;
        }
        private static double GetAngle(IPoint cenPoint, IPoint firstPoint, IPoint secondPoint)
        {
            double ma_x = firstPoint.X - cenPoint.X;
            double ma_y = firstPoint.Y - cenPoint.Y;
            double mb_x = secondPoint.X - cenPoint.X;
            double mb_y = secondPoint.Y - cenPoint.Y;
            double v1 = (ma_x * mb_x) + (ma_y * mb_y);
            double ma_val = Math.Sqrt(ma_x * ma_x + ma_y * ma_y);
            double mb_val = Math.Sqrt(mb_x * mb_x + mb_y * mb_y);
            if (ma_val * mb_val == 0)
            {
                return -1;
            }
            double cosM = v1 / (ma_val * mb_val);
            double angleAMB = Math.Acos(cosM) * 180 / Math.PI;
            return angleAMB;
        }
        private static IGeometry RemoveDuplicatePoints(IGeometry geometry)
        {
            IPointCollection srcPoints = geometry as IPointCollection;
            IPointCollection dstPoints = new PolygonClass();
            IPoint lastPoint = null;
            for (int i = 0; i < srcPoints.PointCount; i++)
            {
                IPoint current = srcPoints.get_Point(i);
                if (lastPoint == null || !PointsEqual(current, lastPoint))
                {
                    dstPoints.AddPoint(current);
                    lastPoint = current;
                }
            }
            // 处理闭合环特殊情况
            if (dstPoints.PointCount > 1 &&
                PointsEqual(dstPoints.get_Point(0), dstPoints.get_Point(dstPoints.PointCount - 1)))
            {
                dstPoints.RemovePoints(dstPoints.PointCount - 1, 1);
            }
            return dstPoints as IPolygon;
        }
        private static bool PointsEqual(IPoint p1, IPoint p2)
        {
            const double tolerance = 1e-6;
            return Math.Abs(p1.X - p2.X) < tolerance &&
                   Math.Abs(p1.Y - p2.Y) < tolerance;
        }
        /// 
        /// 沿多边形边计算距离终点指定长度的点坐标
        /// 
        /// 边的起点坐标
        /// 边的终点坐标
        /// 从终点向起点方向移动的距离(非负数)
        /// 计算得到的新坐标点
        /// 当距离参数为负数时抛出
        private static IPoint GetPointAlongEdge(IPoint fromPoint, IPoint toPoint, double distanceFromEnd)
        {
            // 参数有效性验证
            if (distanceFromEnd < 0)
                throw new ArgumentException("移动距离必须为非负值", nameof(distanceFromEnd));
            const double precisionEpsilon = 1e-9; // 浮点计算精度阈值
            // 计算边向量分量
            double deltaX = toPoint.X - fromPoint.X;
            double deltaY = toPoint.Y - fromPoint.Y;
            // 计算边长的平方(避免开根号提升性能)
            double squaredEdgeLength = deltaX * deltaX + deltaY * deltaY;
            /* 处理特殊边界情况:
             * 1. 起点终点重合(边长接近0)
             * 2. 移动距离接近0
             * 以上情况直接返回终点坐标
             */
            if (squaredEdgeLength < precisionEpsilon * precisionEpsilon
                || distanceFromEnd < precisionEpsilon)
            {
                return ClonePoint(toPoint);
            }
            // 计算实际边长和标准化比例
            double edgeLength = Math.Sqrt(squaredEdgeLength);
            double normalizedRatio = distanceFromEnd / edgeLength;
            // 当移动距离超过边长时返回起点
            if (normalizedRatio >= 1.0)
            {
                return ClonePoint(fromPoint);
            }
            /* 坐标计算逻辑:
             * 从终点(toPoint)向起点(fromPoint)方向移动指定距离
             * 新坐标 = 终点坐标 - 边向量 * 距离比例
             */
            return CreateNewPoint(
                x: toPoint.X - deltaX * normalizedRatio,
                y: toPoint.Y - deltaY * normalizedRatio
            );
        }
        /// 
        /// 创建新点对象(封装对象创建逻辑)
        /// 
        private static IPoint CreateNewPoint(double x, double y)
            => new PointClass() { X = x, Y = y };
        /// 
        /// 复制点对象(避免引用关联)
        /// 
        private static IPoint ClonePoint(IPoint original)
            => CreateNewPoint(original.X, original.Y);
        private static IPolygon CreateTriangle(IPoint d, IPoint b, IPoint e)
        {
            IPolygon triangle = new PolygonClass();
            IPointCollection trianglePoints = triangle as IPointCollection;
            trianglePoints.AddPoint(d);
            trianglePoints.AddPoint(b);
            trianglePoints.AddPoint(e);
            trianglePoints.AddPoint(d); // 闭合多边形
            // 确保几何有效
            ITopologicalOperator topo = triangle as ITopologicalOperator;
            topo.Simplify();
            return triangle;
        }
        #region 判断尖锐角与修复尖锐角
        public static bool JudgmentSharpAngle(IGeometry geometry, ref List pointList, ref double angle)
        {
            bool isSharpAngle = false;
            try
            {
                if (geometry == null) return isSharpAngle;
                angle = GetMinAngle1(geometry, ref pointList, false);
                if (angle < 10) isSharpAngle = true;
            }
            catch (Exception) { }
            return isSharpAngle;
        }
        #endregion
        public static double GetMinAngle1(IGeometry pGeo, ref List pointlist)
        {
            const double NoAngleFound = double.MaxValue;
            double minAngle = NoAngleFound;
            pointlist = new List();
            if (pGeo == null || pGeo.IsEmpty)
                return -1;
            if (!(pGeo is IPolygon4 poly4))
                return -1;
            // 简化几何拓扑
            (poly4 as ITopologicalOperator)?.Simplify();
            // 收集所有环(外环 + 内环)
            var rings = new List();
            IGeometryCollection exteriorRings = poly4.ExteriorRingBag as IGeometryCollection;
            if (exteriorRings != null)
            {
                for (int i = 0; i < exteriorRings.GeometryCount; i++)
                {
                    if (exteriorRings.get_Geometry(i) is IRing ring)
                    {
                        rings.Add(ring);
                        // 获取当前外环的内环
                        IGeometryBag interiorBag = poly4.get_InteriorRingBag(ring);
                        if (interiorBag != null)
                        {
                            IGeometryCollection interiorRings = interiorBag as IGeometryCollection;
                            for (int j = 0; j < interiorRings.GeometryCount; j++)
                            {
                                if (interiorRings.get_Geometry(j) is IRing interiorRing)
                                {
                                    rings.Add(interiorRing);
                                }
                            }
                        }
                    }
                }
            }
            // 存储所有环的点集合(每个环单独存储)
            var ringPoints = new List>();
            // 提前提取所有环的点坐标
            foreach (IRing ring in rings)
            {
                if (ring.IsEmpty) continue;
                IPointCollection pColl = ring as IPointCollection;
                int totalPoints = pColl.PointCount;
                // 检查是否闭合(首尾点相同)
                bool isClosed = totalPoints > 0 && PointEqual(pColl.get_Point(0), pColl.get_Point(totalPoints - 1));
                // 提取点坐标(如果是闭合环则忽略最后一个点)
                var points = new List();
                int pointsToTake = isClosed ? totalPoints - 1 : totalPoints;
                for (int i = 0; i < pointsToTake; i++)
                {
                    points.Add(pColl.get_Point(i));
                }
                ringPoints.Add(points);
            }
            // 使用线程安全的集合存储结果
            var minAngles = new ConcurrentBag<(double angle, IPoint p1, IPoint p2, IPoint p3)>();
            // 并行处理每个环
            Parallel.ForEach(ringPoints, (points) =>
            {
                int count = points.Count;
                // 单环内并行处理每个点组合
                Parallel.For(0, count, (i) =>
                {
                    int prevIdx = (i - 1 + count) % count;
                    int nextIdx = (i + 1) % count;
                    IPoint p1 = points[prevIdx];
                    IPoint p2 = points[i];
                    IPoint p3 = points[nextIdx];
                    if (PointEqual(p1, p2) || PointEqual(p2, p3) || PointEqual(p1, p3))
                        return;
                    double angle = GetAngle(p2, p1, p3);
                    if (double.IsNaN(angle))
                        return;
                    // 添加到线程安全集合
                    minAngles.Add((angle, p1, p2, p3));
                });
            });
            // 在所有结果中找到最小角度
            foreach (var item in minAngles)
            {
                if (item.angle < minAngle)
                {
                    minAngle = item.angle;
                    pointlist.Clear();
                    pointlist.Add(item.p1);
                    pointlist.Add(item.p2);
                    pointlist.Add(item.p3);
                }
            }
            return minAngle == NoAngleFound ? -1 : minAngle;
        }
        // 辅助方法:判断两点是否重合
        private static bool PointEqual(IPoint a, IPoint b)
            => a.X == b.X && a.Y == b.Y;
        #region MyRegion
        public struct PointD
        {
            public double X { get; }
            public double Y { get; }
            public PointD(double x, double y)
            {
                X = x;
                Y = y;
            }
        }
        // 优化后的最小角度计算方法(针对大型图形)
        public static double GetMinAngle1(IGeometry pGeo, ref List pointlist, bool skipSimplify = false)
        {
            const double NoAngleFound = double.MaxValue;
            double minAngle = NoAngleFound;
            pointlist = new List();
            // 1. 输入校验(提前返回)
            if (pGeo == null || pGeo.IsEmpty)
                return -1;
            if (!(pGeo is IPolygon4 poly4))
                return -1;
            // 2. 拓扑简化(可选跳过,适用于外部已简化的几何)
            if (!skipSimplify)
            {
                (poly4 as ITopologicalOperator)?.Simplify(); // 仅执行一次简化
            }
            // 3. 提取所有环(外环 + 内环)并转换为值类型点集合(减少 COM 交互)
            var allRingsPoints = ExtractRingsAsPointD(poly4);
            if (allRingsPoints.Count == 0)
                return -1;
            // 4. 并行/串行处理每个环(根据环大小动态选择)
            var minAngles = new ConcurrentBag<(double angle, PointD p1, PointD p2, PointD p3)>();
            foreach (var ringPoints in allRingsPoints)
            {
                int pointCount = ringPoints.Count;
                if (pointCount < 3) continue; // 环至少需要3个点才能构成角
                // 动态选择处理方式:点数量大时并行,否则串行(避免小任务并行开销)
                if (pointCount > 1000) // 阈值可根据实际场景调整
                {
                    Parallel.For(0, pointCount, i => ProcessPointInRing(ringPoints, i, minAngles));
                }
                else
                {
                    for (int i = 0; i < pointCount; i++)
                    {
                        ProcessPointInRing(ringPoints, i, minAngles);
                    }
                }
            }
            // 5. 查找全局最小角度(并转换回 IPoint)
            foreach (var item in minAngles)
            {
                if (item.angle < minAngle)
                {
                    minAngle = item.angle;
                    pointlist.Clear();
                    // 将值类型点转换为 IPoint(仅最后需要时创建 COM 对象)
                    pointlist.Add(CreateIPoint(item.p1.X, item.p1.Y));
                    pointlist.Add(CreateIPoint(item.p2.X, item.p2.Y));
                    pointlist.Add(CreateIPoint(item.p3.X, item.p3.Y));
                }
                // 优化:若已找到小于10度的角,可提前终止(适用于仅需判断尖锐角的场景)
                if (minAngle < 10) break;
            }
            return minAngle == NoAngleFound ? -1 : minAngle;
        }
        // 辅助方法:提取所有环的点坐标(转换为值类型 PointD)
        private static List> ExtractRingsAsPointD(IPolygon4 poly4)
        {
            var allRingsPoints = new List>();
            // 提取外环
            IGeometryCollection exteriorRings = poly4.ExteriorRingBag as IGeometryCollection;
            if (exteriorRings != null)
            {
                for (int i = 0; i < exteriorRings.GeometryCount; i++)
                {
                    if (exteriorRings.get_Geometry(i) is IRing ring)
                    {
                        var ringPoints = ExtractRingPointsAsPointD(ring);
                        allRingsPoints.Add(ringPoints);
                        // 提取当前外环的内环
                        IGeometryBag interiorBag = poly4.get_InteriorRingBag(ring);
                        if (interiorBag != null)
                        {
                            IGeometryCollection interiorRings = interiorBag as IGeometryCollection;
                            for (int j = 0; j < interiorRings.GeometryCount; j++)
                            {
                                if (interiorRings.get_Geometry(j) is IRing interiorRing)
                                {
                                    var interiorRingPoints = ExtractRingPointsAsPointD(interiorRing);
                                    allRingsPoints.Add(interiorRingPoints);
                                }
                            }
                        }
                    }
                }
            }
            return allRingsPoints;
        }
        // 辅助方法:提取单个环的点坐标(转换为 PointD)
        private static List ExtractRingPointsAsPointD(IRing ring)
        {
            var points = new List();
            if (ring.IsEmpty) return points;
            IPointCollection pColl = ring as IPointCollection;
            int totalPoints = pColl.PointCount;
            bool isClosed = totalPoints > 0 && PointEqual2(pColl.get_Point(0), pColl.get_Point(totalPoints - 1));
            int pointsToTake = isClosed ? totalPoints - 1 : totalPoints;
            // 仅遍历一次 COM 对象,转换为值类型存储
            for (int i = 0; i < pointsToTake; i++)
            {
                IPoint comPoint = pColl.get_Point(i);
                points.Add(new PointD(comPoint.X, comPoint.Y));
            }
            return points;
        }
        // 辅助方法:处理环中的单个点(计算角度)
        private static void ProcessPointInRing(List ringPoints, int i, ConcurrentBag<(double angle, PointD p1, PointD p2, PointD p3)> minAngles)
        {
            int count = ringPoints.Count;
            int prevIdx = (i - 1 + count) % count;
            int nextIdx = (i + 1) % count;
            PointD p1 = ringPoints[prevIdx];
            PointD p2 = ringPoints[i];
            PointD p3 = ringPoints[nextIdx];
            // 跳过重合点(提前判断,减少无效计算)
            if (PointEqual(p1, p2) || PointEqual(p2, p3) || PointEqual(p1, p3))
                return;
            // 计算角度(预计算向量差值和模长,避免重复计算)
            double maX = p1.X - p2.X;
            double maY = p1.Y - p2.Y;
            double mbX = p3.X - p2.X;
            double mbY = p3.Y - p2.Y;
            double dotProduct = maX * mbX + maY * mbY;
            double maLength = Math.Sqrt(maX * maX + maY * maY);
            double mbLength = Math.Sqrt(mbX * mbX + mbY * mbY);
            if (maLength < 1e-9 || mbLength < 1e-9) // 避免除零错误
                return;
            double cosTheta = dotProduct / (maLength * mbLength);
            cosTheta = Math.Max(Math.Min(cosTheta, 1), -1); // 防止浮点误差导致超出 [-1,1]
            double angle = Math.Acos(cosTheta) * 180 / Math.PI;
            minAngles.Add((angle, p1, p2, p3));
        }
        // 辅助方法:判断两个 PointD 是否重合(值类型比较更快)
        private static bool PointEqual(PointD a, PointD b)
            => Math.Abs(a.X - b.X) < 1e-6 && Math.Abs(a.Y - b.Y) < 1e-6;
        // 辅助方法:将值类型点转换为 IPoint(仅最后需要时创建)
        private static IPoint CreateIPoint(double x, double y)
            => new PointClass { X = x, Y = y };
        // 辅助方法:兼容原 COM 对象的点比较(仅用于初始环提取)
        private static bool PointEqual2(IPoint a, IPoint b)
            => Math.Abs(a.X - b.X) < 1e-6 && Math.Abs(a.Y - b.Y) < 1e-6;
        #endregion
    }
    // 自定义值类型:存储坐标(替代IPoint引用类型,减少GC)
    public struct PointD : IEquatable
    {
        public double X { get; }
        public double Y { get; }
        public PointD(double x, double y)
        {
            X = x;
            Y = y;
        }
        public bool Equals(PointD other)
        {
            return X.Equals(other.X) && Y.Equals(other.Y);
        }
        public override bool Equals(object obj)
        {
            return obj is PointD other && Equals(other);
        }
        public override int GetHashCode()
        {
            return 0; //HashCode.Combine(X, Y);
        }
        public static bool operator ==(PointD left, PointD right)
        {
            return left.Equals(right);
        }
        public static bool operator !=(PointD left, PointD right)
        {
            return !left.Equals(right);
        }
    }
    public static class GeometryOptimizer
    {
        // 线程安全的最小值容器(存储角度及对应三点)
        private class ThreadSafeMinAngle
        {
            private double _minAngle = double.MaxValue;
            private PointD _p1, _p2, _p3;
            private readonly object _lock = new object();
            public void Update(double angle, PointD p1, PointD p2, PointD p3)
            {
                lock (_lock)
                {
                    if (angle < _minAngle)
                    {
                        _minAngle = angle;
                        _p1 = p1;
                        _p2 = p2;
                        _p3 = p3;
                    }
                }
            }
            public (double angle, PointD p1, PointD p2, PointD p3) GetResult()
            {
                lock (_lock)
                {
                    return (_minAngle == double.MaxValue ? -1 : _minAngle, _p1, _p2, _p3);
                }
            }
        }
        public static double GetMinAngle1(IGeometry pGeo, ref List pointlist)
        {
            // 初始化返回值和常量
            const double NoAngleFound = double.MaxValue;
            pointlist = new List();
            // 输入参数校验
            if (pGeo == null || pGeo.IsEmpty || !(pGeo is IPolygon4 poly4))
                return -1;
            // 简化几何拓扑(修复自相交、冗余顶点等)
            (poly4 as ITopologicalOperator)?.Simplify();
            // 收集所有环的顶点(直接提取,不暂存环对象)
            var ringPoints = new List>();
            CollectRingPoints(poly4, ringPoints);
            // 过滤无效环(顶点数 < 3 的环无法构成角度)
            var validRingPoints = ringPoints.Where(points => points.Count >= 3).ToList();
            if (!validRingPoints.Any())
                return -1;
            // 并行计算角度并实时跟踪最小值
            var minAngleContainer = new ThreadSafeMinAngle();
            Parallel.ForEach(validRingPoints, points =>
            {
                int count = points.Count;
                for (int i = 0; i < count; i++)
                {
                    // 获取当前点及相邻点(循环索引)
                    int prevIdx = (i - 1 + count) % count;
                    int nextIdx = (i + 1) % count;
                    PointD pPrev = points[prevIdx];
                    PointD pCurr = points[i];
                    PointD pNext = points[nextIdx];
                    // 跳过重复点(避免计算无效角度)
                    if (pPrev == pCurr || pCurr == pNext || pPrev == pNext)
                        continue;
                    // 计算角度(使用值类型坐标提升效率)
                    double angle = CalculateAngle(pCurr, pPrev, pNext);
                    if (!double.IsNaN(angle))
                        minAngleContainer.Update(angle, pPrev, pCurr, pNext);
                }
            });
            // 处理最终结果
            var result = minAngleContainer.GetResult();
            if (result.angle <= 0)
                return -1;
            // 转换值类型坐标为IPoint并返回
            pointlist.Add(CreateIPoint(result.p1));
            pointlist.Add(CreateIPoint(result.p2));
            pointlist.Add(CreateIPoint(result.p3));
            return result.angle;
        }
        // 辅助方法:收集多边形所有环的顶点(外环+内环)
        private static void CollectRingPoints(IPolygon4 poly4, List> ringPoints)
        {
            // 处理外环
            if (poly4.ExteriorRingBag is IGeometryCollection exteriorRings)
            {
                for (int i = 0; i < exteriorRings.GeometryCount; i++)
                {
                    if (exteriorRings.get_Geometry(i) is IRing exteriorRing)
                    {
                        AddRingPointsToCollection(exteriorRing, ringPoints);
                        // 处理当前外环的内环
                        if (poly4.get_InteriorRingBag(exteriorRing) is IGeometryCollection interiorRings)
                        {
                            for (int j = 0; j < interiorRings.GeometryCount; j++)
                            {
                                if (interiorRings.get_Geometry(j) is IRing interiorRing)
                                    AddRingPointsToCollection(interiorRing, ringPoints);
                            }
                        }
                    }
                }
            }
        }
        // 辅助方法:提取单个环的顶点并添加到集合
        private static void AddRingPointsToCollection(IRing ring, List> ringPoints)
        {
            if (ring.IsEmpty || !(ring is IPointCollection pointColl))
                return;
            // 提取顶点(闭合环忽略最后一个点,避免重复)
            int totalPoints = pointColl.PointCount;
            bool isClosed = totalPoints > 0 && PointEqual(pointColl.get_Point(0), pointColl.get_Point(totalPoints - 1));
            int pointsToTake = isClosed ? totalPoints - 1 : totalPoints;
            var points = new List();
            for (int i = 0; i < pointsToTake; i++)
            {
                IPoint p = pointColl.get_Point(i);
                points.Add(new PointD(p.X, p.Y)); // 转换为值类型坐标
            }
            ringPoints.Add(points);
        }
        // 辅助方法:计算三点构成的夹角(pCurr为顶点)
        private static double CalculateAngle(PointD pCurr, PointD pPrev, PointD pNext)
        {
            // 构建向量:pCurr->pPrev 和 pCurr->pNext
            double v1X = pPrev.X - pCurr.X;
            double v1Y = pPrev.Y - pCurr.Y;
            double v2X = pNext.X - pCurr.X;
            double v2Y = pNext.Y - pCurr.Y;
            // 向量模长(避免除以零)
            double len1 = Math.Sqrt(v1X * v1X + v1Y * v1Y);
            double len2 = Math.Sqrt(v2X * v2X + v2Y * v2Y);
            if (len1 < 1e-9 || len2 < 1e-9)
                return double.NaN;
            // 向量点积计算夹角(弧度转角度)
            double dotProduct = v1X * v2X + v1Y * v2Y;
            double cosTheta = Math.Max(-1, Math.Min(1, dotProduct / (len1 * len2))); // 修正精度误差
            return Math.Acos(cosTheta) * (180 / Math.PI);
        }
        // 辅助方法:比较两个IPoint是否相等(坐标精度:1e-6)
        private static bool PointEqual(IPoint p1, IPoint p2)
        {
            return Math.Abs(p1.X - p2.X) < 1e-6 && Math.Abs(p1.Y - p2.Y) < 1e-6;
        }
        // 辅助方法:将PointD转换为IPoint(假设IPoint可实例化)
        private static IPoint CreateIPoint(PointD point)
        {
            var iPoint = new PointClass();
            iPoint.X = point.X;
            iPoint.Y = point.Y;
            return iPoint;
        }
    }
}