using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Autodesk.Navisworks.Api;
using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;

namespace NavisworksTransport
{
    /// <summary>
    /// 几何提取器
    /// </summary>
    public class GeometryHelper
    {
        /// <summary>
        /// 默认轮廓提取容差（米）
        /// </summary>
        private const double DEFAULT_OUTLINE_TOLERANCE_METERS = 0.5;

        /// <summary>
        /// 1厘米容差（米）- 用于精确几何计算
        /// </summary>
        private const double TOLERANCE_1CM_METERS = 0.01;

        /// <summary>
        /// 提取模型项的顶视图轮廓
        /// </summary>
        /// <param name="modelItem">模型项</param>
        /// <param name="tolerance">容差</param>
        /// <returns>轮廓点集合</returns>
        public static List<Point3D> ExtractTopViewOutline(ModelItem modelItem, double tolerance = DEFAULT_OUTLINE_TOLERANCE_METERS)
        {
            var points = new List<Point3D>();

            try
            {
                LogManager.Debug($"开始提取模型 {modelItem.DisplayName} 的几何数据");
                LogManager.Debug($"模型项类型: {modelItem.GetType().Name}");
                LogManager.Debug($"模型项GUID: {modelItem.InstanceGuid}");

                // 详细检查模型是否有几何数据
                bool hasGeometry = modelItem.HasGeometry;
                LogManager.Debug($"[关键检查] ModelItem.HasGeometry = {hasGeometry}");

                if (!hasGeometry)
                {
                    LogManager.Debug("[关键发现] 模型项没有几何数据 - HasGeometry 返回 false");
                    LogManager.Debug($"模型项详细信息:");
                    LogManager.Debug($"  - 显示名称: {modelItem.DisplayName}");
                    LogManager.Debug($"  - 实例GUID: {modelItem.InstanceGuid}");

                    // 检查子项数量来判断是否为叶节点
                    int childrenCount = modelItem.Children.Count();
                    LogManager.Debug($"  - 子项数量: {childrenCount}");
                    LogManager.Debug($"  - 是否为叶节点: {childrenCount == 0}");

                    // 尝试检查包围盒
                    try
                    {
                        var bbox = modelItem.BoundingBox();
                        if (bbox != null)
                        {
                            LogManager.Debug($"  - 包围盒存在: {bbox.Min} - {bbox.Max}");
                        }
                        else
                        {
                            LogManager.Debug($"  - 包围盒不存在");
                        }
                    }
                    catch (Exception bboxEx)
                    {
                        LogManager.Warning($"  - 获取包围盒失败: {bboxEx.Message}");
                    }

                    return points;
                }

                LogManager.Debug("[几何检查通过] 模型项有几何数据，继续处理");

                // 处理多实例问题 - 确保只获取当前实例的几何
                var targetItem = modelItem;
                int instanceCount = targetItem.Instances.Count();
                LogManager.Debug($"原始模型实例数: {instanceCount}");

                while (targetItem.Instances.Count() > 1)
                {
                    targetItem = targetItem.Parent;
                    if (targetItem == null) break;
                    LogManager.Debug($"向上查找父项: {targetItem?.DisplayName}, 实例数: {targetItem?.Instances.Count()}");
                }

                if (targetItem == null)
                {
                    LogManager.Warning("无法找到合适的几何节点");
                    return points;
                }

                // 再次检查目标项的几何状态
                bool targetHasGeometry = targetItem.HasGeometry;
                LogManager.Debug($"[目标项检查] 使用几何节点: {targetItem.DisplayName}");
                LogManager.Debug($"[目标项检查] 实例数: {targetItem.Instances.Count()}");
                LogManager.Debug($"[目标项检查] HasGeometry = {targetHasGeometry}");

                if (!targetHasGeometry)
                {
                    LogManager.Warning("[目标项问题] 目标节点也没有几何数据");
                    return points;
                }

                // 使用优化的几何提取方法
                var triangles = ExtractTriangles(new[] { targetItem });
                LogManager.Debug($"提取到 {triangles.Count} 个三角形");

                if (triangles.Count > 0)
                {
                    // 生成轮廓
                    points = GenerateOutlineFromTriangles(triangles, tolerance);
                    LogManager.Info($"生成轮廓包含 {points.Count} 个点");
                }
                else
                {
                    LogManager.Warning("未提取到三角形数据");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"提取几何数据失败: {ex.Message}");
                LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
            }

            return points;
        }

        /// <summary>
        /// 批量提取三角形（优化版本）
        /// </summary>
        /// <param name="modelItems">模型项集合</param>
        /// <returns>三角形集合</returns>
        public static List<Triangle3D> ExtractTriangles(IEnumerable<ModelItem> modelItems)
        {
            var triangles = new List<Triangle3D>();

            ComApi.InwOpSelection comSelection = null;
            Progress progress = null;
            try
            {
                // 批量转换为 COM 选择 - 性能优化关键
                var modelCollection = new ModelItemCollection();
                int itemCount = 0;
                foreach (var item in modelItems)
                {
                    modelCollection.Add(item);
                    itemCount++;
                }

                LogManager.Info($"[批量提取] 开始批量提取 {itemCount} 个模型项的三角形");

                var comState = ComStateManager.GetState();
                comSelection = ComApiBridge.ToInwOpSelection(modelCollection);

                LogManager.Debug($"[批量提取] COM 选择创建成功，路径数: {comSelection.Paths().Count}");

                // 获取所有片段
                var allFragments = GetAllFragments(comSelection);
                LogManager.Info($"[批量提取] 获取到 {allFragments.Count} 个片段");

                // 🎯 开始进度条
                progress = Application.BeginProgress("提取几何体",
                    $"正在提取 {allFragments.Count} 个片段的三角形数据...");

                try
                {
                    int processedFragments = 0;
                    foreach (var fragmentInfo in allFragments)
                    {
                        // 🎯 检查用户是否取消
                        if (progress.IsCanceled)
                        {
                            LogManager.Info($"[批量提取] 用户取消操作，已处理 {processedFragments}/{allFragments.Count}");
                            break;
                        }

                        try
                        {
                            var callback = new OptimizedGeometryCallback(fragmentInfo.TransformMatrix);
                            fragmentInfo.Fragment.GenerateSimplePrimitives(
                                ComApi.nwEVertexProperty.eNORMAL,
                                callback);

                            var fragmentTriangles = callback.GetTriangles();
                            triangles.AddRange(fragmentTriangles);
                            processedFragments++;

                            // 🎯 更新进度（每处理完一个片段更新一次）
                            progress.Update((double)processedFragments / allFragments.Count);
                        }
                        catch (Exception ex)
                        {
                            LogManager.Error($"[批量提取] 处理片段失败: {ex.Message}");
                        }
                    }

                    LogManager.Info($"[批量提取] 片段处理完成，共提取 {triangles.Count} 个三角形");
                }
                finally
                {
                    // 释放所有片段COM对象
                    foreach (var fragmentInfo in allFragments)
                    {
                        try
                        {
                            if (fragmentInfo.Fragment != null)
                            {
                                Marshal.ReleaseComObject(fragmentInfo.Fragment);
                            }
                        }
                        catch (Exception ex)
                        {
                            LogManager.Warning($"[批量提取] 释放片段COM对象失败: {ex.Message}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[批量提取] 提取三角形失败: {ex.Message}");
            }
            finally
            {
                // 🎯 确保进度条被关闭
                if (progress != null)
                {
                    Application.EndProgress();
                }

                // 释放COM对象，避免内存泄漏
                if (comSelection != null)
                {
                    Marshal.ReleaseComObject(comSelection);
                }
            }

            return triangles;
        }

        /// <summary>
        /// 获取所有片段
        /// </summary>
        /// <param name="selection">COM 选择</param>
        /// <returns>所有片段信息集合</returns>
        public static List<FragmentInfo> GetAllFragments(ComApi.InwOpSelection selection)
        {
            var fragmentList = new List<FragmentInfo>();
            int totalPathCount = 0;
            int totalFragmentCount = 0;

            try
            {
                foreach (ComApi.InwOaPath3 path in selection.Paths())
                {
                    totalPathCount++;
                    int fragmentsInPath = 0;

                    try
                    {
                        foreach (ComApi.InwOaFragment3 fragment in path.Fragments())
                        {
                            fragmentsInPath++;
                            totalFragmentCount++;

                            try
                            {
                                // 获取片段的路径信息（仅用于日志记录）
                                var pathArray = ((Array)fragment.path.ArrayData).ToArray<int>();
                                var pathKey = string.Join(",", pathArray);

                                // 获取变换矩阵
                                var transform = (ComApi.InwLTransform3f3)(object)fragment.GetLocalToWorldMatrix();

                                // 🔧 关键修复：预处理Transform矩阵并立即释放COM对象
                                double[] transformMatrix = null;
                                if (transform != null)
                                {
                                    try
                                    {
                                        // 提取矩阵数据到普通数组
                                        var matrixArray = (Array)(object)transform.Matrix;
                                        transformMatrix = matrixArray.ToArray<double>();
                                    }
                                    catch (Exception ex)
                                    {
                                        LogManager.Error($"提取Transform矩阵失败: {ex.Message}");
                                        transformMatrix = null;
                                    }
                                    finally
                                    {
                                        // 立即释放COM对象，避免内存泄露
                                        Marshal.ReleaseComObject(transform);
                                    }
                                }

                                // 使用实际的路径键而不是递增索引
                                fragmentList.Add(new FragmentInfo
                                {
                                    Fragment = fragment,
                                    TransformMatrix = transformMatrix,
                                    PathKey = pathKey  // 使用实际的路径键
                                });
                            }
                            catch (Exception ex)
                            {
                                LogManager.Error($"处理单个片段失败: {ex.Message}");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"遍历路径片段失败: {ex.Message}");
                    }
                    finally
                    {
                        // 释放路径COM对象
                        if (path != null)
                        {
                            Marshal.ReleaseComObject(path);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"获取所有片段失败: {ex.Message}");
            }

            return fragmentList;
        }

        /// <summary>
        /// 从三角形生成轮廓
        /// </summary>
        /// <param name="triangles">三角形集合</param>
        /// <param name="tolerance">容差</param>
        /// <returns>轮廓点集合</returns>
        private static List<Point3D> GenerateOutlineFromTriangles(List<Triangle3D> triangles, double tolerance)
        {
            var outlinePoints = new List<Point3D>();

            try
            {
                if (triangles.Count == 0) return outlinePoints;

                // 找到最高的 Z 坐标
                var maxZ = triangles.SelectMany(t => new[] { t.Point1.Z, t.Point2.Z, t.Point3.Z }).Max();

                // 筛选顶部表面的三角形
                var topTriangles = triangles.Where(t =>
                    Math.Abs(t.Point1.Z - maxZ) < tolerance &&
                    Math.Abs(t.Point2.Z - maxZ) < tolerance &&
                    Math.Abs(t.Point3.Z - maxZ) < tolerance).ToList();

                LogManager.Debug($"顶部三角形数量: {topTriangles.Count}");

                if (topTriangles.Count == 0) return outlinePoints;

                // 提取所有边
                var edges = new List<Edge2D>();
                foreach (var triangle in topTriangles)
                {
                    edges.Add(new Edge2D(
                        new Point2D(triangle.Point1.X, triangle.Point1.Y),
                        new Point2D(triangle.Point2.X, triangle.Point2.Y)));
                    edges.Add(new Edge2D(
                        new Point2D(triangle.Point2.X, triangle.Point2.Y),
                        new Point2D(triangle.Point3.X, triangle.Point3.Y)));
                    edges.Add(new Edge2D(
                        new Point2D(triangle.Point3.X, triangle.Point3.Y),
                        new Point2D(triangle.Point1.X, triangle.Point1.Y)));
                }

                // 找到边界边（只出现一次的边）
                var boundaryEdges = FindBoundaryEdges(edges);
                LogManager.Debug($"边界边数量: {boundaryEdges.Count}");

                if (boundaryEdges.Count > 0)
                {
                    // 构建轮廓
                    var outlinePoints2D = BuildOutlineFromEdges(boundaryEdges);

                    // 转换为3D点（使用最高Z坐标）
                    outlinePoints = outlinePoints2D.Select(p => new Point3D(p.X, p.Y, maxZ)).ToList();
                    LogManager.Debug($"最终轮廓点数量: {outlinePoints.Count}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"生成轮廓失败: {ex.Message}");
            }

            return outlinePoints;
        }

        /// <summary>
        /// 查找边界边（在俯视图中只出现一次的边）
        /// </summary>
        /// <param name="edges">所有边的集合</param>
        /// <returns>边界边集合</returns>
        private static List<Edge2D> FindBoundaryEdges(List<Edge2D> edges)
        {
            var boundaryEdges = new List<Edge2D>();
            var edgeCount = new Dictionary<string, int>();
            var edgeMap = new Dictionary<string, Edge2D>();

            try
            {
                // 统计每条边出现的次数
                foreach (var edge in edges)
                {
                    var key = edge.GetKey();
                    var reverseKey = edge.GetReverseKey();

                    // 使用规范化的边键（总是用较小的端点作为起点）
                    var normalizedKey = string.Compare(key, reverseKey) < 0 ? key : reverseKey;
                    var normalizedEdge = string.Compare(key, reverseKey) < 0 ? edge : new Edge2D(edge.End, edge.Start);

                    if (edgeCount.ContainsKey(normalizedKey))
                    {
                        edgeCount[normalizedKey]++;
                    }
                    else
                    {
                        edgeCount[normalizedKey] = 1;
                        edgeMap[normalizedKey] = normalizedEdge;
                    }
                }

                LogManager.Debug($"边计数完成，唯一边数: {edgeCount.Count}");

                // 找出只出现一次的边（边界边）
                int boundaryCount = 0;
                int sharedCount = 0;

                foreach (var kvp in edgeCount)
                {
                    if (kvp.Value == 1)
                    {
                        boundaryEdges.Add(edgeMap[kvp.Key]);
                        boundaryCount++;
                    }
                    else
                    {
                        sharedCount++;
                    }
                }

                LogManager.Debug($"边界边分析完成:");
                LogManager.Debug($"  边界边数量: {boundaryCount}");
                LogManager.Debug($"  共享边数量: {sharedCount}");
                LogManager.Debug($"  边界/总边比例: {(double)boundaryCount / edges.Count:P1}");

                // 验证边界边的连通性
                if (boundaryEdges.Count > 0)
                {
                    var connectivity = AnalyzeBoundaryConnectivity(boundaryEdges);
                    LogManager.Debug($"边界边连通性分析: {connectivity}");
                }

            }
            catch (Exception ex)
            {
                LogManager.Error($"查找边界边失败: {ex.Message}");
            }

            return boundaryEdges;
        }

        /// <summary>
        /// 分析边界边的连通性
        /// </summary>
        /// <param name="boundaryEdges">边界边集合</param>
        /// <returns>连通性分析字符串</returns>
        private static string AnalyzeBoundaryConnectivity(List<Edge2D> boundaryEdges)
        {
            try
            {
                var vertexConnectionCount = new Dictionary<string, int>();

                // 统计每个顶点的连接数
                foreach (var edge in boundaryEdges)
                {
                    var startKey = $"{edge.Start.X:F3},{edge.Start.Y:F3}";
                    var endKey = $"{edge.End.X:F3},{edge.End.Y:F3}";

                    vertexConnectionCount[startKey] = (vertexConnectionCount.ContainsKey(startKey) ? vertexConnectionCount[startKey] : 0) + 1;
                    vertexConnectionCount[endKey] = (vertexConnectionCount.ContainsKey(endKey) ? vertexConnectionCount[endKey] : 0) + 1;
                }

                // 分析连接模式
                int isolatedVertices = 0;  // 度数为1的顶点
                int normalVertices = 0;    // 度数为2的顶点
                int junctionVertices = 0;  // 度数>2的顶点

                foreach (var count in vertexConnectionCount.Values)
                {
                    if (count == 1) isolatedVertices++;
                    else if (count == 2) normalVertices++;
                    else junctionVertices++;
                }

                return $"顶点: {vertexConnectionCount.Count}, 孤立: {isolatedVertices}, 正常: {normalVertices}, 连接点: {junctionVertices}";
            }
            catch (Exception ex)
            {
                return $"连通性分析失败: {ex.Message}";
            }
        }

        /// <summary>
        /// 从边界边构建轮廓点集合（支持多轮廓）
        /// </summary>
        /// <param name="edges">边界边集合</param>
        /// <returns>轮廓点集合</returns>
        private static List<Point2D> BuildOutlineFromEdges(List<Edge2D> edges)
        {
            var allOutlinePoints = new List<Point2D>();
            var remainingEdges = new List<Edge2D>(edges);
            var contourCount = 0;

            try
            {
                LogManager.Debug($"开始构建轮廓，总边数: {edges.Count}");

                while (remainingEdges.Count > 0 && contourCount < 10) // 最多处理10个轮廓
                {
                    contourCount++;
                    LogManager.Debug($"=== 开始构建第 {contourCount} 个轮廓 ===");

                    var currentContour = BuildSingleContour(remainingEdges);

                    if (currentContour.Count >= 3) // 至少3个点才能形成有效轮廓
                    {
                        LogManager.Debug($"第 {contourCount} 个轮廓包含 {currentContour.Count} 个点");
                        allOutlinePoints.AddRange(currentContour);

                        // 添加轮廓分隔符（使用特殊坐标标记）
                        if (contourCount > 1)
                        {
                            allOutlinePoints.Add(new Point2D(double.NaN, double.NaN)); // 轮廓分隔符
                        }
                    }
                    else
                    {
                        LogManager.Debug($"第 {contourCount} 个轮廓点数不足({currentContour.Count})，跳过");
                        break; // 如果轮廓太小，可能是噪声，停止处理
                    }
                }

                LogManager.Info($"轮廓构建完成，共 {contourCount} 个轮廓，总点数: {allOutlinePoints.Count}");

                // 如果有多个轮廓，返回最大的外部轮廓
                if (contourCount > 1)
                {
                    LogManager.Debug("检测到多个轮廓，返回最大轮廓作为外部边界");
                    return GetLargestContour(allOutlinePoints);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"构建轮廓失败: {ex.Message}");
            }

            return allOutlinePoints;
        }

        /// <summary>
        /// 构建单个连续轮廓
        /// </summary>
        /// <param name="remainingEdges">剩余边集合（会被修改）</param>
        /// <returns>单个轮廓的点集合</returns>
        private static List<Point2D> BuildSingleContour(List<Edge2D> remainingEdges)
        {
            var contour = new List<Point2D>();

            try
            {
                if (remainingEdges.Count == 0) return contour;

                // 从第一条边开始
                var currentEdge = remainingEdges[0];
                remainingEdges.RemoveAt(0);

                contour.Add(currentEdge.Start);
                var currentPoint = currentEdge.End;
                var startPoint = currentEdge.Start;

                LogManager.Debug($"轮廓起点: ({startPoint.X:F2}, {startPoint.Y:F2})");

                // 连接后续的边
                int maxIterations = remainingEdges.Count + 10; // 防止无限循环
                int iteration = 0;

                while (remainingEdges.Count > 0 && iteration < maxIterations)
                {
                    iteration++;
                    var nextEdgeIndex = -1;
                    var tolerance = TOLERANCE_1CM_METERS; // 1cm容差，稍微放宽

                    for (int i = 0; i < remainingEdges.Count; i++)
                    {
                        var edge = remainingEdges[i];

                        // 检查边的起点是否与当前点连接
                        if (Math.Abs(edge.Start.X - currentPoint.X) < tolerance &&
                            Math.Abs(edge.Start.Y - currentPoint.Y) < tolerance)
                        {
                            nextEdgeIndex = i;
                            currentPoint = edge.End;
                            break;
                        }
                        // 检查边的终点是否与当前点连接（反向）
                        else if (Math.Abs(edge.End.X - currentPoint.X) < tolerance &&
                                Math.Abs(edge.End.Y - currentPoint.Y) < tolerance)
                        {
                            nextEdgeIndex = i;
                            currentPoint = edge.Start;
                            break;
                        }
                    }

                    if (nextEdgeIndex >= 0)
                    {
                        contour.Add(currentPoint);
                        remainingEdges.RemoveAt(nextEdgeIndex);

                        // 检查是否回到起点（闭合轮廓）
                        if (Math.Abs(currentPoint.X - startPoint.X) < tolerance &&
                            Math.Abs(currentPoint.Y - startPoint.Y) < tolerance)
                        {
                            LogManager.Debug($"轮廓已闭合，点数: {contour.Count}");
                            break;
                        }
                    }
                    else
                    {
                        LogManager.Warning($"无法找到连接边，轮廓中断，点数: {contour.Count}");
                        break;
                    }
                }

                if (iteration >= maxIterations)
                {
                    LogManager.Warning($"轮廓构建达到最大迭代次数，强制停止");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"构建单个轮廓失败: {ex.Message}");
            }

            return contour;
        }

        /// <summary>
        /// 从多个轮廓中获取最大的轮廓（外部边界）
        /// </summary>
        /// <param name="allPoints">包含多个轮廓的点集合</param>
        /// <returns>最大轮廓的点集合</returns>
        private static List<Point2D> GetLargestContour(List<Point2D> allPoints)
        {
            var contours = new List<List<Point2D>>();
            var currentContour = new List<Point2D>();

            try
            {
                // 分离各个轮廓
                foreach (var point in allPoints)
                {
                    // 检查是否为分隔符
                    if (double.IsNaN(point.X) || double.IsNaN(point.Y))
                    {
                        if (currentContour.Count > 0)
                        {
                            contours.Add(new List<Point2D>(currentContour));
                            currentContour.Clear();
                        }
                    }
                    else
                    {
                        currentContour.Add(point);
                    }
                }

                // 添加最后一个轮廓
                if (currentContour.Count > 0)
                {
                    contours.Add(currentContour);
                }

                if (contours.Count == 0)
                {
                    LogManager.Warning("未找到有效轮廓");
                    return allPoints;
                }

                // 找到最大的轮廓（按包围盒面积）
                double maxArea = 0;
                List<Point2D> largestContour = new List<Point2D>();

                for (int i = 0; i < contours.Count; i++)
                {
                    var contour = contours[i];
                    if (contour.Count >= 3)
                    {
                        var area = CalculateContourArea(contour);
                        LogManager.Debug($"轮廓 {i + 1} 面积: {area:F2}, 点数: {contour.Count}");

                        if (area > maxArea)
                        {
                            maxArea = area;
                            largestContour = contour;
                        }
                    }
                }

                LogManager.Debug($"选择最大轮廓，面积: {maxArea:F2}, 原始点数: {largestContour.Count}");

                // 清理和排序最大轮廓
                var cleanedContour = CleanAndSortContour(largestContour);
                LogManager.Debug($"清理后轮廓点数: {cleanedContour.Count}");

                return cleanedContour;
            }
            catch (Exception ex)
            {
                LogManager.Error($"获取最大轮廓失败: {ex.Message}");
                return allPoints; // 返回原始点集合
            }
        }

        /// <summary>
        /// 清理和排序轮廓点
        /// </summary>
        /// <param name="contour">原始轮廓点</param>
        /// <returns>清理和排序后的轮廓点</returns>
        private static List<Point2D> CleanAndSortContour(List<Point2D> contour)
        {
            var result = new List<Point2D>();

            try
            {
                if (contour.Count < 3)
                {
                    LogManager.Warning($"轮廓点数不足: {contour.Count}");
                    return contour;
                }

                // 第1步：移除重复点
                var uniquePoints = new List<Point2D>();
                const double tolerance = TOLERANCE_1CM_METERS; // 1cm容差

                foreach (var point in contour)
                {
                    bool isDuplicate = false;
                    foreach (var existing in uniquePoints)
                    {
                        if (Math.Abs(point.X - existing.X) < tolerance &&
                            Math.Abs(point.Y - existing.Y) < tolerance)
                        {
                            isDuplicate = true;
                            break;
                        }
                    }

                    if (!isDuplicate)
                    {
                        uniquePoints.Add(point);
                    }
                }

                LogManager.Debug($"去重后点数: {uniquePoints.Count}");

                if (uniquePoints.Count < 3)
                {
                    LogManager.Warning("去重后点数不足，返回原始轮廓");
                    return contour;
                }

                // 第2步：排序点以形成正确的轮廓
                result = SortPointsIntoContour(uniquePoints);

                LogManager.Debug($"排序后轮廓点数: {result.Count}");
                for (int i = 0; i < result.Count; i++)
                {
                    LogManager.Debug($"  排序点 {i}: ({result[i].X:F2}, {result[i].Y:F2})");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"清理轮廓失败: {ex.Message}");
                return contour;
            }

            return result.Count >= 3 ? result : contour;
        }

        /// <summary>
        /// 将点排序成正确的轮廓顺序
        /// </summary>
        /// <param name="points">无序的点集合</param>
        /// <returns>有序的轮廓点</returns>
        private static List<Point2D> SortPointsIntoContour(List<Point2D> points)
        {
            var sortedPoints = new List<Point2D>();

            try
            {
                if (points.Count < 3) return points;

                // 找到最左下角的点作为起点（保证起点的唯一性）
                var startPoint = points.OrderBy(p => p.X).ThenBy(p => p.Y).First();
                sortedPoints.Add(startPoint);

                var remainingPoints = new List<Point2D>(points);
                remainingPoints.Remove(startPoint);

                LogManager.Debug($"轮廓起始点: ({startPoint.X:F2}, {startPoint.Y:F2})");

                // 使用最近邻算法按顺序连接点
                var currentPoint = startPoint;
                while (remainingPoints.Count > 0)
                {
                    Point2D? nearestPoint = null;
                    double minDistance = double.MaxValue;

                    foreach (var point in remainingPoints)
                    {
                        var distance = Math.Sqrt(
                            Math.Pow(point.X - currentPoint.X, 2) +
                            Math.Pow(point.Y - currentPoint.Y, 2)
                        );

                        if (distance < minDistance)
                        {
                            minDistance = distance;
                            nearestPoint = point;
                        }
                    }

                    if (nearestPoint.HasValue)
                    {
                        sortedPoints.Add(nearestPoint.Value);
                        remainingPoints.Remove(nearestPoint.Value);
                        currentPoint = nearestPoint.Value;

                        LogManager.Debug($"下一个点: ({nearestPoint.Value.X:F2}, {nearestPoint.Value.Y:F2}), 距离: {minDistance:F2}");
                    }
                    else
                    {
                        LogManager.Warning("无法找到下一个最近点");
                        break;
                    }
                }

                // 验证轮廓是否闭合（可选）
                if (sortedPoints.Count >= 3)
                {
                    var firstPoint = sortedPoints[0];
                    var lastPoint = sortedPoints[sortedPoints.Count - 1];
                    var closingDistance = Math.Sqrt(
                        Math.Pow(lastPoint.X - firstPoint.X, 2) +
                        Math.Pow(lastPoint.Y - firstPoint.Y, 2)
                    );

                    LogManager.Debug($"轮廓闭合距离: {closingDistance:F2}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"排序轮廓点失败: {ex.Message}");
                return points;
            }

            return sortedPoints;
        }

        /// <summary>
        /// 计算轮廓的包围盒面积
        /// </summary>
        /// <param name="contour">轮廓点集合</param>
        /// <returns>包围盒面积</returns>
        private static double CalculateContourArea(List<Point2D> contour)
        {
            if (contour.Count < 3) return 0;

            try
            {
                var minX = contour.Min(p => p.X);
                var maxX = contour.Max(p => p.X);
                var minY = contour.Min(p => p.Y);
                var maxY = contour.Max(p => p.Y);

                return (maxX - minX) * (maxY - minY);
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// 射线与三角形相交检测（Möller-Trumbore算法）
        /// </summary>
        /// <param name="rayOrigin">射线起点</param>
        /// <param name="rayDirection">射线方向</param>
        /// <param name="triangle">三角形</param>
        /// <param name="intersectionZ">相交点的Z坐标</param>
        /// <returns>是否相交</returns>
        public static bool RayTriangleIntersect(Point3D rayOrigin, Point3D rayDirection, Triangle3D triangle, out double intersectionZ)
        {
            intersectionZ = 0.0;
            const double EPSILON = 0.0000001;

            try
            {
                // 计算三角形的两条边
                var edge1 = SubtractPoints(triangle.Point2, triangle.Point1);
                var edge2 = SubtractPoints(triangle.Point3, triangle.Point1);

                // 计算射线方向与edge2的叉积
                var h = CrossProduct(rayDirection, edge2);
                var a = DotProduct(edge1, h);

                // 如果a接近0，射线与三角形平行
                if (a > -EPSILON && a < EPSILON)
                {
                    return false;
                }

                var f = 1.0 / a;
                var s = SubtractPoints(rayOrigin, triangle.Point1);
                var u = f * DotProduct(s, h);

                if (u < 0.0 || u > 1.0)
                {
                    return false;
                }

                var q = CrossProduct(s, edge1);
                var v = f * DotProduct(rayDirection, q);

                if (v < 0.0 || u + v > 1.0)
                {
                    return false;
                }

                // 计算t值（射线参数）
                var t = f * DotProduct(edge2, q);

                if (t > EPSILON) // 射线相交
                {
                    // 计算交点
                    intersectionZ = rayOrigin.Z + t * rayDirection.Z;
                    return true;
                }

                return false; // 线段相交但射线不相交
            }
            catch (Exception ex)
            {
                LogManager.Error($"射线-三角形相交计算出错: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 点减法运算
        /// </summary>
        public static Point3D SubtractPoints(Point3D a, Point3D b)
        {
            return new Point3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
        }

        /// <summary>
        /// 向量叉积运算
        /// </summary>
        public static Point3D CrossProduct(Point3D a, Point3D b)
        {
            return new Point3D(
                a.Y * b.Z - a.Z * b.Y,
                a.Z * b.X - a.X * b.Z,
                a.X * b.Y - a.Y * b.X
            );
        }

        /// <summary>
        /// Rodrigues旋转公式 - 绕任意轴旋转点
        /// </summary>
        /// <param name="point">要旋转的点</param>
        /// <param name="center">旋转中心</param>
        /// <param name="axis">旋转轴（单位向量）</param>
        /// <param name="angle">旋转角度（弧度）</param>
        /// <returns>旋转后的点</returns>
        public static Point3D RotatePointAroundAxis(
            Point3D point,
            Point3D center,
            Vector3D axis,
            double angle)
        {
            // 将点转换为相对于中心的向量
            Vector3D v = point - center;

            // Rodrigues旋转公式
            // v_rot = v * cos(θ) + (k × v) * sin(θ) + k * (k · v) * (1 - cos(θ))
            Point3D kxv = CrossProduct(
                new Point3D(axis.X, axis.Y, axis.Z),
                new Point3D(v.X, v.Y, v.Z));
            double kdv = DotProduct(
                new Point3D(axis.X, axis.Y, axis.Z),
                new Point3D(v.X, v.Y, v.Z));

            Vector3D kxvVec = new Vector3D(kxv.X, kxv.Y, kxv.Z);
            Vector3D vRot = v * Math.Cos(angle) + kxvVec * Math.Sin(angle) + axis * kdv * (1 - Math.Cos(angle));

            return center + vRot;
        }

        /// <summary>
        /// 向量点积运算
        /// </summary>
        public static double DotProduct(Point3D a, Point3D b)
        {
            return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
        }

        /// <summary>
        /// 检查2D点是否在三角形内部（使用重心坐标法）
        /// </summary>
        /// <param name="point">测试点</param>
        /// <param name="triangle">三角形</param>
        /// <returns>是否在内部</returns>
        public static bool IsPointInTriangle2D(Point3D point, Triangle3D triangle)
        {
            // 使用重心坐标法判断点是否在三角形内
            var v0x = triangle.Point3.X - triangle.Point1.X;
            var v0y = triangle.Point3.Y - triangle.Point1.Y;
            var v1x = triangle.Point2.X - triangle.Point1.X;
            var v1y = triangle.Point2.Y - triangle.Point1.Y;
            var v2x = point.X - triangle.Point1.X;
            var v2y = point.Y - triangle.Point1.Y;

            var dot00 = v0x * v0x + v0y * v0y;
            var dot01 = v0x * v1x + v0y * v1y;
            var dot02 = v0x * v2x + v0y * v2y;
            var dot11 = v1x * v1x + v1y * v1y;
            var dot12 = v1x * v2x + v1y * v2y;

            var invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
            var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
            var v = (dot00 * dot12 - dot01 * dot02) * invDenom;

            return (u >= 0) && (v >= 0) && (u + v <= 1);
        }

        /// <summary>
        /// 计算两个3D点之间的距离
        /// </summary>
        /// <param name="point1">第一个点</param>
        /// <param name="point2">第二个点</param>
        /// <returns>两点之间的欧几里得距离</returns>
        public static double CalculatePointDistance(Point3D point1, Point3D point2)
        {
            var dx = point1.X - point2.X;
            var dy = point1.Y - point2.Y;
            var dz = point1.Z - point2.Z;
            return Math.Sqrt(dx * dx + dy * dy + dz * dz);
        }
    }

    /// <summary>
    /// 片段信息类 - 优化版本，预处理Transform矩阵避免COM对象泄露
    /// </summary>
    public class FragmentInfo
    {
        public ComApi.InwOaFragment3 Fragment { get; set; }
        public double[] TransformMatrix { get; set; }  // 预处理为普通数组，避免COM对象泄露
        public string PathKey { get; set; }
    }

    /// <summary>
    /// 优化的几何回调处理器 - 使用预处理的矩阵数组避免COM对象泄露
    /// </summary>
    public class OptimizedGeometryCallback : ComApi.InwSimplePrimitivesCB
    {
        private List<Triangle3D> _triangles = new List<Triangle3D>();
        private double[] _transformMatrix;

        public OptimizedGeometryCallback(double[] transformMatrix)
        {
            _transformMatrix = transformMatrix;
        }

        public void Line(ComApi.InwSimpleVertex v1, ComApi.InwSimpleVertex v2)
        {
            // 线段处理（如果需要）
        }

        public void Point(ComApi.InwSimpleVertex v1)
        {
            // 点处理（如果需要）
        }

        public void SnapPoint(ComApi.InwSimpleVertex v1)
        {
            // 捕捉点处理（如果需要）
        }

        public void Triangle(ComApi.InwSimpleVertex v1, ComApi.InwSimpleVertex v2, ComApi.InwSimpleVertex v3)
        {
            try
            {
                // 使用优化的数组访问方法
                var coords1 = ((Array)(object)v1.coord).ToArray<float>();
                var coords2 = ((Array)(object)v2.coord).ToArray<float>();
                var coords3 = ((Array)(object)v3.coord).ToArray<float>();

                // 创建局部坐标点
                var localPoint1 = new Point3D(coords1[0], coords1[1], coords1[2]);
                var localPoint2 = new Point3D(coords2[0], coords2[1], coords2[2]);
                var localPoint3 = new Point3D(coords3[0], coords3[1], coords3[2]);

                // 应用变换矩阵转换为世界坐标
                var worldPoint1 = TransformPoint(localPoint1);
                var worldPoint2 = TransformPoint(localPoint2);
                var worldPoint3 = TransformPoint(localPoint3);

                // 创建三角形
                var triangle = new Triangle3D(worldPoint1, worldPoint2, worldPoint3);
                _triangles.Add(triangle);
            }
            catch (Exception ex)
            {
                LogManager.Error($"处理三角形失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 将局部坐标点转换为世界坐标点 - 优化版本，直接使用预处理的矩阵数组
        /// </summary>
        /// <param name="localPoint">局部坐标点</param>
        /// <returns>世界坐标点</returns>
        private Point3D TransformPoint(Point3D localPoint)
        {
            if (_transformMatrix == null || _transformMatrix.Length != 16)
            {
                return localPoint; // 如果没有有效的变换矩阵，返回原始点
            }

            try
            {
                // 应用变换矩阵 (4x4 矩阵，列主序)
                double x = localPoint.X;
                double y = localPoint.Y;
                double z = localPoint.Z;
                double w = 1.0;

                double newX = _transformMatrix[0] * x + _transformMatrix[4] * y + _transformMatrix[8] * z + _transformMatrix[12] * w;
                double newY = _transformMatrix[1] * x + _transformMatrix[5] * y + _transformMatrix[9] * z + _transformMatrix[13] * w;
                double newZ = _transformMatrix[2] * x + _transformMatrix[6] * y + _transformMatrix[10] * z + _transformMatrix[14] * w;
                double newW = _transformMatrix[3] * x + _transformMatrix[7] * y + _transformMatrix[11] * z + _transformMatrix[15] * w;

                // 透视除法（如果需要）
                if (Math.Abs(newW) > 1e-10)
                {
                    newX /= newW;
                    newY /= newW;
                    newZ /= newW;
                }

                return new Point3D(newX, newY, newZ);
            }
            catch (Exception ex)
            {
                LogManager.Error($"坐标变换失败: {ex.Message}");
                return localPoint;
            }
        }

        /// <summary>
        /// 获取提取的三角形集合
        /// </summary>
        /// <returns>三角形集合</returns>
        public List<Triangle3D> GetTriangles()
        {
            return _triangles;
        }
    }

    /// <summary>
    /// 数组扩展方法（性能优化）
    /// </summary>
    public static class ArrayExtensions
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static T[] ToArray<T>(this Array arr) where T : struct
        {
            T[] result = new T[arr.Length];
            Array.Copy(arr, result, result.Length);
            return result;
        }
    }

    /// <summary>
    /// 三角形结构体
    /// </summary>
    public struct Triangle3D
    {
        public Point3D Point1 { get; }
        public Point3D Point2 { get; }
        public Point3D Point3 { get; }

        public Triangle3D(Point3D point1, Point3D point2, Point3D point3)
        {
            Point1 = point1;
            Point2 = point2;
            Point3 = point3;
        }

        public override string ToString()
        {
            return $"Triangle[{Point1}, {Point2}, {Point3}]";
        }
    }

    /// <summary>
    /// 2D点结构体
    /// </summary>
    public struct Point2D
    {
        public double X { get; }
        public double Y { get; }

        public Point2D(double x, double y)
        {
            X = x;
            Y = y;
        }

        public override string ToString()
        {
            return $"Point2D({X:F3}, {Y:F3})";
        }
    }

    /// <summary>
    /// 2D边结构体
    /// </summary>
    public struct Edge2D
    {
        public Point2D Start { get; }
        public Point2D End { get; }

        public Edge2D(Point2D start, Point2D end)
        {
            Start = start;
            End = end;
        }

        public string GetKey()
        {
            return $"{Start.X:F6},{Start.Y:F6}-{End.X:F6},{End.Y:F6}";
        }

        public string GetReverseKey()
        {
            return $"{End.X:F6},{End.Y:F6}-{Start.X:F6},{Start.Y:F6}";
        }

        public override string ToString()
        {
            return $"Edge2D[{Start} -> {End}]";
        }
    }
}