using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Utils;
using NavisworksTransport.Utils.CoordinateSystem;
using static NavisworksTransport.Core.Config.ConfigManager;

namespace NavisworksTransport
{
    /// <summary>
    /// 路径可视化模式枚举
    /// </summary>
    public enum PathVisualizationMode
    {
        /// <summary>
        /// 标准连线模式 - 圆柱形连线
        /// </summary>
        StandardLine,

        /// <summary>
        /// 带状连线模式 - 长方体连线
        /// </summary>
        RibbonLine,

        /// <summary>
        /// 物体通行空间模式 - 矩形通道
        /// </summary>
        ObjectSpace
    }

    /// <summary>
    /// 网格点类型枚举
    /// </summary>
    public enum GridPointType
    {
        /// <summary>
        /// 球形
        /// </summary>
        Sphere,

        /// <summary>
        /// 正方形
        /// </summary>
        Rectangle,

        /// <summary>
        /// 圆
        /// </summary>
        Circle
    }


    /// <summary>
    /// 可视化元素样式名称枚举
    /// </summary>
    public enum RenderStyleName
    {
        /// <summary>
        /// 路径起点样式（绿色）
        /// </summary>
        StartPoint,

        /// <summary>
        /// 路径终点样式（红色）
        /// </summary>
        EndPoint,

        /// <summary>
        /// 路径中间点样式（蓝色）
        /// </summary>
        WayPoint,

        /// <summary>
        /// 连线样式（橙色）
        /// </summary>
        Line,

        /// <summary>
        /// 物体通行空间样式（灰色）
        /// </summary>
        ObjectSpace,

        /// <summary>
        /// 预览点样式（白色）
        /// </summary>
        PreviewPoint,

        /// <summary>
        /// 预览连线样式（灰色）
        /// </summary>
        PreviewLine,

        /// <summary>
        /// 未到达终点样式（深红色）
        /// </summary>
        UnreachedEndPoint,

        /// <summary>
        /// 网格通道样式（浅绿色）
        /// </summary>
        GridChannel,

        /// <summary>
        /// 网格障碍物样式（灰色）
        /// </summary>
        GridObstacle,

        /// <summary>
        /// 网格未知区域样式（深橙色）
        /// </summary>
        GridUnknown,

        /// <summary>
        /// 切点样式（深红色）
        /// </summary>
        TangentPoint,

        /// <summary>
        /// 安全警告样式（红色）
        /// </summary>
        SafetyWarning,

        /// <summary>
        /// 空轨基准路径样式（浅红色）
        /// </summary>
        RailBaseline,

        /// <summary>
        /// 直线装配基准向量样式（绿色）
        /// </summary>
        AssemblyGuideLine,

        /// <summary>
        /// 直线装配安装参考面样式（绿色半透明）
        /// </summary>
        AssemblyInstallationPlane,

        /// <summary>
        /// 吊装路径样式（紫色）
        /// </summary>
        HoistingLine
        ,

        /// <summary>
        /// 真实物体原始位姿 X 轴样式（红色）
        /// </summary>
        TransformAxisX,

        /// <summary>
        /// 真实物体原始位姿 Y 轴样式（绿色）
        /// </summary>
        TransformAxisY,

        /// <summary>
        /// 真实物体原始位姿 Z 轴样式（蓝色）
        /// </summary>
        TransformAxisZ
    }

    /// <summary>
    /// 渲染样式，包含颜色和透明度
    /// </summary>
    public readonly struct RenderStyle
    {
        /// <summary>
        /// 颜色
        /// </summary>
        public Color Color { get; }

        /// <summary>
        /// 透明度 (0.0 = 完全透明, 1.0 = 完全不透明)
        /// </summary>
        public double Alpha { get; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="color">颜色</param>
        /// <param name="alpha">透明度</param>
        public RenderStyle(Color color, double alpha)
        {
            Color = color;
            Alpha = alpha;
        }

        public override string ToString()
        {
            return $"RenderStyle[Color={Color}, Alpha={Alpha:F2}]";
        }
    }

    /// <summary>
    /// 物体通行空间标记，用于渲染物体通道空间
    /// </summary>
    public class ObjectSpaceMarker
    {
        /// <summary>
        /// 通道起点
        /// </summary>
        public Point3D StartPoint { get; set; }

        /// <summary>
        /// 通道终点
        /// </summary>
        public Point3D EndPoint { get; set; }

        /// <summary>
        /// 通道宽度（垂直于路径方向的尺寸）
        /// </summary>
        public double Width { get; set; }

        /// <summary>
        /// 通道高度（法线方向的尺寸）
        /// </summary>
        public double Height { get; set; }

        /// <summary>
        /// 通道颜色
        /// </summary>
        public Color Color { get; set; }

        /// <summary>
        /// 透明度（0.0-1.0，默认0.5即50%透明）
        /// </summary>
        public double Alpha { get; set; } = 0.5;

        /// <summary>
        /// 起点在路径中的索引
        /// </summary>
        public int FromIndex { get; set; }

        /// <summary>
        /// 终点在路径中的索引
        /// </summary>
        public int ToIndex { get; set; }

        public override string ToString()
        {
            return $"ObjectSpaceMarker[{FromIndex}->{ToIndex}, 宽度={Width:F2}m, 高度={Height:F2}m, 透明度={Alpha:F1}]";
        }
    }

    /// <summary>
    /// 连线标记，用于渲染路径点之间的连接线
    /// </summary>
    public class LineMarker
    {
        /// <summary>
        /// 连线起点
        /// </summary>
        public Point3D StartPoint { get; set; }

        /// <summary>
        /// 连线终点
        /// </summary>
        public Point3D EndPoint { get; set; }

        /// <summary>
        /// 连线颜色
        /// </summary>
        public Color Color { get; set; }

        /// <summary>
        /// 连线半径
        /// </summary>
        public double Radius { get; set; }

        /// <summary>
        /// 起点在路径中的索引
        /// </summary>
        public int FromIndex { get; set; }

        /// <summary>
        /// 终点在路径中的索引
        /// </summary>
        public int ToIndex { get; set; }

        /// <summary>
        /// 路径段类型
        /// </summary>
        public PathSegmentType SegmentType { get; set; } = PathSegmentType.Straight;

        /// <summary>
        /// 圆弧轨迹数据（仅当SegmentType=Arc时有效）
        /// </summary>
        public ArcTrajectory Trajectory { get; set; }

        /// <summary>
        /// 采样点列表（用于圆弧段的多段圆柱体渲染）
        /// </summary>
        public List<Point3D> SampledPoints { get; set; }

        /// <summary>
        /// 带状连线高度（仅用于 RibbonLine 和 ObjectSpace 模式）
        /// </summary>
        public double Height { get; set; }

        /// <summary>
        /// 带状连线宽度（仅用于 ObjectSpace 模式）
        /// </summary>
        public double Width { get; set; }

        /// <summary>
        /// 透明度（0.0=完全透明，1.0=完全不透明）
        /// </summary>
        public double Opacity { get; set; } = 1.0;

        /// <summary>
        /// 水平段方向向量（用于垂直段渲染时确定通行空间方向）
        /// </summary>
        public Vector3D HorizontalDirection { get; set; }

        /// <summary>
        /// 通行空间的优先 up 方向（例如 Rail 安装面法向）
        /// </summary>
        public Vector3D UpDirection { get; set; }

        public override string ToString()
        {
            return $"LineMarker[{FromIndex}->{ToIndex}, 类型={SegmentType}, 起点=({StartPoint.X:F2},{StartPoint.Y:F2},{StartPoint.Z:F2}), 终点=({EndPoint.X:F2},{EndPoint.Y:F2},{EndPoint.Z:F2})]";
        }
    }

    /// <summary>
    /// 路径可视化数据，包含一个完整路径的所有可视化元素
    /// </summary>
    public class PathVisualization
    {
        /// <summary>
        /// 路径唯一标识
        /// </summary>
        public string PathId { get; set; }

        /// <summary>
        /// 路径数据引用
        /// </summary>
        public PathRoute PathRoute { get; set; }

        /// <summary>
        /// 点标记集合
        /// </summary>
        public List<CircleMarker> PointMarkers { get; set; }

        /// <summary>
        /// 控制点连线集合（用户意图，半透明）
        /// </summary>
        public List<LineMarker> ControlLineMarkers { get; set; }

        /// <summary>
        /// 路径连线集合（真实路径，不透明）
        /// </summary>
        public List<LineMarker> PathLineMarkers { get; set; }

        /// <summary>
        /// 切点标记集合
        /// </summary>
        public List<SquareMarker> TangentMarkers { get; set; }

        /// <summary>
        /// 物体通行空间标记集合
        /// </summary>
        public List<ObjectSpaceMarker> ObjectSpaceMarkers { get; set; }

        /// <summary>
        /// 平面标记集合
        /// </summary>
        public List<PlaneMarker> PlaneMarkers { get; set; }

        /// <summary>
        /// 是否显示控制点可视化（用户意图）
        /// </summary>
        public bool ShowControlVisualization { get; set; } = true;

        /// <summary>
        /// 最后更新时间
        /// </summary>
        public DateTime LastUpdated { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public PathVisualization()
        {
            PointMarkers = new List<CircleMarker>();
            ControlLineMarkers = new List<LineMarker>();
            PathLineMarkers = new List<LineMarker>();
            TangentMarkers = new List<SquareMarker>();
            ObjectSpaceMarkers = new List<ObjectSpaceMarker>();
            PlaneMarkers = new List<PlaneMarker>();
            LastUpdated = DateTime.Now;
        }

        public override string ToString()
        {
            return $"PathVisualization[PathId={PathId}, 点数={PointMarkers.Count}, 控制连线={ControlLineMarkers.Count}, 路径连线={PathLineMarkers.Count}]";
        }
    }
    /// <summary>
    /// 路径点圆形标记渲染插件
    /// 使用Graphics.Circle在3D空间绘制圆形标记
    /// </summary>
    [Plugin("PathPointRenderPlugin", "NavisworksTransport", DisplayName = "路径点圆形标记渲染器")]
    public class PathPointRenderPlugin : RenderPlugin
    {
        private readonly object _lockObject = new object();
        private Dictionary<string, PathVisualization> _pathVisualizations = new Dictionary<string, PathVisualization>();
        private bool _isEnabled = true;

        // 预览点标记
        private CircleMarker _previewMarker = null;

        // 预览连线标记
        private List<LineMarker> _previewLines = new List<LineMarker>();

        // 空轨基准路径可视化
        private Dictionary<string, PathVisualization> _railBaselineVisualizations = new Dictionary<string, PathVisualization>();

        // 当前网格大小（米），用于自适应点大小计算
        private double _currentGridSizeInMeters;

        // 路径可视化模式配置
        private PathVisualizationMode _visualizationMode = PathVisualizationMode.RibbonLine;

        // 独立可视化开关（替代单一模式）
        private bool _showPathLines = true;      // 显示路径线（地面连线/带状线）
        private bool _showObjectSpace = false;  // 显示通行空间

        // 网格点类型配置
        private GridPointType _gridPointType = GridPointType.Rectangle;

        // 通行空间参数（最终尺寸，已包括安全间隙）- 内部使用模型单位
        private double _passageAlongPath;   // 通行空间沿路径方向的尺寸（模型单位）
        private double _passageAcrossPath;  // 通行空间垂直于路径方向的尺寸（模型单位）
        private double _passageNormalToPath;  // 通行空间法线方向的尺寸（模型单位）

        // 物体尺寸 - 内部使用模型单位
        private double _objectLength;  // 物体长度（模型单位）
        private double _objectHeight;  // 物体高度（模型单位）

        // 静态实例，用于外部访问
        private static PathPointRenderPlugin _instance;
        
        // 防抖机制：记录上次刷新时间（使用高精度计数器）
        private long _lastRefreshTicks = 0;

        /// <summary>
        /// 构造函数
        /// </summary>
        public PathPointRenderPlugin()
        {
            _instance = this;
            
            // 订阅配置变更事件，实现通行空间透明度实时生效
            try
            {
                ConfigManager.Instance.CategoryConfigurationChanged += OnConfigurationChanged;
                LogManager.Info("[PathPointRenderPlugin] 已订阅配置变更事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[PathPointRenderPlugin] 订阅配置变更事件失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 配置变更事件处理
        /// </summary>
        private void OnConfigurationChanged(object sender, Tuple<ConfigCategory, ConfigurationChangedEventArgs> e)
        {
            try
            {
                // 只处理可视化配置变更
                if (e.Item1 == ConfigCategory.Visualization || e.Item1 == ConfigCategory.All)
                {
                    LogManager.Info("[PathPointRenderPlugin] 可视化配置已变更，刷新所有路径渲染");
                    
                    // 重新构建所有路径可视化（使用新的透明度设置）
                    lock (_lockObject)
                    {
                        foreach (var visualization in _pathVisualizations.Values)
                        {
                            BuildVisualization(visualization);
                        }
                    }
                    
                    // 请求视图刷新
                    RequestViewRefresh();
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[PathPointRenderPlugin] 处理配置变更失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取静态实例
        /// </summary>
        public static PathPointRenderPlugin Instance => _instance;

        /// <summary>
        /// 路径可视化模式（向后兼容，根据 ShowPathLines 和 ShowObjectSpace 计算）
        /// </summary>
        public PathVisualizationMode VisualizationMode
        {
            get 
            { 
                // 根据新的独立开关计算模式
                if (_showObjectSpace) return PathVisualizationMode.ObjectSpace;
                if (_showPathLines) return PathVisualizationMode.RibbonLine;
                return PathVisualizationMode.StandardLine;
            }
            set
            {
                _visualizationMode = value;
                // 同步到新的独立开关
                _showObjectSpace = (value == PathVisualizationMode.ObjectSpace);
                _showPathLines = (value == PathVisualizationMode.RibbonLine || value == PathVisualizationMode.StandardLine);
                // 模式改变时刷新所有普通路径（排除网格）
                RefreshNormalPaths();
            }
        }

        /// <summary>
        /// 是否显示路径线（地面连线/带状线）
        /// </summary>
        public bool ShowPathLines
        {
            get { return _showPathLines; }
            set
            {
                _showPathLines = value;
                RefreshNormalPaths();
            }
        }

        /// <summary>
        /// 是否显示通行空间（物体通行空间）
        /// </summary>
        public bool ShowObjectSpace
        {
            get { return _showObjectSpace; }
            set
            {
                _showObjectSpace = value;
                RefreshNormalPaths();
            }
        }

        /// <summary>
        /// 网格点类型
        /// </summary>
        public GridPointType GridPointType
        {
            get { return _gridPointType; }
            set
            {
                _gridPointType = value;
                // 类型改变时刷新所有网格路径
                RefreshGridPaths();
            }
        }


        /// <summary>
        /// 是否启用渲染
        /// </summary>
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                // 触发视图刷新
                if (Application.ActiveDocument?.ActiveView != null)
                {
                    Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render);
                }
            }
        }

        /// <summary>
        /// 当前路径总数
        /// </summary>
        public int PathCount
        {
            get
            {
                lock (_lockObject)
                {
                    return _pathVisualizations.Count;
                }
            }
        }

        /// <summary>
        /// 当前点标记总数
        /// </summary>
        public int MarkerCount
        {
            get
            {
                lock (_lockObject)
                {
                    return _pathVisualizations.Values.Sum(v => v.PointMarkers.Count);
                }
            }
        }

        /// <summary>
        /// Navisworks渲染回调方法
        /// </summary>
        /// <param name="view">当前视图</param>
        /// <param name="graphics">图形上下文</param>
        public override void Render(View view, Graphics graphics)
        {
            if (!_isEnabled)
            {
                return;
            }

            try
            {
                // 快速检查，避免频繁的API调用
                var activeDoc = Application.ActiveDocument;
                if (activeDoc?.Models == null || activeDoc.Models.Count == 0)
                {
                    return; // 静默返回
                }

                // 检查是否有路径或预览点需要渲染
                int pathCount;
                int railBaselineCount;
                bool hasPreviewPoint;
                lock (_lockObject)
                {
                    pathCount = _pathVisualizations.Count;
                    railBaselineCount = _railBaselineVisualizations.Count;
                    hasPreviewPoint = _previewMarker != null;
                }

                if (pathCount == 0 && railBaselineCount == 0 && !hasPreviewPoint)
                {
                    return;
                }

                // 使用BeginModelContext确保正确的渲染上下文
                graphics.BeginModelContext();

                lock (_lockObject)
                {
                    // 渲染所有正式路径
                    foreach (var visualization in _pathVisualizations.Values)
                    {
                        // 渲染控制点可视化（用户意图）
                        if (visualization.ShowControlVisualization)
                        {
                            // 渲染所有点标记
                            foreach (var pointMarker in visualization.PointMarkers)
                            {
                                graphics.Color(pointMarker.Color, pointMarker.Alpha);
                                RenderPointMarker(graphics, pointMarker);
                            }

                            foreach (var planeMarker in visualization.PlaneMarkers)
                            {
                                RenderPlaneMarker(graphics, planeMarker);
                            }

                            // 渲染控制点连线（半透明）
                            foreach (var controlLineMarker in visualization.ControlLineMarkers)
                            {
                                var style = GetRenderStyle(RenderStyleName.PreviewLine);
                                graphics.Color(style.Color, style.Alpha);  // 完全使用PreviewLine的颜色和透明度
                                graphics.Cylinder(controlLineMarker.StartPoint, controlLineMarker.EndPoint, controlLineMarker.Radius);
                            }
                        }
                        
                        // 渲染真实路径可视化（使用独立开关，可同时显示多种）
                        // 先渲染路径线（地面连线/带状线）
                        if (_showPathLines)
                        {
                            // 先渲染切点（在底层）
                            foreach (var tangentMarker in visualization.TangentMarkers)
                            {
                                RenderSquareMarker(graphics, tangentMarker);
                            }

                            // 再渲染路径连线
                            foreach (var pathLineMarker in visualization.PathLineMarkers)
                            {
                                RenderLineMarker(graphics, pathLineMarker);
                            }
                        }

                        // 再渲染通行空间（可以在路径线之上）
                        if (_showObjectSpace)
                        {
                            // ObjectSpace 模式：使用物体通行空间渲染（高高度长方体）
                            foreach (var pathLineMarker in visualization.PathLineMarkers)
                            {
                                RenderRibbonLineMarker(graphics, pathLineMarker);
                            }
                        }
                    }

                    // 渲染预览点（灰色）
                    if (_previewMarker != null && _previewMarker.IsVisible)
                    {
                        graphics.Color(_previewMarker.Color, 0.7); // 使用半透明效果
                        RenderPointMarker(graphics, _previewMarker);
                    }

                    // 渲染预览连线（灰色）
                    if (_previewLines.Count > 0)
                    {
                        foreach (var previewLine in _previewLines)
                        {
                            graphics.Color(previewLine.Color, 0.7); // 使用半透明效果
                            graphics.Cylinder(previewLine.StartPoint, previewLine.EndPoint, previewLine.Radius);
                        }
                    }

                    // 渲染空轨基准路径（浅红色）
                    if (_railBaselineVisualizations.Count > 0)
                    {
                        foreach (var visualization in _railBaselineVisualizations.Values)
                        {
                            foreach (var pathLineMarker in visualization.PathLineMarkers)
                            {
                                graphics.Color(pathLineMarker.Color, 0.7); // 使用70%透明度
                                graphics.Cylinder(pathLineMarker.StartPoint, pathLineMarker.EndPoint, pathLineMarker.Radius);
                            }
                        }
                    }
                }

                graphics.EndModelContext();
            }
            catch (InvalidOperationException ex) when (ex.Message.Contains("[渲染错误]"))
            {
                // 🔥 参数错误不应该静默处理，需要暴露出来让开发者修复
                LogManager.Error($"[渲染错误] {ex.Message}");
                throw; // 重新抛出，让上层捕获并显示给用户
            }
            catch (Exception ex)
            {
                // 其他渲染异常静默处理，避免影响Navisworks主程序
                LogManager.Error($"[渲染异常] {ex.Message}", ex);
            }
        }

        #region 新的统一路径可视化接口

        /// <summary>
        /// 渲染完整路径
        /// </summary>
        /// <param name="pathRoute">路径数据</param>
        public void RenderPath(PathRoute pathRoute)
        {
            if (pathRoute == null)
            {
                return;
            }

            try
            {
                // 清除所有其他路径的可视化，只保留当前路径
                ClearPathsExcept(pathRoute.Id);

                var visualization = new PathVisualization
                {
                    PathId = pathRoute.Id,
                    PathRoute = pathRoute
                };

                BuildVisualization(visualization);

                lock (_lockObject)
                {
                    _pathVisualizations[pathRoute.Id] = visualization;
                }

                RequestViewRefresh();
            }
            catch (InvalidOperationException ex) when (ex.Message.Contains("[渲染错误]"))
            {
                // 🔥 参数错误不应该静默处理，需要暴露出来让开发者修复
                LogManager.Error($"[渲染错误] {ex.Message}");
                throw; // 重新抛出，让上层捕获
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径渲染] 渲染路径失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 只渲染点标记，不绘制连线（用于自动路径规划的起终点显示）
        /// </summary>
        public void RenderPointOnly(PathRoute pathRoute)
        {
            if (pathRoute == null)
            {
                return;
            }

            try
            {
                // 检查是否是网格可视化路径
                bool isGridVisualization = pathRoute.Id == "grid_visualization_all" ||
                                           pathRoute.Id == "grid_visualization_channel" ||
                                           pathRoute.Id == "grid_visualization_door" ||
                                           pathRoute.Id == "grid_visualization_unknown" ||
                                           pathRoute.Id == "grid_visualization_obstacle";

                var visualization = new PathVisualization
                {
                    PathId = pathRoute.Id,
                    PathRoute = pathRoute
                };

                // 只构建点标记，不构建连线
                BuildPointMarkersOnly(visualization);

                lock (_lockObject)
                {
                    _pathVisualizations[pathRoute.Id] = visualization;
                }

                RequestViewRefresh();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[点标记渲染] 渲染点标记失败: {ex.Message}", ex);
            }
        }

        public void RenderRectanglePlane(
            string pathId,
            Point3D origin,
            Vector3D xVector,
            Vector3D yVector,
            RenderStyleName renderStyleName,
            bool filled = true)
        {
            if (string.IsNullOrWhiteSpace(pathId))
            {
                throw new ArgumentException("pathId 不能为空。", nameof(pathId));
            }

            try
            {
                var visualization = new PathVisualization
                {
                    PathId = pathId,
                    PathRoute = new PathRoute(pathId)
                    {
                        Id = pathId,
                        Description = $"矩形平面可视化:{pathId}"
                    }
                };

                var renderStyle = GetRenderStyle(renderStyleName);
                visualization.PlaneMarkers.Add(new PlaneMarker
                {
                    Origin = origin,
                    XVector = xVector,
                    YVector = yVector,
                    Color = renderStyle.Color,
                    Alpha = renderStyle.Alpha,
                    Filled = filled
                });

                lock (_lockObject)
                {
                    _pathVisualizations[pathId] = visualization;
                }

                RequestViewRefresh();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[平面渲染] 渲染矩形平面失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 清除网格可视化
        /// </summary>
        public void ClearGridVisualization()
        {
            try
            {
                lock (_lockObject)
                {
                    // 清除所有网格可视化
                    RemovePath("grid_visualization_walkable");
                    RemovePath("grid_visualization_obstacle");
                    RemovePath("grid_visualization_unknown");
                    RemovePath("grid_visualization_door");
                    // 清除旧的网格可视化 ID（向后兼容）
                    RemovePath("grid_visualization_all");
                    RemovePath("grid_visualization_channel");
                }

                RequestViewRefresh();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[网格可视化] 清除网格可视化失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 渲染网格可视化（使用专门的 GridMarker 类型）
        /// </summary>
        /// <param name="gridVis">网格可视化对象</param>
        public void RenderGridVisualization(GridVisualization gridVis)
        {
            if (gridVis == null)
            {
                LogManager.Warning("[网格可视化] GridVisualization 对象为 null，无法渲染");
                return;
            }

            try
            {
                // 清除之前的网格可视化
                ClearGridVisualization();

                // 渲染可通行的网格点（绿色）
                if (gridVis.Walkable.Count > 0)
                {
                    RenderGridMarkers("grid_visualization_walkable", gridVis.Walkable, GridVisualizationType.Walkable);
                }

                // 渲染障碍物网格点（灰色）
                if (gridVis.Obstacle.Count > 0)
                {
                    RenderGridMarkers("grid_visualization_obstacle", gridVis.Obstacle, GridVisualizationType.Obstacle);
                }

                // 渲染未知区域网格点（红色）
                if (gridVis.Unknown.Count > 0)
                {
                    RenderGridMarkers("grid_visualization_unknown", gridVis.Unknown, GridVisualizationType.Unknown);
                }

                // 渲染门网格点（半透明绿色）
                if (gridVis.Door.Count > 0)
                {
                    RenderGridMarkers("grid_visualization_door", gridVis.Door, GridVisualizationType.Door);
                }

                RequestViewRefresh();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[网格可视化] 渲染失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 渲染一组网格标记
        /// </summary>
        /// <param name="pathId">路径 ID</param>
        /// <param name="markers">网格标记列表</param>
        /// <param name="cellType">网格可视化类型</param>
        private void RenderGridMarkers(string pathId, List<GridMarker> markers, GridVisualizationType cellType)
        {
            if (markers == null || markers.Count == 0)
            {
                return;
            }

            var visualization = new PathVisualization
            {
                PathId = pathId,
                PathRoute = null  // 网格可视化不使用 PathRoute
            };

            // 创建点标记
            foreach (var marker in markers)
            {
                var pointMarker = CreateGridMarker(marker);
                visualization.PointMarkers.Add(pointMarker);
            }

            lock (_lockObject)
            {
                _pathVisualizations[pathId] = visualization;
            }
        }

        /// <summary>
        /// 创建网格标记（类型安全，无需字符串匹配）
        /// </summary>
        /// <param name="marker">网格标记</param>
        /// <returns>圆点标记对象</returns>
        private CircleMarker CreateGridMarker(GridMarker marker)
        {
            // 根据网格可视化类型确定颜色和透明度
            RenderStyle style = new RenderStyle(Color.White, 1.0);
            switch (marker.CellType)
            {
                case GridVisualizationType.Walkable:
                    style = GetRenderStyle(RenderStyleName.GridChannel);
                    break;
                case GridVisualizationType.Obstacle:
                    style = GetRenderStyle(RenderStyleName.GridObstacle);
                    break;
                case GridVisualizationType.Unknown:
                    style = GetRenderStyle(RenderStyleName.GridUnknown);
                    break;
                case GridVisualizationType.Door:
                    // 门使用50%透明度
                    style = new RenderStyle(GetRenderStyle(RenderStyleName.GridChannel).Color, 0.5);
                    break;
            }

            return new CircleMarker
            {
                Center = marker.Position,
                Normal = GetHostUpVector(),
                Radius = GetRadiusForGridVisualization(),
                Color = style.Color,
                Alpha = style.Alpha,
                Filled = true,
                PointType = PathPointType.WayPoint,
                GridPointType = _gridPointType,
                SequenceNumber = 0,
                CreatedTime = DateTime.Now
            };
        }

        /// <summary>
        /// 只构建点标记，不构建连线
        /// </summary>
        private void BuildPointMarkersOnly(PathVisualization visualization)
        {
            // 清空现有标记
            visualization.PointMarkers.Clear();
            visualization.ControlLineMarkers.Clear(); // 确保没有控制点连线
            visualization.PathLineMarkers.Clear(); // 确保没有路径连线
            visualization.PlaneMarkers.Clear();

            var points = visualization.PathRoute.Points;
            if (points.Count == 0) return;

            // 检查是否是网格可视化路径
            bool isGridVisualization = visualization.PathId == "grid_visualization_all" ||
                                      visualization.PathId == "grid_visualization_channel" ||
                                      visualization.PathId == "grid_visualization_door" ||
                                      visualization.PathId == "grid_visualization_unknown" ||
                                      visualization.PathId == "grid_visualization_obstacle";

            // 按索引排序点
            var sortedPoints = points.OrderBy(p => p.Index).ToList();

            // 只构建点标记，不构建连线
            foreach (var point in sortedPoints)
            {
                var pointMarker = CreatePointMarker(point);
                visualization.PointMarkers.Add(pointMarker);
            }

            visualization.LastUpdated = DateTime.Now;
        }

        /// <summary>
        /// 刷新路径可视化
        /// </summary>
        /// <param name="pathId">路径ID</param>
        public void RefreshPath(string pathId)
        {
            lock (_lockObject)
            {
                if (_pathVisualizations.TryGetValue(pathId, out var visualization))
                {
                    BuildVisualization(visualization);
                    RequestViewRefresh();
                }
            }
        }

        /// <summary>
        /// 设置控制点可视化的显示状态
        /// </summary>
        /// <param name="pathId">路径ID</param>
        /// <param name="show">是否显示</param>
        public void SetControlVisualizationVisibility(string pathId, bool show)
        {
            lock (_lockObject)
            {
                if (_pathVisualizations.TryGetValue(pathId, out var visualization))
                {
                    if (visualization.ShowControlVisualization != show)
                    {
                        visualization.ShowControlVisualization = show;
                        RequestViewRefresh();
                    }
                }
            }
        }

        /// <summary>
        /// 切换控制点可视化的显示状态
        /// </summary>
        /// <param name="pathId">路径ID</param>
        public void ToggleControlVisualization(string pathId)
        {
            lock (_lockObject)
            {
                if (_pathVisualizations.TryGetValue(pathId, out var visualization))
                {
                    visualization.ShowControlVisualization = !visualization.ShowControlVisualization;
                    RequestViewRefresh();
                }
            }
        }

        /// <summary>
        /// 获取所有路径可视化对象
        /// </summary>
        /// <returns>所有路径可视化对象的列表</returns>
        public List<PathVisualization> GetAllPathVisualizations()
        {
            lock (_lockObject)
            {
                return _pathVisualizations.Values.ToList();
            }
        }

        /// <summary>
        /// 判断是否为网格可视化路径
        /// </summary>
        private bool IsGridVisualizationPath(string pathId)
        {
            return pathId != null && (
                pathId.StartsWith("grid_visualization_") ||
                pathId == "grid_visualization_all" ||
                pathId == "voxel_grid_visualization");  // 体素网格可视化
        }

        /// <summary>
        /// 刷新所有普通路径（排除网格可视化）
        /// </summary>
        private void RefreshNormalPaths()
        {
            lock (_lockObject)
            {
                var normalPathIds = _pathVisualizations.Keys
                    .Where(id => !IsGridVisualizationPath(id))
                    .ToList();

                foreach (var pathId in normalPathIds)
                {
                    if (_pathVisualizations.TryGetValue(pathId, out var visualization))
                    {
                        BuildVisualization(visualization);
                    }
                }

                if (normalPathIds.Count > 0)
                {
                    RequestViewRefresh();
                }
            }
        }

        /// <summary>
        /// 刷新所有网格路径
        /// </summary>
        private void RefreshGridPaths()
        {
            lock (_lockObject)
            {
                var gridPathIds = _pathVisualizations.Keys
                    .Where(id => IsGridVisualizationPath(id))
                    .ToList();

                foreach (var pathId in gridPathIds)
                {
                    if (_pathVisualizations.TryGetValue(pathId, out var visualization))
                    {
                        BuildPointMarkersOnly(visualization);
                    }
                }

                if (gridPathIds.Count > 0)
                {
                    RequestViewRefresh();
                }
            }
        }

        /// <summary>
        /// 移除路径
        /// </summary>
        /// <param name="pathId">路径ID</param>
        public void RemovePath(string pathId)
        {
            lock (_lockObject)
            {
                if (_pathVisualizations.Remove(pathId))
                {
                    RequestViewRefresh();
                }
            }
        }

        /// <summary>
        /// 渲染空轨基准路径
        /// </summary>
        /// <param name="railModelId">空轨模型ID</param>
        /// <param name="baselinePoints">基准路径点列表</param>
        public void RenderRailBaseline(string railModelId, List<Point3D> baselinePoints)
        {
            RenderRailBaseline(railModelId, baselinePoints, RenderStyleName.RailBaseline);
        }

        /// <summary>
        /// 按指定样式渲染基准路径。
        /// </summary>
        public void RenderRailBaseline(string railModelId, List<Point3D> baselinePoints, RenderStyleName renderStyleName)
        {
            if (string.IsNullOrEmpty(railModelId) || baselinePoints == null || baselinePoints.Count < 2)
            {
                LogManager.Warning($"[路径渲染] RenderRailBaseline参数无效: railModelId={railModelId}, points={(baselinePoints?.Count ?? 0)}");
                return;
            }

            try
            {
                // 先清除该模型的旧基准路径可视化
                ClearRailBaseline(railModelId);

                // 创建PathVisualization对象
                var visualization = new PathVisualization
                {
                    PathId = railModelId,
                    ShowControlVisualization = false, // 不显示控制点
                    LastUpdated = DateTime.Now
                };

                var renderStyle = GetRenderStyle(renderStyleName);

                // 创建连线标记
                for (int i = 0; i < baselinePoints.Count - 1; i++)
                {
                    var start = baselinePoints[i];
                    var end = baselinePoints[i + 1];

                    var lineMarker = new LineMarker
                    {
                        StartPoint = start,
                        EndPoint = end,
                        Color = renderStyle.Color,
                        Radius = GetLineRadius() * 0.2,
                        SegmentType = PathSegmentType.Straight,
                        FromIndex = i,
                        ToIndex = i + 1
                    };

                    visualization.PathLineMarkers.Add(lineMarker);
                }

                lock (_lockObject)
                {
                    _railBaselineVisualizations[railModelId] = visualization;
                }

                RequestViewRefresh();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径渲染] 渲染空轨基准路径失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 清除指定空轨的基准路径可视化
        /// </summary>
        /// <param name="railModelId">空轨模型ID</param>
        public void ClearRailBaseline(string railModelId)
        {
            if (string.IsNullOrEmpty(railModelId))
            {
                return;
            }

            lock (_lockObject)
            {
                if (_railBaselineVisualizations.Remove(railModelId))
                {
                    RequestViewRefresh();
                }
            }
        }

        /// <summary>
        /// 获取所有空轨基准路径
        /// </summary>
        /// <returns>所有空轨基准路径的字典</returns>
        public Dictionary<string, List<Point3D>> GetAllRailBaselinePaths()
        {
            lock (_lockObject)
            {
                var result = new Dictionary<string, List<Point3D>>();
                foreach (var kvp in _railBaselineVisualizations)
                {
                    var pathPoints = kvp.Value.PathLineMarkers.Select(m => m.StartPoint).ToList();
                    var lastMarker = kvp.Value.PathLineMarkers.LastOrDefault();
                    if (lastMarker != null)
                    {
                        pathPoints.Add(lastMarker.EndPoint);
                    }

                    result[kvp.Key] = pathPoints;
                }
                return result;
            }
        }

        /// <summary>
        /// 清除所有空轨基准路径可视化
        /// </summary>
        public void ClearAllRailBaselines()
        {
            lock (_lockObject)
            {
                int count = _railBaselineVisualizations.Count;
                _railBaselineVisualizations.Clear();
                if (count > 0)
                {
                    RequestViewRefresh();
                }
            }
        }

        /// <summary>
        /// 清空所有路径
        /// </summary>
        public void ClearAllPaths()
        {
            lock (_lockObject)
            {
                var count = _pathVisualizations.Count;
                _pathVisualizations.Clear();
                RequestViewRefresh();
            }
        }

        /// <summary>
        /// 清空路径，但保留指定的路径
        /// </summary>
        /// <param name="excludedPathIds">要保留的路径ID列表</param>
        public void ClearPathsExcept(params string[] excludedPathIds)
        {
            try
            {
                lock (_lockObject)
                {
                    // 防御性编程：处理空参数
                    if (excludedPathIds == null)
                    {
                        excludedPathIds = new string[0];
                    }

                    var excludedSet = new HashSet<string>(excludedPathIds.Where(id => !string.IsNullOrEmpty(id)));
                    var toRemove = _pathVisualizations.Keys.Where(id => !excludedSet.Contains(id)).ToList();

                    // 检查排除的路径是否实际存在
                    var existingExcluded = excludedSet.Where(id => _pathVisualizations.ContainsKey(id)).ToList();
                    var nonExistingExcluded = excludedSet.Where(id => !_pathVisualizations.ContainsKey(id)).ToList();

                    int removedCount = 0;
                    foreach (var pathId in toRemove)
                    {
                        if (_pathVisualizations.Remove(pathId))
                        {
                            removedCount++;
                        }
                    }

                    if (removedCount > 0)
                    {
                        RequestViewRefresh();
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[选择性清空] 清理路径时发生异常: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 构建路径可视化
        /// </summary>
        /// <param name="visualization">路径可视化对象</param>
        private void BuildVisualization(PathVisualization visualization)
        {
            // 清空现有标记
            visualization.PointMarkers.Clear();
            visualization.ControlLineMarkers.Clear();
            visualization.PathLineMarkers.Clear();
            visualization.TangentMarkers.Clear();
            visualization.ObjectSpaceMarkers.Clear();

            var points = visualization.PathRoute.Points;
            if (points.Count == 0) return;

            // 按索引排序点
            var sortedPoints = points.OrderBy(p => p.Index).ToList();

            // 构建点标记（所有控制点）
            foreach (var point in sortedPoints)
            {
                var pointMarker = CreatePointMarker(point);
                visualization.PointMarkers.Add(pointMarker);
            }

            // 构建控制点连线（用户意图，半透明）
            BuildControlLines(visualization, sortedPoints);

            // 地面路径使用曲线化后的路径（Edges）
            // 空中路径只显示控制点连线，不显示路径连线（除非启用通行空间可视化）
            if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail ||
                visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
            {
                // 空中路径：默认只显示控制点连线
                // 但如果启用了通行空间可视化，则构建路径连线以显示通行空间
                if (_showObjectSpace)
                {
                    string aerialSubTypeName = visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail ? "空轨" : "吊装";
                    BuildPathLines(visualization, sortedPoints);
                    LogManager.Debug($"[BuildVisualization] {aerialSubTypeName}路径已启用通行空间，构建路径连线");
                }
                else
                {
                    string aerialSubTypeName = visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail ? "空轨" : "吊装";
                    LogManager.Debug($"[BuildVisualization] {aerialSubTypeName}路径未启用通行空间，仅显示控制点连线");
                }
            }
            else if (visualization.PathRoute.Edges != null && visualization.PathRoute.Edges.Count > 0)
            {
                // 地面路径：使用曲线化后的路径
                BuildPathLines(visualization, sortedPoints);
            }

            // 如果路径未完成，添加灰色的原始终点标记
            if (!visualization.PathRoute.IsComplete && visualization.PathRoute.OriginalEndPoint != null)
            {
                var originalEndPoint = visualization.PathRoute.OriginalEndPoint;
                var unreachedStyle = GetRenderStyle(RenderStyleName.UnreachedEndPoint);
                var grayEndMarker = new CircleMarker
                {
                    Center = originalEndPoint,
                    Normal = GetHostUpVector(),
                    Radius = GetRadiusForPointType(PathPointType.EndPoint),
                    Color = unreachedStyle.Color, // 未到达终点颜色
                    Alpha = unreachedStyle.Alpha, // 透明度，统一管理
                    Filled = true,
                    PointType = PathPointType.EndPoint,
                    SequenceNumber = -1, // 特殊序号表示这是未到达的终点
                    CreatedTime = DateTime.Now
                };
                visualization.PointMarkers.Add(grayEndMarker);
            }

            visualization.LastUpdated = DateTime.Now;
        }

        /// <summary>
        /// 构建控制点连线（用户意图，半透明）
        /// </summary>
        /// <param name="visualization">路径可视化对象</param>
        /// <param name="sortedPoints">排序后的路径点列表</param>
        private void BuildControlLines(PathVisualization visualization, List<PathPoint> sortedPoints)
        {
            // 根据路径类型选择连线样式
            RenderStyleName lineStyleName = RenderStyleName.PreviewLine;
            if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail ||
                visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
            {
                lineStyleName = RenderStyleName.HoistingLine;
            }

            // 构建控制点之间的连线（所有相邻控制点）
            for (int i = 0; i < sortedPoints.Count - 1; i++)
            {
                var currentPoint = sortedPoints[i];
                var nextPoint = sortedPoints[i + 1];

                var controlLineMarker = new LineMarker
                {
                    StartPoint = currentPoint.Position,
                    EndPoint = nextPoint.Position,
                    Color = GetRenderStyle(lineStyleName).Color,
                    Radius = GetLineRadius() * 0.5,  // 比实际路径细
                    SegmentType = PathSegmentType.Straight,
                    FromIndex = currentPoint.Index,
                    ToIndex = nextPoint.Index
                };
                visualization.ControlLineMarkers.Add(controlLineMarker);
            }
        }

        /// <summary>
        /// 计算通行空间参数（高度、宽度、颜色、透明度、垂直偏移）
        /// </summary>
        /// <param name="visualization">路径可视化对象</param>
        /// <param name="isVerticalSegment">是否是垂直段（仅用于吊装路径）</param>
        /// <param name="isTurn90Horizontal">是否是与初始方向垂直的水平段（吊装路径转折90度）</param>
        /// <param name="isFirstOrLastSegment">是否是第一个或最后一个线段（起吊/下降段）</param>
        /// <returns>通行空间参数元组</returns>
        private (double height, double width, Color lineColor, double lineOpacity, double verticalOffset)
            CalculatePassageSpaceParameters(PathVisualization visualization, bool isVerticalSegment = false, bool isTurn90Horizontal = false, bool isFirstOrLastSegment = false)
        {
            // 🔥 验证通行空间参数是否已正确设置
            if (_passageAcrossPath <= 0 || _passageNormalToPath <= 0 || _passageAlongPath <= 0)
            {
                throw new InvalidOperationException(
                    $"[渲染错误] 通行空间参数未正确设置: " +
                    $"_passageAcrossPath={_passageAcrossPath:F4}, " +
                    $"_passageNormalToPath={_passageNormalToPath:F4}, " +
                    $"_passageAlongPath={_passageAlongPath:F4}. " +
                    $"请确保在渲染前调用 SetPassageSpaceParameters()");
            }

            double height;
            double width;
            Color lineColor;
            double lineOpacity;

            if (_showObjectSpace)
            {
                // 通行空间模式：根据路径类型和段类型计算通行空间尺寸
                // _passage* 和 _object* 字段已经是模型单位（由 SetPassageSpaceParameters 转换）
                if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
                {
                    // 吊装路径：根据段类型和方向设置尺寸
                    // 默认：width=物体宽度（垂直于路径），height=物体高度/长度
                    width = _passageAcrossPath;
                    height = isVerticalSegment ? _objectLength : _objectHeight;
                    
                    // 🔥 水平段转折90度特殊处理：width改用物体长度
                    if (!isVerticalSegment && isTurn90Horizontal)
                    {
                        width = _objectLength;
                    }
                }
                else
                {
                    // 其他路径类型
                    width = _passageAcrossPath;
                    height = _passageNormalToPath;
                }

                var renderStyle = GetRenderStyle(RenderStyleName.ObjectSpace);
                lineColor = renderStyle.Color;
                lineOpacity = renderStyle.Alpha;
            }
            else if (_showPathLines)
            {
                // RibbonLine 模式：使用较低的带状高度
                // GetLineRadius() 返回模型单位，直接乘以系数
                height = GetLineRadius() * 0.1;
                width = _passageAcrossPath; // 已经是模型单位
                LogManager.Debug($"[CalculatePassageSpaceParameters] RibbonLine模式: _passageAcrossPath={_passageAcrossPath:F4}, width={width:F4}, height={height:F4}");
                var renderStyle = GetRenderStyle(RenderStyleName.Line);
                lineColor = renderStyle.Color;
                lineOpacity = renderStyle.Alpha;
            }
            else
            {
                // StandardLine 模式：不需要高度和宽度（圆柱体）
                height = 0;
                width = 0;
                var renderStyle = GetRenderStyle(RenderStyleName.Line);
                lineColor = renderStyle.Color;
                lineOpacity = renderStyle.Alpha;
            }

            // 计算通行空间的垂直偏移（根据路径类型）
            double verticalOffset = 0;
                if (_showObjectSpace)
                {
                    if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Ground)
                    {
                        // 地面路径：路径点是地面位置，通行空间底面在地面，中心需要向上偏移半个高度
                        verticalOffset = ResolveGroundPathObjectSpaceVerticalOffset(height);
                    }
                    else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Free)
                    {
                        // 自由路径：路径点即物体几何中心，通行空间以路径点为中心，无偏移
                        verticalOffset = 0;
                    }
                    else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail)
                    {
                    verticalOffset = RailPathPoseHelper.GetObjectSpaceCenterZOffset(
                        visualization.PathRoute,
                        height);
                }
                else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
                {
                    // 吊装路径：根据段类型设置偏移
                    if (isVerticalSegment)
                    {
                        // 所有垂直段（起吊、下降、层间过渡）：顶面在高点，不需要偏移
                        // 起吊/下降段：底面在地面（起点/终点）
                        // 层间过渡：底面在低点以下物体长度（通过延伸实现）
                        verticalOffset = 0;
                    }
                    else
                    {
                        // 水平段：顶面中心对齐路径点，向下偏移半个高度
                        verticalOffset = -height / 2.0;
                    }
                }
            }

            return (height, width, lineColor, lineOpacity, verticalOffset);
        }

        /// <summary>
        /// 构建路径连线（使用Edges，包含直线段和圆弧段）
        /// </summary>
        /// <param name="visualization">路径可视化对象</param>
        /// <param name="sortedPoints">排序后的路径点列表</param>
        private void BuildPathLines(PathVisualization visualization, List<PathPoint> sortedPoints)
        {
            var edges = visualization.PathRoute.Edges;

            // 处理 Edges 为空的情况（如吊装路径未经过曲线化）
            if (edges == null || edges.Count == 0)
            {
                BuildDirectPathLines(visualization, sortedPoints);
                return;
            }

            // 1. 收集在路径上的控制点ID
            var onPathPointIds = new HashSet<string>();
            foreach (var edge in edges)
            {
                if (!string.IsNullOrEmpty(edge.StartPointId))
                    onPathPointIds.Add(edge.StartPointId);
                if (!string.IsNullOrEmpty(edge.EndPointId))
                    onPathPointIds.Add(edge.EndPointId);
            }

            // 2. 更新点标记的透明度
            foreach (var pointMarker in visualization.PointMarkers)
            {
                var point = sortedPoints.FirstOrDefault(p => p.Id == pointMarker.PathPoint?.Id);
                if (point != null)
                {
                    bool isOnPath = onPathPointIds.Contains(point.Id);
                    pointMarker.IsOffPath = !isOnPath;
                }
            }

            // 获取单位转换系数
            double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();

            // 计算通行空间参数
            var (height, width, lineColor, lineOpacity, verticalOffset) = 
                CalculatePassageSpaceParameters(visualization);

            // 3. 构建路径连线（Edges包含直线段和圆弧段）
            foreach (var edge in edges)
            {
                if (edge.SegmentType == PathSegmentType.Straight)
                {
                    // 直线段：检查SampledPoints是否有效
                    if (edge.SampledPoints != null && edge.SampledPoints.Count >= 2)
                    {
                        var startPoint = edge.SampledPoints.First();
                        var endPoint = edge.SampledPoints.Last();

                        // 计算长方体的轴向量（right和up向量）
                        var preferredUp = ResolveObjectSpaceUpDirection(visualization.PathRoute);
                        var (right, up) = CalculateCuboidAxes(startPoint, endPoint, preferredUp);

                        // 根据路径类型调整起点和终点位置
                        // 关键修复：垂直偏移应该沿着长方体的轴线方向（up向量）平移
                        Point3D adjustedStartPoint;
                        Point3D adjustedEndPoint;

                        if (_showObjectSpace && visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail)
                        {
                            adjustedStartPoint = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
                                visualization.PathRoute,
                                startPoint,
                                startPoint,
                                endPoint,
                                height);
                            adjustedEndPoint = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
                                visualization.PathRoute,
                                endPoint,
                                startPoint,
                                endPoint,
                                height);
                        }
                        else if (_showObjectSpace && Math.Abs(verticalOffset) > 0.001)
                        {
                            // 非 Rail 通行空间必须沿宿主 up 偏移，不能写死世界 Z。
                            var hostUp = GetHostUpVector();
                            adjustedStartPoint = ApplyVerticalOffset(startPoint, hostUp, verticalOffset);
                            adjustedEndPoint = ApplyVerticalOffset(endPoint, hostUp, verticalOffset);
                        }
                        else
                        {
                            // 其他情况，不调整起点和终点位置
                            adjustedStartPoint = startPoint;
                            adjustedEndPoint = endPoint;
                        }

                        // 🔥 地面/空轨路径水平段：起点和终点向路径方向延伸半个物体尺寸（仅通行空间）
                        if (_showObjectSpace)
                        {
                            ExtendLineSegmentForObjectSpace(ref adjustedStartPoint, ref adjustedEndPoint, _passageAlongPath);
                        }

                        var lineMarker = new LineMarker
                        {
                            StartPoint = adjustedStartPoint,
                            EndPoint = adjustedEndPoint,
                            Color = lineColor,
                            Radius = GetLineRadius(),
                            SegmentType = PathSegmentType.Straight,
                            SampledPoints = edge.SampledPoints,
                            Height = height, // 根据模式设置高度
                            Width = width, // 根据模式设置宽度
                            Opacity = lineOpacity, // 根据模式设置透明度
                            UpDirection = preferredUp
                        };
                        visualization.PathLineMarkers.Add(lineMarker);
                    }
                }
                else if (edge.SegmentType == PathSegmentType.Arc && edge.Trajectory != null)
                {
                    // 圆弧段：检查Trajectory是否有效

                    // 检查是否发生安全截断
                    bool hasSafetyTruncation = edge.Trajectory.ActualRadius < edge.Trajectory.RequestedRadius;

                    // 如果发生安全截断，使用安全警告样式
                    Color arcLineColor = lineColor;
                    double arcLineOpacity = lineOpacity;
                    if (hasSafetyTruncation)
                    {
                        var warningStyle = GetRenderStyle(RenderStyleName.SafetyWarning);
                        arcLineColor = warningStyle.Color;
                        arcLineOpacity = warningStyle.Alpha;
                    }

                    var startPoint = edge.Trajectory.Ts;
                    var endPoint = edge.Trajectory.Te;

                    // 计算长方体的轴向量（right和up向量）
                    var preferredUp = ResolveObjectSpaceUpDirection(visualization.PathRoute);
                    var (right, up) = CalculateCuboidAxes(startPoint, endPoint, preferredUp);

                    // 根据路径类型调整起点和终点位置
                    // 关键修复：垂直偏移应该沿着长方体的轴线方向（up向量）平移
                    Point3D adjustedStartPoint;
                    Point3D adjustedEndPoint;
                    List<Point3D> adjustedSampledPoints;

                    if (_showObjectSpace && visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail)
                    {
                        adjustedStartPoint = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
                            visualization.PathRoute,
                            startPoint,
                            startPoint,
                            endPoint,
                            height);
                        adjustedEndPoint = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
                            visualization.PathRoute,
                            endPoint,
                            startPoint,
                            endPoint,
                            height);

                        adjustedSampledPoints = new List<Point3D>();
                        if (edge.SampledPoints != null)
                        {
                            for (int sampleIndex = 0; sampleIndex < edge.SampledPoints.Count; sampleIndex++)
                            {
                                var currentPoint = edge.SampledPoints[sampleIndex];
                                var previousPoint = sampleIndex > 0 ? edge.SampledPoints[sampleIndex - 1] : currentPoint;
                                var nextPoint = sampleIndex < edge.SampledPoints.Count - 1 ? edge.SampledPoints[sampleIndex + 1] : currentPoint;
                                adjustedSampledPoints.Add(RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
                                    visualization.PathRoute,
                                    currentPoint,
                                    previousPoint,
                                    nextPoint,
                                    height));
                            }
                        }
                    }
                    else if (_showObjectSpace && Math.Abs(verticalOffset) > 0.001)
                    {
                        // 非 Rail 通行空间必须沿宿主 up 偏移，不能写死世界 Z。
                        var hostUp = GetHostUpVector();
                        adjustedStartPoint = ApplyVerticalOffset(startPoint, hostUp, verticalOffset);
                        adjustedEndPoint = ApplyVerticalOffset(endPoint, hostUp, verticalOffset);

                        // 对 SampledPoints 应用同一宿主 up 方向偏移。
                        adjustedSampledPoints = new List<Point3D>();
                        if (edge.SampledPoints != null)
                        {
                            foreach (var point in edge.SampledPoints)
                            {
                                adjustedSampledPoints.Add(ApplyVerticalOffset(point, hostUp, verticalOffset));
                            }
                        }
                    }
                    else
                    {
                        // 其他情况，不调整起点和终点位置
                        adjustedStartPoint = startPoint;
                        adjustedEndPoint = endPoint;
                        adjustedSampledPoints = edge.SampledPoints;
                    }

                    // 🔥 圆弧段：起点和终点向路径方向延伸半个物体尺寸（仅通行空间）
                    if (_showObjectSpace)
                    {
                        ExtendLineSegmentForObjectSpace(ref adjustedStartPoint, ref adjustedEndPoint, _passageAlongPath);
                    }

                    var arcMarker = new LineMarker
                    {
                        StartPoint = adjustedStartPoint,
                        EndPoint = adjustedEndPoint,
                        Color = arcLineColor,
                        Radius = GetLineRadius(),
                        SegmentType = PathSegmentType.Arc,
                        Trajectory = edge.Trajectory,
                        SampledPoints = adjustedSampledPoints,
                        Height = height, // 根据模式设置高度
                        Width = width, // 根据模式设置宽度
                        Opacity = arcLineOpacity, // 根据模式设置透明度
                        UpDirection = preferredUp
                    };
                    visualization.PathLineMarkers.Add(arcMarker);

                    // 添加切点标记（路径线模式才添加）
                    if (_showPathLines)
                    {
                        AddTangentMarkers(visualization, edge);
                    }
                }
            }
        }

        /// <summary>
        /// 计算长方体的轴向量（right和up向量）
        /// </summary>
        /// <param name="startPoint">路径段起点</param>
        /// <param name="endPoint">路径段终点</param>
        /// <param name="horizontalDirection">水平段方向向量（用于垂直路径渲染时确定通行空间方向）</param>
        /// <returns>元组（right向量，up向量）</returns>
        private (Vector3D right, Vector3D up) CalculateCuboidAxes(Point3D startPoint, Point3D endPoint, Vector3D upReference = null, Vector3D horizontalDirection = null)
        {
            return ObjectSpaceOrientationHelper.CalculateAxes(
                startPoint,
                endPoint,
                upReference ?? GetHostUpVector(),
                horizontalDirection);
        }

        /// <summary>
        /// 直接使用路径点构建直线连线（用于吊装路径等未曲线化的路径）
        /// </summary>
        /// <param name="visualization">路径可视化对象</param>
        /// <param name="sortedPoints">排序后的路径点列表</param>
        private void BuildDirectPathLines(PathVisualization visualization, List<PathPoint> sortedPoints)
        {
            if (sortedPoints == null || sortedPoints.Count < 2)
                return;

            // 获取单位转换系数
            double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();

            // 对于吊装路径，预先计算水平段的方向向量
            Vector3D horizontalDirection = null;
            if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting &&
                sortedPoints.Count >= 3)
            {
                var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
                horizontalDirection = ToVector3D(HoistingCoordinateHelper.GetHorizontalDirection3(
                    ToVector3(sortedPoints[1].Position),
                    ToVector3(sortedPoints[2].Position),
                    adapter));
            }

            // 直接使用路径点构建直线连线
            for (int i = 0; i < sortedPoints.Count - 1; i++)
            {
                var startPoint = sortedPoints[i];
                var endPoint = sortedPoints[i + 1];
                double segmentDx = endPoint.Position.X - startPoint.Position.X;
                double segmentDy = endPoint.Position.Y - startPoint.Position.Y;
                double segmentDz = endPoint.Position.Z - startPoint.Position.Z;
                double segmentLength = Math.Sqrt(
                    segmentDx * segmentDx +
                    segmentDy * segmentDy +
                    segmentDz * segmentDz);

                if (segmentLength < 0.001)
                {
                    LogManager.Debug($"[路径渲染] 跳过零长度路径段: 索引={i}, 路径={visualization.PathRoute?.Name}");
                    continue;
                }

                // 对于吊装路径，判断是否是垂直段和起吊/下降段
                bool isVerticalSegment = false;
                bool isFirstOrLastSegment = false;
                if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
                {
                    // 吊装路径：支持动态数量的路径点
                    // 路径点结构：
                    //   点0（起吊点）：地面位置
                    //   点1（提升点）：悬挂点
                    //   点2...点N-2：中间悬挂点（用户添加的转向点）
                    //   点N-1（下降点）：悬挂点
                    //   点N（落地点）：地面位置
                    //
                    // 线段结构：
                    //   线段0：起吊段（垂直）
                    //   线段1...线段N-2：平移段（水平）
                    //   线段N-1：下降段（垂直）

                    int totalSegments = sortedPoints.Count - 1;
                    int firstSegment = 0;      // 起吊段
                    int lastSegment = totalSegments - 1;  // 下降段

                    // 沿宿主 up 判断垂直段，避免把世界 Z 误当成向上轴
                    var hostUp = GetHostUpVector();
                    double upDelta = segmentDx * hostUp.X + segmentDy * hostUp.Y + segmentDz * hostUp.Z;
                    double horizontalDist = Math.Sqrt(Math.Max(0.0, segmentLength * segmentLength - upDelta * upDelta));
                    // 如果沿宿主 up 的变化占主导（垂直段），或者是第一个/最后一个线段
                    bool isZDominant = Math.Abs(upDelta) > horizontalDist * 2.0;
                    
                    // 第一个线段和最后一个线段是起吊/下降段
                    // 中间的垂直段是层间过渡
                    isVerticalSegment = (i == firstSegment || i == lastSegment || isZDominant);
                    
                    // 检测是否是第一个或最后一个线段（起吊/下降段）
                    isFirstOrLastSegment = (i == firstSegment || i == lastSegment);
                }

                // 计算通行空间参数（根据段类型）
                // 对于吊装路径水平段，检测是否转折90度
                bool isTurn90Horizontal = false;
                if (!isVerticalSegment && visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting && horizontalDirection != null)
                {
                    var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
                    var currentDirection = ToVector3D(HoistingCoordinateHelper.GetHorizontalDirection3(
                        ToVector3(startPoint.Position),
                        ToVector3(endPoint.Position),
                        adapter));
                    var currentLength = Math.Sqrt(
                        currentDirection.X * currentDirection.X +
                        currentDirection.Y * currentDirection.Y +
                        currentDirection.Z * currentDirection.Z);
                    if (currentLength > 0.001)
                    {
                        // 计算与初始水平段方向的点积
                        double dotProduct =
                            currentDirection.X * horizontalDirection.X +
                            currentDirection.Y * horizontalDirection.Y +
                            currentDirection.Z * horizontalDirection.Z;
                        // 点积接近0表示垂直（90度转折）
                        isTurn90Horizontal = Math.Abs(dotProduct) < 0.1;
                    }
                }
                
                var (height, width, lineColor, lineOpacity, verticalOffset) =
                    CalculatePassageSpaceParameters(visualization, isVerticalSegment, isTurn90Horizontal, isFirstOrLastSegment);

                // 计算长方体的轴向量（right和up向量）
                var preferredUp = ResolveObjectSpaceUpDirection(visualization.PathRoute);
                var (right, up) = CalculateCuboidAxes(startPoint.Position, endPoint.Position, preferredUp, horizontalDirection);

                // 根据路径类型调整起点和终点位置
                // 关键修复：垂直偏移应该沿着长方体的轴线方向（up向量）平移，而不是简单地添加到Z坐标上
                Point3D adjustedStartPoint;
                Point3D adjustedEndPoint;

                if (_showObjectSpace && visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail)
                {
                    adjustedStartPoint = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
                        visualization.PathRoute,
                        startPoint.Position,
                        startPoint.Position,
                        endPoint.Position,
                        height);
                    adjustedEndPoint = RailPathPoseHelper.ResolveObjectSpaceCenterPosition(
                        visualization.PathRoute,
                        endPoint.Position,
                        startPoint.Position,
                        endPoint.Position,
                        height);
                }
                else if (_showObjectSpace && Math.Abs(verticalOffset) > 0.001)
                {
                    // 非 Rail 通行空间统一沿宿主 up 方向偏移，不能再默认世界 Z。
                    var hostUp = GetHostUpVector();
                    adjustedStartPoint = ApplyVerticalOffset(startPoint.Position, hostUp, verticalOffset);
                    adjustedEndPoint = ApplyVerticalOffset(endPoint.Position, hostUp, verticalOffset);
                }
                else
                {
                    // 其他情况，不调整起点和终点位置
                    adjustedStartPoint = startPoint.Position;
                    adjustedEndPoint = endPoint.Position;
                }

                // 🔥 通行空间包裹调整：水平段和层间垂直过渡延伸以完全包裹物体（仅通行空间）
                if (_showObjectSpace)
                {
                    if (!isVerticalSegment)
                    {
                        // 水平段：沿路径方向延伸
                        double alongPathSize = _passageAlongPath;
                        if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
                        {
                            alongPathSize = isTurn90Horizontal ? _passageAcrossPath : _objectLength;
                        }
                        ExtendLineSegmentForObjectSpace(ref adjustedStartPoint, ref adjustedEndPoint, alongPathSize);
                    }
                    else if (isVerticalSegment && !isFirstOrLastSegment)
                    {
                        // 层间垂直过渡：通行空间总高度 = 层间路径高度 + 物体高度
                        // 顶面中心 = 路径高点，底面中心 = 路径低点向下物体高度
                        var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
                        bool isStartHigher =
                            HoistingCoordinateHelper.GetElevation(adjustedStartPoint, adapter) >
                            HoistingCoordinateHelper.GetElevation(adjustedEndPoint, adapter);
                        
                        if (isStartHigher)
                        {
                            adjustedEndPoint = HoistingCoordinateHelper.ExtendVerticalTransitionForObjectSpace(
                                adjustedEndPoint,
                                _objectHeight,
                                isLowerPoint: true,
                                adapter: adapter);
                        }
                        else
                        {
                            adjustedStartPoint = HoistingCoordinateHelper.ExtendVerticalTransitionForObjectSpace(
                                adjustedStartPoint,
                                _objectHeight,
                                isLowerPoint: true,
                                adapter: adapter);
                        }
                    }
                    // 起吊/下降段不需要延伸，因为底面对齐地面
                }

                var lineMarker = new LineMarker
                {
                    StartPoint = adjustedStartPoint,
                    EndPoint = adjustedEndPoint,
                    Color = lineColor,
                    Radius = GetLineRadius(),
                    SegmentType = PathSegmentType.Straight,
                    FromIndex = startPoint.Index,
                    ToIndex = endPoint.Index,
                    Height = height,
                    Width = width,
                    Opacity = lineOpacity,
                    HorizontalDirection = horizontalDirection, // 设置水平段方向向量
                    UpDirection = preferredUp
                };
                visualization.PathLineMarkers.Add(lineMarker);
            }
        }

        /// <summary>
        /// 计算垂直偏移后的点
        /// </summary>
        /// <param name="point">原始点</param>
        /// <param name="up">长方体的轴线方向（高度向量）</param>
        /// <param name="verticalOffset">垂直偏移量</param>
        /// <returns>偏移后的点</returns>
        private Point3D ApplyVerticalOffset(Point3D point, Vector3D up, double verticalOffset)
        {
            if (Math.Abs(verticalOffset) < 0.001)
            {
                return point;
            }

            var normalizedUp = Normalize(up);
            if (normalizedUp.X == 0.0 && normalizedUp.Y == 0.0 && normalizedUp.Z == 0.0)
            {
                return point;
            }

            return new Point3D(
                point.X + normalizedUp.X * verticalOffset,
                point.Y + normalizedUp.Y * verticalOffset,
                point.Z + normalizedUp.Z * verticalOffset
            );
        }

        private static System.Numerics.Vector3 ToVector3(Point3D point)
        {
            return new System.Numerics.Vector3((float)point.X, (float)point.Y, (float)point.Z);
        }

        private static Vector3D ToVector3D(System.Numerics.Vector3 vector)
        {
            return new Vector3D(vector.X, vector.Y, vector.Z);
        }

        private static Vector3D GetHostUpVector()
        {
            var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
            return Normalize(adapter.FromCanonicalVector(HostCoordinateAdapter.CanonicalUp));
        }

        private static Vector3D Cross(Vector3D a, Vector3D b)
        {
            return new Vector3D(
                a.Y * b.Z - a.Z * b.Y,
                a.Z * b.X - a.X * b.Z,
                a.X * b.Y - a.Y * b.X);
        }

        private static Vector3D Normalize(Vector3D vector)
        {
            double lengthSquared = vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z;
            if (lengthSquared < 1e-9)
            {
                return new Vector3D(0, 0, 0);
            }

            double length = Math.Sqrt(lengthSquared);
            return new Vector3D(vector.X / length, vector.Y / length, vector.Z / length);
        }

        private static Point3D ApplyVectorOffset(Point3D point, Vector3D direction, double distance)
        {
            var normalized = Normalize(direction);
            return new Point3D(
                point.X + normalized.X * distance,
                point.Y + normalized.Y * distance,
                point.Z + normalized.Z * distance);
        }

        private static (Vector3D axis1, Vector3D axis2) GetHostPlanarAxes(Vector3D hostUp)
        {
            var normalizedUp = Normalize(hostUp);
            var reference = Math.Abs(normalizedUp.X) > 0.9
                ? new Vector3D(0, 1, 0)
                : new Vector3D(1, 0, 0);

            double projection = reference.X * normalizedUp.X + reference.Y * normalizedUp.Y + reference.Z * normalizedUp.Z;
            var axis1 = Normalize(new Vector3D(
                reference.X - projection * normalizedUp.X,
                reference.Y - projection * normalizedUp.Y,
                reference.Z - projection * normalizedUp.Z));

            if (axis1.X == 0 && axis1.Y == 0 && axis1.Z == 0)
            {
                axis1 = new Vector3D(0, 0, 1);
            }

            var axis2 = Normalize(Cross(normalizedUp, axis1));
            return (axis1, axis2);
        }

        /// <summary>
        /// 添加切点标记
        /// </summary>
        /// <param name="visualization">路径可视化对象</param>
        /// <param name="edge">路径边</param>
        private void AddTangentMarkers(PathVisualization visualization, PathEdge edge)
        {
            if (edge.Trajectory == null) return;

            // 使用统一样式
            var tangentStyle = GetRenderStyle(RenderStyleName.TangentPoint);
            var tangentColor = tangentStyle.Color;

            // 路径宽度基准值（柱状和带状都是 GetLineRadius() * 2）
            var pathWidth = GetLineRadius() * 2;

            // 切点半径：路径半径的一半（切点直径 = 路径宽度的一半）
            var tangentRadius = GetLineRadius() * 0.5;

            // 切点高度：路径宽度的一半
            var tangentHeight = pathWidth * 0.5;

            // 进入切点Ts
            var tsMarker = new SquareMarker
            {
                Center = edge.Trajectory.Ts,
                Normal = GetHostUpVector(),
                Size = tangentRadius * 2, // 直径
                Height = tangentHeight, // 高度
                Color = tangentColor,
                Alpha = 0.8, // 80%透明度
                EdgeId = edge.Id,
                TangentType = TangentPointType.EntryTangent
            };
            visualization.TangentMarkers.Add(tsMarker);

            // 退出切点Te
            var teMarker = new SquareMarker
            {
                Center = edge.Trajectory.Te,
                Normal = GetHostUpVector(),
                Size = tangentRadius * 2, // 直径
                Height = tangentHeight, // 高度
                Color = tangentColor,
                Alpha = 0.8, // 80%透明度
                EdgeId = edge.Id,
                TangentType = TangentPointType.ExitTangent
            };
            visualization.TangentMarkers.Add(teMarker);
        }

        /// <summary>
        /// 创建物体通行空间标记
        /// </summary>
        /// <param name="fromPoint">起点</param>
        /// <param name="toPoint">终点</param>
        /// <returns>物体通行空间标记</returns>
        private ObjectSpaceMarker CreateObjectSpaceMarker(PathPoint fromPoint, PathPoint toPoint)
        {
            var style = GetRenderStyle(RenderStyleName.ObjectSpace);
            return new ObjectSpaceMarker
            {
                StartPoint = fromPoint.Position,
                EndPoint = toPoint.Position,
                Width = _passageAcrossPath,  // 直接使用模型单位
                Height = _passageNormalToPath,    // 直接使用模型单位
                Color = style.Color, // 物体通行空间颜色
                Alpha = style.Alpha, // 透明度，统一管理
                FromIndex = fromPoint.Index,
                ToIndex = toPoint.Index
            };
        }

        /// <summary>
        /// 创建点标记
        /// </summary>
        /// <param name="point">路径点</param>
        /// <returns>圆形标记</returns>
        private CircleMarker CreatePointMarker(PathPoint point)
        {
            // 检查是否是网格/体素可视化点（通过名称判断）
            bool isGridVisualization = point.Name.StartsWith("网格(") || point.Name.StartsWith("网格_") ||
                                      point.Name.StartsWith("体素(");  // 体素点

            // 确定网格点样式（颜色+透明度）
            RenderStyle gridStyle = new RenderStyle(Color.White, 1.0); // 默认样式
            if (isGridVisualization)
            {
                // 根据网格类型确定样式
                if (point.Name.Contains("空洞"))
                {
                    gridStyle = GetRenderStyle(RenderStyleName.GridUnknown);
                }
                else if (point.Name.Contains("障碍") || point.Name.Contains("Obstacle"))
                {
                    gridStyle = GetRenderStyle(RenderStyleName.GridObstacle);
                }
                else if (point.Name.Contains("通道") || point.Name.Contains("Channel") || point.Name.Contains("开放"))
                {
                    gridStyle = GetRenderStyle(RenderStyleName.GridChannel);
                }
                // 也可以通过Notes字段检查
                else if (!string.IsNullOrEmpty(point.Notes) && point.Notes.StartsWith("GridType:"))
                {
                    var gridTypeStr = point.Notes.Substring(9); // 去掉"GridType:"前缀
                    if (gridTypeStr == "空洞")
                        gridStyle = GetRenderStyle(RenderStyleName.GridUnknown);
                    else if (gridTypeStr == "障碍物")
                        gridStyle = GetRenderStyle(RenderStyleName.GridObstacle);
                    else
                        gridStyle = GetRenderStyle(RenderStyleName.GridChannel);
                }

                // 门网格点使用50%透明度覆盖默认透明度
                if (point.Name.Contains("门"))
                {
                    gridStyle = new RenderStyle(gridStyle.Color, 0.5);
                }
            }

            return new CircleMarker
            {
                Center = point.Position,
                Normal = GetHostUpVector(),
                Radius = point.ResolveVisualizationRadius(
                    isGridVisualization ? GetRadiusForGridVisualization() : GetRadiusForPointType(point.Type)),
                Color = isGridVisualization ? gridStyle.Color : GetColorForPointType(point.Type),
                Alpha = isGridVisualization ? gridStyle.Alpha : 1.0,
                Filled = true,
                PointType = point.Type,
                GridPointType = isGridVisualization ? _gridPointType : GridPointType.Sphere, // 网格点使用配置的类型，其他点使用球形
                SequenceNumber = point.Index, // 使用Index而不是任意序号
                CreatedTime = DateTime.Now
            };
        }

        /// <summary>
        /// 获取网格可视化小球的半径（比正常路径点小）
        /// </summary>
        /// <returns>网格可视化半径</returns>
        private double GetRadiusForGridVisualization()
        {
            // 使用标准尺寸的1/5作为网格点尺寸
            double standardRadiusInMeters = GetStandardRadiusInMeters();
            double radiusInMeters = standardRadiusInMeters / 5.0;

            double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
            return radiusInMeters * metersToModelUnits;
        }

        /// <summary>
        /// 设置当前网格大小（米），用于自适应点大小计算
        /// </summary>
        /// <param name="gridSizeInMeters">网格大小（米）</param>
        public void SetGridSize(double gridSizeInMeters)
        {
            _currentGridSizeInMeters = gridSizeInMeters;
        }

        /// <summary>
        /// 设置物体参数（从PathPlanningManager同步）
        /// </summary>
        /// <summary>
        /// 设置通行空间参数 - 外部传入模型单位，内部直接使用
        /// </summary>
        /// <param name="passageAcrossPath">垂直于路径方向的通行空间尺寸（模型单位）</param>
        /// <param name="passageNormalToPath">法线方向的通行空间尺寸（模型单位）</param>
        /// <param name="passageAlongPath">沿路径方向的通行空间尺寸（模型单位）</param>
        /// <param name="passageNormalToPathVertical">垂直段的高度（物体长度 + 2×安全间隙，模型单位）</param>
        /// <param name="passageNormalToPathHorizontal">水平段的高度（物体高度 + 2×安全间隙，模型单位）</param>
        public void SetPassageSpaceParameters(
            double passageAcrossPath,
            double passageNormalToPath,
            double passageAlongPath,
            double passageNormalToPathVertical,
            double passageNormalToPathHorizontal)
        {
            // 直接存储模型单位（调用方已转换）
            _passageAlongPath = passageAlongPath;
            _passageAcrossPath = passageAcrossPath;
            _passageNormalToPath = passageNormalToPath;

            // 保存垂直段和水平段的高度（用于吊装路径分段渲染）
            _objectLength = passageNormalToPathVertical;
            _objectHeight = passageNormalToPathHorizontal;

            // 参数改变时刷新所有普通路径（因为RibbonLine模式也使用物体宽度）
            RefreshNormalPaths();
        }

        internal static double ResolveGroundPathObjectSpaceVerticalOffset(double objectSpaceHeight)
        {
            return objectSpaceHeight / 2.0;
        }

        #region 颜色管理

        /// <summary>
        /// 根据样式名称获取对应的渲染样式（颜色+透明度）
        /// </summary>
        /// <param name="styleName">样式名称</param>
        /// <returns>对应的渲染样式</returns>
        private RenderStyle GetRenderStyle(RenderStyleName styleName)
        {
            switch (styleName)
            {
                case RenderStyleName.StartPoint:
                    return new RenderStyle(Color.FromByteRGB(76, 175, 80), 0.9); // Material Green起点，10%透明

                case RenderStyleName.EndPoint:
                    return new RenderStyle(Color.FromByteRGB(244, 67, 54), 0.9); // Material Red终点，10%透明

                case RenderStyleName.WayPoint:
                    return new RenderStyle(Color.FromByteRGB(33, 150, 243), 0.9); // Material Blue路径点，10%透明

                case RenderStyleName.Line:
                    return new RenderStyle(Color.FromByteRGB(255, 152, 0), 0.8); // Material Orange连线，20%透明

                case RenderStyleName.ObjectSpace:
                {
                    // 从配置读取通行空间透明度，默认为0.4（40%不透明，60%透明）
                    double opacity = ConfigManager.Instance.Current.Visualization.PassageSpaceOpacity;
                    // 确保透明度在有效范围内
                    opacity = Math.Max(0.0, Math.Min(1.0, opacity));
                    return new RenderStyle(Color.FromByteRGB(129, 199, 132), opacity); // Material Light Green通行空间
                }
                case RenderStyleName.PreviewPoint:
                    return new RenderStyle(Color.White, 0.7); // 白色预览点，30%透明

                case RenderStyleName.PreviewLine:
                    return new RenderStyle(Color.FromByteRGB(128, 128, 128), 0.5); // 灰色预览连线，50%透明

                case RenderStyleName.UnreachedEndPoint:
                    return new RenderStyle(Color.FromByteRGB(139, 0, 0), 0.7); // 深红色未到达终点，30%透明

                case RenderStyleName.GridChannel:
                    return new RenderStyle(Color.FromByteRGB(129, 199, 132), 0.8); // Material Light Green网格通道，20%透明

                case RenderStyleName.GridObstacle:
                    return new RenderStyle(Color.FromByteRGB(117, 117, 117), 0.8); // Material Grey网格障碍物，20%透明

                case RenderStyleName.GridUnknown:
                    return new RenderStyle(Color.FromByteRGB(255, 112, 67), 0.8); // Material Deep Orange网格未知区域，20%透明

                case RenderStyleName.TangentPoint:
                    return new RenderStyle(Color.FromByteRGB(244, 67, 54), 0.8); // Material Red切点，20%透明

                case RenderStyleName.SafetyWarning:
                    return new RenderStyle(Color.FromByteRGB(244, 67, 54), 0.85); // Material Red安全警告，15%透明

                case RenderStyleName.RailBaseline:
                    return new RenderStyle(Color.FromByteRGB(255, 138, 128), 0.7); // 浅红色，30%透明

                case RenderStyleName.AssemblyGuideLine:
                    return new RenderStyle(Color.FromByteRGB(76, 175, 80), 0.85); // Material Green装配基准向量

                case RenderStyleName.AssemblyInstallationPlane:
                    return new RenderStyle(Color.FromByteRGB(76, 175, 80), 0.5); // Material Green安装参考面，50%透明

                case RenderStyleName.HoistingLine:
                    return new RenderStyle(Color.FromByteRGB(156, 39, 176), 0.8); // Material Purple吊装路径，20%透明

                case RenderStyleName.TransformAxisX:
                    return new RenderStyle(Color.FromByteRGB(244, 67, 54), 0.9); // Material Red

                case RenderStyleName.TransformAxisY:
                    return new RenderStyle(Color.FromByteRGB(76, 175, 80), 0.9); // Material Green

                case RenderStyleName.TransformAxisZ:
                    return new RenderStyle(Color.FromByteRGB(33, 150, 243), 0.9); // Material Blue

                default:
                    return new RenderStyle(Color.White, 1.0); // 默认白色，完全不透明
            }
        }


        #endregion

        /// <summary>
        /// 获取连线半径
        /// </summary>
        /// <returns>连线半径</returns>
        private double GetLineRadius()
        {
            // 获取标准尺寸（起点尺寸）
            double standardRadiusInMeters = GetStandardRadiusInMeters();

            // 连线半径为标准尺寸的40%
            double lineRadiusInMeters = standardRadiusInMeters * 0.4;

            return lineRadiusInMeters * UnitsConverter.GetMetersToUnitsConversionFactor();
        }

        /// <summary>
        /// 获取路径可视化对象
        /// </summary>
        /// <param name="pathId">路径ID</param>
        /// <returns>路径可视化对象，如果不存在返回null</returns>
        private PathVisualization GetPathVisualization(string pathId)
        {
            lock (_lockObject)
            {
                _pathVisualizations.TryGetValue(pathId, out var visualization);
                return visualization;
            }
        }

        #endregion

        /// <summary>
        /// 渲染预览点（灰色显示）
        /// </summary>
        /// <param name="previewPoint">预览点对象</param>
        public void RenderPreviewPoint(PathPoint previewPoint)
        {
            try
            {
                if (previewPoint == null)
                {
                    return;
                }

                lock (_lockObject)
                {
                    // 获取适当的半径
                    double radius = GetRadiusForPointType(previewPoint.Type);

                    // 获取预览点样式（颜色+透明度）
                    var previewStyle = GetRenderStyle(RenderStyleName.PreviewPoint);

                    // 创建预览点标记
                    _previewMarker = new CircleMarker
                    {
                        Position = previewPoint.Position,
                        Radius = radius,
                        Color = previewStyle.Color,
                        Alpha = previewStyle.Alpha,
                        IsVisible = true,
                        PathPoint = previewPoint
                    };

                    // 请求刷新视图
                    RequestViewRefresh();
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[预览点渲染] 渲染预览点失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 清除预览点
        /// </summary>
        public void ClearPreviewPoint()
        {
            try
            {
                lock (_lockObject)
                {
                    if (_previewMarker != null || _previewLines.Count > 0)
                    {
                        _previewMarker = null;
                        _previewLines.Clear();

                        // 请求刷新视图
                        RequestViewRefresh();
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[预览点渲染] 清除预览点失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 渲染预览连线
        /// </summary>
        /// <param name="previewPoint">预览点</param>
        /// <param name="pathPoints">当前路径点列表</param>
        public void RenderPreviewLines(PathPoint previewPoint, List<PathPoint> pathPoints)
        {
            try
            {
                if (previewPoint == null || pathPoints == null || pathPoints.Count == 0)
                {
                    return;
                }

                lock (_lockObject)
                {
                    // 清除旧的预览连线
                    _previewLines.Clear();

                    // 找到预览点应该插入的最近线段
                    var nearestSegment = FindNearestLineSegment(previewPoint.Position, pathPoints);

                    if (nearestSegment.HasValue)
                    {
                        var (prevPoint, nextPoint) = nearestSegment.Value;

                        // 创建两条预览连线
                        // 1. 前一个点 -> 预览点
                        var line1 = new LineMarker
                        {
                            StartPoint = prevPoint.Position,
                            EndPoint = previewPoint.Position,
                            Color = GetRenderStyle(RenderStyleName.PreviewLine).Color, // 预览连线颜色
                            Radius = GetLineRadius() // 使用与正常连线相同的直径
                        };
                        _previewLines.Add(line1);

                        // 2. 预览点 -> 后一个点
                        var line2 = new LineMarker
                        {
                            StartPoint = previewPoint.Position,
                            EndPoint = nextPoint.Position,
                            Color = GetRenderStyle(RenderStyleName.PreviewLine).Color, // 预览连线颜色
                            Radius = GetLineRadius()
                        };
                        _previewLines.Add(line2);

                    }
                    else
                    {
                        LogManager.Warning("[预览连线渲染] 未找到合适的线段插入预览点");
                    }

                    // 请求刷新视图
                    RequestViewRefresh();
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[预览连线渲染] 渲染预览连线失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 清除预览连线
        /// </summary>
        public void ClearPreviewLines()
        {
            try
            {
                lock (_lockObject)
                {
                    if (_previewLines.Count > 0)
                    {
                        _previewLines.Clear();

                        // 请求刷新视图
                        RequestViewRefresh();
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[预览连线渲染] 清除预览连线失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 渲染预览路径（用于修改路径点时的预览）
        /// </summary>
        /// <param name="previewRoute">包含预览修改的路径</param>
        public void RenderPreviewPath(PathRoute previewRoute)
        {
            try
            {
                if (previewRoute == null || previewRoute.Points.Count == 0)
                {
                    return;
                }

                lock (_lockObject)
                {
                    // 只清理预览元素，不影响原有路径
                    ClearPreviewPoint();
                    ClearPreviewLines();

                    // 找到预览点及其索引
                    var previewPointIndex = -1;
                    PathPoint previewPoint = null;

                    for (int i = 0; i < previewRoute.Points.Count; i++)
                    {
                        if (previewRoute.Points[i].Name.Contains("_预览"))
                        {
                            previewPointIndex = i;
                            previewPoint = previewRoute.Points[i];
                            break;
                        }
                    }

                    if (previewPoint != null && previewPointIndex >= 0)
                    {
                        // 只渲染预览点
                        RenderPreviewPoint(previewPoint);

                        // 只渲染与预览点相关的连线
                        // 连接前一个点到预览点
                        if (previewPointIndex > 0)
                        {
                            var prevPoint = previewRoute.Points[previewPointIndex - 1];
                            var line1 = new LineMarker
                            {
                                StartPoint = prevPoint.Position,
                                EndPoint = previewPoint.Position,
                                Color = GetRenderStyle(RenderStyleName.PreviewLine).Color, // 预览连线颜色
                                Radius = GetLineRadius()
                            };
                            _previewLines.Add(line1);
                        }

                        // 连接预览点到下一个点
                        if (previewPointIndex < previewRoute.Points.Count - 1)
                        {
                            var nextPoint = previewRoute.Points[previewPointIndex + 1];
                            var line2 = new LineMarker
                            {
                                StartPoint = previewPoint.Position,
                                EndPoint = nextPoint.Position,
                                Color = GetRenderStyle(RenderStyleName.PreviewLine).Color, // 预览连线颜色
                                Radius = GetLineRadius()
                            };
                            _previewLines.Add(line2);
                        }
                    }
                    else
                    {
                        LogManager.Warning("[预览路径渲染] 未找到预览点，跳过渲染");
                    }

                    RequestViewRefresh();
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[预览路径渲染] 渲染预览路径失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 清理所有预览渲染
        /// </summary>
        public void ClearPreview()
        {
            try
            {
                lock (_lockObject)
                {
                    // 清理预览点
                    ClearPreviewPoint();

                    // 清理预览连线
                    ClearPreviewLines();

                    RequestViewRefresh();
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[清理预览] 清理预览失败: {ex.Message}", ex);
            }
        }

        #region 私有辅助方法

        /// <returns>标准尺寸（米）</returns>
        /// <summary>
        /// 计算标准尺寸（起点尺寸），其他元素以此为基准按比例计算
        /// </summary>
        /// <returns>标准尺寸（米）</returns>
        private double GetStandardRadiusInMeters()
        {
            // 起点尺寸为网格大小的100%，并限制在合理范围内
            double standardRadius = _currentGridSizeInMeters * 1.0;

            // 边界限制：最小0.1米，最大0.5米
            return Math.Max(0.1, Math.Min(0.5, standardRadius));
        }

        public double GetRadiusForPointType(PathPointType pointType)
        {
            // 获取标准尺寸（起点尺寸）
            double standardRadiusInMeters = GetStandardRadiusInMeters();

            // 根据点类型应用比例系数
            double baseRadiusInMeters;
            if (pointType == PathPointType.WayPoint)
            {
                // 路径点为标准尺寸的1/4
                baseRadiusInMeters = standardRadiusInMeters * 0.25;
            }
            else
            {
                // 起点/终点使用标准尺寸的1/2
                baseRadiusInMeters = standardRadiusInMeters * 0.5;
            }

            // 获取真实文档单位转换系数
            double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();

            // 转换为模型单位
            double radius = baseRadiusInMeters * metersToModelUnits;

            return radius;
        }

        /// <summary>
        /// 根据路径点类型获取颜色
        /// </summary>
        public Color GetColorForPointType(PathPointType pointType)
        {
            switch (pointType)
            {
                case PathPointType.StartPoint:
                    return GetRenderStyle(RenderStyleName.StartPoint).Color; // 起点绿色
                case PathPointType.EndPoint:
                    return GetRenderStyle(RenderStyleName.EndPoint).Color; // 终点红色
                case PathPointType.WayPoint:
                default:
                    return GetRenderStyle(RenderStyleName.WayPoint).Color; // 路径中间点蓝色
            }
        }

        /// <summary>
        /// 计算两点间距离
        /// </summary>
        private double CalculateDistance(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>
        /// 渲染长方体标记（通用方法）
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="startPoint">起点</param>
        /// <param name="endPoint">终点</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="horizontalDirection">水平段方向向量（用于垂直路径渲染时确定通行空间方向）</param>
        private void RenderCuboidMarker(Graphics graphics, Point3D startPoint, Point3D endPoint, double width, double height, Vector3D horizontalDirection = null, Vector3D upReference = null)
        {
            try
            {
                // 计算方向向量
                var direction = new Vector3D(
                    endPoint.X - startPoint.X,
                    endPoint.Y - startPoint.Y,
                    endPoint.Z - startPoint.Z
                );

                // 计算长度
                var length = Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y + direction.Z * direction.Z);

                if (length < 0.001) // 避免零长度线段
                    return;

                // 归一化方向向量
                direction = new Vector3D(direction.X / length, direction.Y / length, direction.Z / length);

                var (right, up) = ObjectSpaceOrientationHelper.CalculateAxes(
                    startPoint,
                    endPoint,
                    upReference ?? GetHostUpVector(),
                    horizontalDirection);

                // 计算长方体的边界框和向量
                var halfWidth = width / 2.0;
                var halfHeight = height / 2.0;

                // 计算立方体原点（使长方体中心在起点位置）
                var origin = new Point3D(
                    startPoint.X - halfWidth * right.X - halfHeight * up.X,
                    startPoint.Y - halfWidth * right.Y - halfHeight * up.Y,
                    startPoint.Z - halfWidth * right.Z - halfHeight * up.Z
                );

                // 定义立方体的三个轴向量
                var xVector = new Vector3D(direction.X * length, direction.Y * length, direction.Z * length); // 长度方向（沿路径）
                var yVector = new Vector3D(right.X * width, right.Y * width, right.Z * width); // 宽度方向（垂直于路径）
                var zVector = new Vector3D(up.X * height, up.Y * height, up.Z * height); // 高度方向（垂直于路径和宽度）

                // 使用Cuboid API渲染长方体
                graphics.Cuboid(origin, xVector, yVector, zVector, true);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[长方体渲染] 渲染长方体失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 渲染长方体标记（指定长度）
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="startPoint">起点</param>
        /// <param name="endPoint">终点</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="length">指定长度（覆盖默认计算值）</param>
        /// <param name="horizontalDirection">水平段方向向量（用于垂直路径渲染时确定通行空间方向）</param>
        private void RenderCuboidMarkerWithLength(Graphics graphics, Point3D startPoint, Point3D endPoint, double width, double height, double length, Vector3D horizontalDirection = null, Vector3D upReference = null)
        {
            try
            {
                // 计算方向向量
                var direction = new Vector3D(
                    endPoint.X - startPoint.X,
                    endPoint.Y - startPoint.Y,
                    endPoint.Z - startPoint.Z
                );

                // 归一化方向向量
                var directionLength = Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y + direction.Z * direction.Z);
                if (directionLength < 0.001) // 避免零长度线段
                    return;

                direction = new Vector3D(direction.X / directionLength, direction.Y / directionLength, direction.Z / directionLength);

                var (right, up) = ObjectSpaceOrientationHelper.CalculateAxes(
                    startPoint,
                    endPoint,
                    upReference ?? GetHostUpVector(),
                    horizontalDirection);

                // 计算长方体的边界框和向量
                var halfWidth = width / 2.0;
                var halfHeight = height / 2.0;

                // 计算立方体原点（使长方体中心在起点位置）
                var origin = new Point3D(
                    startPoint.X - halfWidth * right.X - halfHeight * up.X,
                    startPoint.Y - halfWidth * right.Y - halfHeight * up.Y,
                    startPoint.Z - halfWidth * right.Z - halfHeight * up.Z
                );

                // 定义立方体的三个轴向量
                var xVector = new Vector3D(direction.X * length, direction.Y * length, direction.Z * length); // 使用指定长度（沿路径）
                var yVector = new Vector3D(right.X * width, right.Y * width, right.Z * width); // 宽度方向（垂直于路径）
                var zVector = new Vector3D(up.X * height, up.Y * height, up.Z * height); // 高度方向（垂直于路径和宽度）

                // 使用Cuboid API渲染长方体
                graphics.Cuboid(origin, xVector, yVector, zVector, true);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[长方体渲染] 渲染长方体失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 渲染带状连线（长方体）
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="lineMarker">连线标记</param>
        private void RenderRibbonLineMarker(Graphics graphics, LineMarker lineMarker)
        {
            // 使用 LineMarker 的 Width 属性（如果没有设置则使用 Radius * 2）
            var width = lineMarker.Width > 0 ? lineMarker.Width : lineMarker.Radius * 2;

            // 检查是否是圆弧段且有多段采样点
            if (lineMarker.SegmentType == PathSegmentType.Arc &&
                lineMarker.SampledPoints != null &&
                lineMarker.SampledPoints.Count >= 2)
            {
                // 圆弧段：在每个采样点渲染完整的物体长方体
                RenderArcSegmentCuboids(graphics, lineMarker, width);
            }
            else
            {
                // 直线段：单个长方体
                // 设置颜色和透明度
                graphics.Color(lineMarker.Color, lineMarker.Opacity);
                
                RenderCuboidMarker(
                    graphics,
                    lineMarker.StartPoint,
                    lineMarker.EndPoint,
                    width,
                    lineMarker.Height,
                    lineMarker.HorizontalDirection,
                    lineMarker.UpDirection
                );
            }
        }

        /// <summary>
        /// 渲染圆弧段的物体长方体
        /// 在每个采样点处渲染一个完整的物体长方体，中心在采样点，向前后各延伸 L/2
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="lineMarker">连线标记（必须是圆弧段）</param>
        /// <param name="width">长方体宽度</param>
        private void RenderArcSegmentCuboids(Graphics graphics, LineMarker lineMarker, double width)
        {
            // 设置颜色和透明度
            graphics.Color(lineMarker.Color, lineMarker.Opacity);

            // 在每个采样点处渲染完整的物体长方体
            for (int i = 0; i < lineMarker.SampledPoints.Count; i++)
            {
                // 计算当前采样点的切线方向
                Vector3D tangent = CalculateTangentAtSamplePoint(lineMarker.SampledPoints, i);
                
                // 计算长方体的起点和终点（沿切线方向，各延伸 L/2）
                var halfLength = _passageAlongPath / 2.0;
                var startPoint = new Point3D(
                    lineMarker.SampledPoints[i].X - tangent.X * halfLength,
                    lineMarker.SampledPoints[i].Y - tangent.Y * halfLength,
                    lineMarker.SampledPoints[i].Z - tangent.Z * halfLength
                );
                var endPoint = new Point3D(
                    lineMarker.SampledPoints[i].X + tangent.X * halfLength,
                    lineMarker.SampledPoints[i].Y + tangent.Y * halfLength,
                    lineMarker.SampledPoints[i].Z + tangent.Z * halfLength
                );
                
                RenderCuboidMarkerWithLength(
                    graphics,
                    startPoint,
                    endPoint,
                    width,
                    lineMarker.Height,
                    _passageAlongPath,
                    lineMarker.HorizontalDirection,
                    lineMarker.UpDirection
                );
            }
        }

        private Vector3D ResolveObjectSpaceUpDirection(PathRoute route)
        {
            if (route?.PathType == NavisworksTransport.PathType.Rail && route.RailPreferredNormal != null)
            {
                return Normalize(new Vector3D(
                    route.RailPreferredNormal.X,
                    route.RailPreferredNormal.Y,
                    route.RailPreferredNormal.Z));
            }

            return GetHostUpVector();
        }

        /// <summary>
        /// 计算采样点处的切线方向
        /// </summary>
        /// <param name="sampledPoints">采样点列表</param>
        /// <param name="index">当前采样点索引</param>
        /// <returns>归一化的切线向量</returns>
        private Vector3D CalculateTangentAtSamplePoint(List<Point3D> sampledPoints, int index)
        {
            Vector3D tangent;
            
            if (index == 0)
            {
                // 第一个点：使用到下一点的向量作为切线
                tangent = new Vector3D(
                    sampledPoints[1].X - sampledPoints[0].X,
                    sampledPoints[1].Y - sampledPoints[0].Y,
                    sampledPoints[1].Z - sampledPoints[0].Z
                );
            }
            else if (index == sampledPoints.Count - 1)
            {
                // 最后一个点：使用从上一点到当前点的向量作为切线
                tangent = new Vector3D(
                    sampledPoints[index].X - sampledPoints[index - 1].X,
                    sampledPoints[index].Y - sampledPoints[index - 1].Y,
                    sampledPoints[index].Z - sampledPoints[index - 1].Z
                );
            }
            else
            {
                // 中间点：使用前后两点的平均方向作为切线
                var prev = new Vector3D(
                    sampledPoints[index].X - sampledPoints[index - 1].X,
                    sampledPoints[index].Y - sampledPoints[index - 1].Y,
                    sampledPoints[index].Z - sampledPoints[index - 1].Z
                );
                var next = new Vector3D(
                    sampledPoints[index + 1].X - sampledPoints[index].X,
                    sampledPoints[index + 1].Y - sampledPoints[index].Y,
                    sampledPoints[index + 1].Z - sampledPoints[index].Z
                );
                tangent = new Vector3D(prev.X + next.X, prev.Y + next.Y, prev.Z + next.Z);
            }
            
            // 归一化切线向量
            var tangentLength = Math.Sqrt(tangent.X * tangent.X + tangent.Y * tangent.Y + tangent.Z * tangent.Z);
            if (tangentLength > 0.001)
            {
                tangent = new Vector3D(tangent.X / tangentLength, tangent.Y / tangentLength, tangent.Z / tangentLength);
            }
            
            return tangent;
        }


        /// <summary>
        /// 渲染点标记
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="pointMarker">点标记</param>
        private void RenderPointMarker(Graphics graphics, CircleMarker pointMarker)
        {
            switch (pointMarker.GridPointType)
            {
                case GridPointType.Rectangle:
                    // 渲染立方体
                    RenderCubeMarker(graphics, pointMarker);
                    break;
                case GridPointType.Circle:
                    // 渲染圆
                    RenderCircleMarker(graphics, pointMarker);
                    break;
                case GridPointType.Sphere:
                default:
                    // 渲染球形（默认）
                    graphics.Sphere(pointMarker.Center, pointMarker.Radius);
                    break;
            }
        }

        /// <summary>
        /// 渲染立方体标记
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="pointMarker">点标记</param>
        private void RenderCubeMarker(Graphics graphics, CircleMarker pointMarker)
        {
            // 计算正方形的边长（直径）
            double sideLength = pointMarker.Radius * 2;

            // 网格矩形必须落在宿主水平平面内，不能写死世界 XY。
            var hostUp = GetHostUpVector();
            var (planarAxis1, planarAxis2) = GetHostPlanarAxes(hostUp);
            var xVector = new Vector3D(planarAxis1.X * sideLength, planarAxis1.Y * sideLength, planarAxis1.Z * sideLength);
            var yVector = new Vector3D(planarAxis2.X * sideLength, planarAxis2.Y * sideLength, planarAxis2.Z * sideLength);

            // 沿宿主 up 略微抬高，避免与模型重叠。
            var liftedCenter = ApplyVectorOffset(pointMarker.Center, hostUp, 0.01);
            var origin = new Point3D(
                liftedCenter.X - planarAxis1.X * pointMarker.Radius - planarAxis2.X * pointMarker.Radius,
                liftedCenter.Y - planarAxis1.Y * pointMarker.Radius - planarAxis2.Y * pointMarker.Radius,
                liftedCenter.Z - planarAxis1.Z * pointMarker.Radius - planarAxis2.Z * pointMarker.Radius
            );

            // 使用Rectangle API渲染正方形
            graphics.Rectangle(origin, xVector, yVector, pointMarker.Filled);
        }

        /// <summary>
        /// 渲染圆形标记
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="pointMarker">点标记</param>
        private void RenderCircleMarker(Graphics graphics, CircleMarker pointMarker)
        {
            // 调整中心点位置，沿宿主 up 略微抬高以避免与模型重叠
            Point3D adjustCenterPoint = ApplyVectorOffset(pointMarker.Center, pointMarker.Normal, 0.01);

            // 使用Circle API渲染圆形
            graphics.Circle(adjustCenterPoint, pointMarker.Normal, pointMarker.Radius, true);
        }

        /// <summary>
        /// 渲染方块标记（切点）- 使用圆锥体
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="marker">方块标记</param>
        private void RenderSquareMarker(Graphics graphics, SquareMarker marker)
        {
            try
            {
                // 计算圆锥体半径（底部半径）
                var radius = marker.Size / 2.0;

                // 计算圆锥体高度
                var height = marker.Height;

                // 计算圆锥体起点和终点（底面放在通道上）
                var startPoint = new Point3D(
                    marker.Center.X,
                    marker.Center.Y,
                    marker.Center.Z // 底面Z坐标 = 中心Z坐标
                );

                var endPoint = new Point3D(
                    marker.Center.X,
                    marker.Center.Y,
                    marker.Center.Z + height // 顶面Z坐标 = 中心Z坐标 + 高度
                );

                // 使用统一样式
                graphics.Color(marker.Color, marker.Alpha);

                // 使用Cone API渲染圆锥体（底部半径 = radius，顶部半径 = 0）
                graphics.Cone(startPoint, endPoint, radius, 0);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[切点渲染] 渲染切点失败: {ex.Message}", ex);
            }
        }

        private void RenderPlaneMarker(Graphics graphics, PlaneMarker marker)
        {
            graphics.Color(marker.Color, marker.Alpha);
            graphics.Rectangle(marker.Origin, marker.XVector, marker.YVector, marker.Filled);
        }

        /// <summary>
        /// 渲染连线标记（支持直线段和圆弧段）
        /// </summary>
        /// <param name="graphics">图形上下文</param>
        /// <param name="lineMarker">连线标记</param>
        private void RenderLineMarker(Graphics graphics, LineMarker lineMarker)
        {
            // 🔥 路径线渲染逻辑：保持原有行为
            // 注意：ShowObjectSpace 的通行空间使用 RenderRibbonLineMarker 单独渲染
            if (_visualizationMode == PathVisualizationMode.ObjectSpace || _visualizationMode == PathVisualizationMode.RibbonLine)
            {
                // ObjectSpace 或 RibbonLine 模式：使用长方体渲染
                RenderRibbonLineMarker(graphics, lineMarker);
            }
            else
            {
                // StandardLine 模式：使用圆柱体渲染
                var style = GetRenderStyle(RenderStyleName.Line);
                graphics.Color(lineMarker.Color, style.Alpha);
                if (lineMarker.SegmentType == PathSegmentType.Arc &&
                    lineMarker.SampledPoints != null &&
                    lineMarker.SampledPoints.Count >= 2)
                {
                    // 圆弧段：多段圆柱体
                    // 为了避免外侧出现缝隙，需要根据外侧弧线长度调整每个圆柱体的厚度（半径）
                    double cylinderRadius = lineMarker.Radius;  // 默认使用原始半径
                    
                    if (lineMarker.Trajectory != null)
                    {
                        // 计算外侧弧线长度 = (圆弧半径 + 连线半径) * 偏转角
                        double outerArcLength = (lineMarker.Trajectory.ActualRadius + lineMarker.Radius) * lineMarker.Trajectory.DeflectionAngle;
                        
                        // 计算每个圆柱体在外侧应该覆盖的长度
                        int segmentCount = lineMarker.SampledPoints.Count - 1;
                        double outerSegmentLength = outerArcLength / segmentCount;
                        
                        // 圆柱体的半径（厚度）应该等于外侧段长度的一半
                        // 这样圆柱体在外侧的覆盖长度 = 2 * radius = outerSegmentLength，正好填满外侧弧线
                        cylinderRadius = outerSegmentLength / 2.0;
                    }
                    
                    for (int i = 0; i < lineMarker.SampledPoints.Count - 1; i++)
                    {
                        graphics.Cylinder(lineMarker.SampledPoints[i], lineMarker.SampledPoints[i + 1], cylinderRadius);
                    }
                }
                else
                {
                    // 直线段：单个圆柱体
                    graphics.Cylinder(lineMarker.StartPoint, lineMarker.EndPoint, lineMarker.Radius);
                }
            }
        }

        /// <summary>
        /// 延伸线段起点和终点以完全包裹物体（ObjectSpace模式）
        /// </summary>
        /// <param name="startPoint">起点（会被修改）</param>
        /// <param name="endPoint">终点（会被修改）</param>
        private void ExtendLineSegmentForObjectSpace(ref Point3D startPoint, ref Point3D endPoint, double alongPathSize)
        {
            // 注意：调用此方法前应该检查 _showObjectSpace
            if (!_showObjectSpace)
                return;

            var segDx = endPoint.X - startPoint.X;
            var segDy = endPoint.Y - startPoint.Y;
            var segDz = endPoint.Z - startPoint.Z;
            var segLength = Math.Sqrt(segDx * segDx + segDy * segDy + segDz * segDz);
            
            if (segLength > 0.001)
            {
                double offset = alongPathSize / 2.0;
                var dirX = segDx / segLength;
                var dirY = segDy / segLength;
                var dirZ = segDz / segLength;
                
                // 起点向反方向延伸
                startPoint = new Point3D(
                    startPoint.X - dirX * offset,
                    startPoint.Y - dirY * offset,
                    startPoint.Z - dirZ * offset
                );
                
                // 终点向正方向延伸
                endPoint = new Point3D(
                    endPoint.X + dirX * offset,
                    endPoint.Y + dirY * offset,
                    endPoint.Z + dirZ * offset
                );
            }
        }

        /// <summary>
        /// 请求视图刷新（带防抖机制）
        /// </summary>
        private void RequestViewRefresh()
        {
            try
            {
                // 防抖机制：最小间隔50ms，避免过于频繁的Navisworks重绘
                // 使用高精度Ticks避免毫秒精度不足的问题
                long currentTicks = DateTime.Now.Ticks;
                long elapsedTicks = currentTicks - _lastRefreshTicks;
                long intervalMs = elapsedTicks / TimeSpan.TicksPerMillisecond;

                if (intervalMs < 50)
                {
                    return;
                }
                _lastRefreshTicks = currentTicks;

                // 在程序关闭阶段，文档或视图可能为空，这是正常的，静默返回
                if (Application.ActiveDocument?.ActiveView != null)
                {
                    Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[视图刷新] 失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 找到预览点应该插入的最近线段
        /// </summary>
        /// <param name="previewPosition">预览点位置</param>
        /// <param name="pathPoints">路径点列表</param>
        /// <returns>最近线段的前后两个点，如果找不到则返回null</returns>
        private (PathPoint prevPoint, PathPoint nextPoint)? FindNearestLineSegment(Point3D previewPosition, List<PathPoint> pathPoints)
        {
            if (pathPoints == null || pathPoints.Count < 2)
            {
                return null;
            }

            // 按索引排序路径点
            var sortedPoints = pathPoints.OrderBy(p => p.Index).ToList();

            double minDistance = double.MaxValue;
            (PathPoint prevPoint, PathPoint nextPoint)? nearestSegment = null;

            // 遍历相邻的路径点对，找到距离预览点最近的线段
            for (int i = 0; i < sortedPoints.Count - 1; i++)
            {
                var currentPoint = sortedPoints[i];
                var nextPoint = sortedPoints[i + 1];

                // 计算预览点到线段的距离
                var distance = CalculatePointToLineSegmentDistance(previewPosition, currentPoint.Position, nextPoint.Position);

                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestSegment = (currentPoint, nextPoint);
                }
            }

            return nearestSegment;
        }

        /// <summary>
        /// 计算点到线段的距离
        /// </summary>
        /// <param name="point">目标点</param>
        /// <param name="lineStart">线段起点</param>
        /// <param name="lineEnd">线段终点</param>
        /// <returns>点到线段的最短距离</returns>
        private double CalculatePointToLineSegmentDistance(Point3D point, Point3D lineStart, Point3D lineEnd)
        {
            // 线段向量
            var lineVector = new Point3D(lineEnd.X - lineStart.X, lineEnd.Y - lineStart.Y, lineEnd.Z - lineStart.Z);

            // 点到线段起点的向量
            var pointVector = new Point3D(point.X - lineStart.X, point.Y - lineStart.Y, point.Z - lineStart.Z);

            // 计算线段长度的平方
            var lineLengthSquared = lineVector.X * lineVector.X + lineVector.Y * lineVector.Y + lineVector.Z * lineVector.Z;

            if (lineLengthSquared == 0)
            {
                // 线段退化为点，返回点到点的距离
                return CalculateDistance(point, lineStart);
            }

            // 计算投影参数t
            var t = (pointVector.X * lineVector.X + pointVector.Y * lineVector.Y + pointVector.Z * lineVector.Z) / lineLengthSquared;

            // 将t限制在[0,1]范围内
            t = Math.Max(0, Math.Min(1, t));

            // 计算线段上最近点
            var closestPoint = new Point3D(
                lineStart.X + t * lineVector.X,
                lineStart.Y + t * lineVector.Y,
                lineStart.Z + t * lineVector.Z
            );

            // 返回点到最近点的距离
            return CalculateDistance(point, closestPoint);
        }

        #endregion
    }

    /// <summary>
    /// 切点类型枚举
    /// </summary>
    public enum TangentPointType
    {
        /// <summary>
        /// 进入切点（Ts）
        /// </summary>
        EntryTangent,

        /// <summary>
        /// 退出切点（Te）
        /// </summary>
        ExitTangent
    }

    /// <summary>
    /// 方块标记数据结构（用于切点）
    /// </summary>
    public class SquareMarker
    {
        /// <summary>
        /// 中心坐标
        /// </summary>
        public Point3D Center { get; set; }

        /// <summary>
        /// 方块面法向量
        /// </summary>
        public Vector3D Normal { get; set; }

        /// <summary>
        /// 方块边长
        /// </summary>
        public double Size { get; set; }

        /// <summary>
        /// 方块颜色
        /// </summary>
        public Color Color { get; set; }

        /// <summary>
        /// 不透明度 (1.0 = 完全不透明, 0.0 = 完全透明)
        /// </summary>
        public double Alpha { get; set; }

        /// <summary>
        /// 所属边ID
        /// </summary>
        public string EdgeId { get; set; }

        /// <summary>
        /// 切点类型
        /// </summary>
        public TangentPointType TangentType { get; set; }

        /// <summary>
        /// 路径方向（用于渲染垂直薄片）
        /// </summary>
        public Vector3D Direction { get; set; }

        /// <summary>
        /// 高度（用于圆柱体渲染）
        /// </summary>
        public double Height { get; set; }

        public override string ToString()
        {
            return $"SquareMarker[类型={TangentType}, 中心=({Center.X:F2},{Center.Y:F2},{Center.Z:F2}), 边长={Size:F2}]";
        }
    }

    /// <summary>
    /// 圆形标记数据结构
    /// </summary>
    public class CircleMarker
    {
        /// <summary>
        /// 圆心坐标
        /// </summary>
        public Point3D Center { get; set; }

        /// <summary>
        /// 圆面法向量
        /// </summary>
        public Vector3D Normal { get; set; }

        /// <summary>
        /// 圆形半径
        /// </summary>
        public double Radius { get; set; }

        /// <summary>
        /// 圆形颜色
        /// </summary>
        public Color Color { get; set; }

        /// <summary>
        /// 不透明度 (1.0 = 完全不透明, 0.0 = 完全透明)
        /// </summary>
        public double Alpha { get; set; }

        /// <summary>
        /// 是否填充
        /// </summary>
        public bool Filled { get; set; }

        /// <summary>
        /// 路径点类型
        /// </summary>
        public PathPointType PointType { get; set; }

        /// <summary>
        /// 网格点类型
        /// </summary>
        public GridPointType GridPointType { get; set; } = GridPointType.Sphere;

        /// <summary>
        /// 序号
        /// </summary>
        public int SequenceNumber { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreatedTime { get; set; }
        /// <summary>
        /// 是否可见
        /// </summary>
        public bool IsVisible { get; set; }

        /// <summary>
        /// 是否为不在路径上的控制点（半透明）
        /// </summary>
        public bool IsOffPath { get; set; } = false;

        /// <summary>
        /// 位置（Center的别名，用于预览点兼容性）
        /// </summary>
        public Point3D Position
        {
            get { return Center; }
            set { Center = value; }
        }

        /// <summary>
        /// 关联的路径点对象
        /// </summary>
        public PathPoint PathPoint { get; set; }

        public override string ToString()
        {
            return $"CircleMarker[序号={SequenceNumber}, 类型={PointType}, 中心=({Center.X:F2},{Center.Y:F2},{Center.Z:F2}), 半径={Radius:F2}]";
        }
    }

    public class PlaneMarker
    {
        public Point3D Origin { get; set; }
        public Vector3D XVector { get; set; }
        public Vector3D YVector { get; set; }
        public Color Color { get; set; }
        public double Alpha { get; set; }
        public bool Filled { get; set; } = true;
    }
}
