using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;
using NavisworksTransport.PathPlanning;
using NavisworksTransport.Utils;
using NavisworksTransport.Core;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Commands;
using NavisworksTransport.Utils.CoordinateSystem;

namespace NavisworksTransport
{
    /// <summary>
    /// 路径规划管理器
    /// 负责路径规划的核心业务逻辑，与UI完全解耦
    /// </summary>
    public class PathPlanningManager : IPathPlanningManager, IDisposable
    {
        #region 私有字段

        private readonly string _managerId;
        private readonly CategoryAttributeManager _categoryManager;
        private readonly UIStateManager _uiStateManager;

        private CoordinateConverter _coordinateConverter;
        private PathPointRenderPlugin _renderPlugin;

        // 路径分析相关
        private PathDatabase _pathDatabase;
        private PathAnalysisService _analysisService;
        private string _databaseDocumentPath;
        private List<ModelItem> _walkableAreas;
        private List<PathRoute> _routes;
        private PathRoute _currentRoute;
        private ChannelBounds _combinedChannelBounds;

        // 路径编辑状态管理
        private PathEditState _pathEditState = PathEditState.Viewing;
        private PathPointType _currentPointType = PathPointType.WayPoint;
        private PathRoute _editingRoute = null;
        private PathHistoryManager _historyManager;

        // ToolPlugin 集成
        private bool _isToolPluginActive = false;

        // 自动路径规划模式标志
        private bool _isInAutoPathMode = false;

        // 空轨吸附模式标志
        private bool _enableRailSnapping = false;

        // 吊装模式标志
        private bool _enableHoistingMode = false;

        // 吊装起点3D坐标
        private Point3D _hoistingStartPoint = null;

        // 吊装高度（模型单位）
        private double _hoistingLiftHeight;

        // 吊装中间点列表（用户点击的地面投影点）
        private List<Point3D> _hoistingGroundIntermediatePoints = new List<Point3D>();

        // 路径点3D标记管理
        private List<PathPointMarker> _pathPointMarkers;

        // 预览点管理
        private PathPoint _previewPoint = null;

        // 网格可视化设置
        private bool _showWalkableGrid = false;
        private bool _showObstacleGrid = false;
        private bool _showUnknownGrid = false;
        private bool _showDoorGrid = false;
        private GridMap _currentGridMap = null;  // 保存当前网格地图用于刷新
        private double _currentObjectHeight = 2.0; // 保存当前物体高度（米）用于网格刷新
        private bool _isPreviewMode = false;
        private int _previewInsertIndex = -1; // 保存预览点应该插入的索引位置

        // 修改路径点管理
        private int _editingPointIndex = -1; // 正在修改的路径点索引
        private PathPoint _originalPoint = null; // 修改前的原始路径点
        private PathPoint _editingPreviewPoint = null; // 修改时的预览路径点

        /// <summary>
        /// ToolPlugin是否处于激活状态（供InputMonitor使用）
        /// </summary>
        public bool IsToolPluginActive => _isToolPluginActive;

        /// <summary>
        /// 路径数据库是否已初始化（F1 副实例检测前等待数据库就绪，避免路径导入时数据库未建导致丢失）。
        /// </summary>
        public bool IsDatabaseReady => _pathDatabase != null;

        /// <summary>
        /// 获取当前是否在预览模式
        /// </summary>
        public bool IsPreviewMode => _isPreviewMode;

        // 静态引用，用于处理ToolPlugin事件
        private static PathPlanningManager _activePathManager;

        #endregion

        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="categoryManager">类别属性管理器</param>
        /// <param name="uiStateManager">UI状态管理器（可选）</param>
        public PathPlanningManager(CategoryAttributeManager categoryManager, UIStateManager uiStateManager = null)
        {
            _managerId = Guid.NewGuid().ToString("N").Substring(0, 8); // 前8位作为ID
            _categoryManager = categoryManager ?? throw new ArgumentNullException(nameof(categoryManager));
            _uiStateManager = uiStateManager ?? UIStateManager.Instance;

            InitializeManager();
        }

        /// <summary>
        /// 无参构造函数（为向后兼容而保留）
        /// </summary>
        public PathPlanningManager()
        {
            _managerId = Guid.NewGuid().ToString("N").Substring(0, 8);
            _categoryManager = new CategoryAttributeManager();
            _uiStateManager = UIStateManager.Instance;

            InitializeManager();
        }

        private void InitializeManager()
        {
            // 设置静态引用，确保所有地方都使用同一个实例
            _activePathManager = this;
            LogManager.Debug($"[路径管理] 设置_activePathManager静态引用, ManagerId: {_managerId}");

            // 获取已注册的圆形渲染插件实例
            try
            {
                _renderPlugin = PathPointRenderPlugin.Instance;
                if (_renderPlugin != null)
                {
                    LogManager.Info("[路径管理] ✅ PathPointRenderPlugin实例获取成功");
                    LogManager.Debug($"[路径管理] 渲染插件状态 - 启用: {_renderPlugin.IsEnabled}, 标记数量: {_renderPlugin.MarkerCount}");

                    // 推送默认的网格大小和物体参数，确保渲染插件有合理的初始值
                    InitializeRenderPluginDefaults();
                }
                else
                {
                    LogManager.Warning("[路径管理] ❌ PathPointRenderPlugin实例尚未就绪，将在后续尝试获取");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径管理] PathPointRenderPlugin实例获取失败: {ex.Message}");
                LogManager.Error($"[路径管理] 异常堆栈: {ex.StackTrace}");
                _renderPlugin = null;
            }

            // 初始化核心数据结构
            _walkableAreas = new List<ModelItem>();
            _routes = new List<PathRoute>();
            _currentRoute = new PathRoute("默认路径");
            _historyManager = new PathHistoryManager(50); // 最多保存50个历史记录
            _coordinateConverter = null; // 将在需要时初始化
            _pathPointMarkers = new List<PathPointMarker>();

            LogManager.Info($"PathPlanningManager初始化完成，ManagerId: {_managerId}");

            // 注意：数据库采用按需初始化。
            // 文档加载时只尝试连接已存在的数据库，不再为未使用插件的文档自动创建 .db 文件。
        }

        /// <summary>
        /// 路径分析数据库初始化
        /// 此方法应在文档加载完成后调用
        /// </summary>
        public void DatabaseInitialize(bool createIfMissing = true)
        {
            try
            {
                var documentPath = Application.ActiveDocument?.FileName;
                if (string.IsNullOrEmpty(documentPath))
                {
                    LogManager.Debug("文档路径为空，跳过数据库初始化");
                    return;
                }

                if (_pathDatabase != null &&
                    string.Equals(_databaseDocumentPath, documentPath, StringComparison.OrdinalIgnoreCase))
                {
                    return;
                }

                string dbPath = Path.ChangeExtension(documentPath, ".db");
                // F1 副实例支持环境变量覆盖 db 路径（导出模型无同名 .db 时用临时库）
                string overrideDb = Environment.GetEnvironmentVariable("TRANSPORTPLUGIN_TEST_DB_PATH");
                if (!string.IsNullOrWhiteSpace(overrideDb))
                {
                    dbPath = overrideDb;
                }

                // 显式指定的 db 路径（环境变量）即使 createIfMissing=false 也强制创建（F1 副实例临时库）
                if (!createIfMissing && !File.Exists(dbPath) && string.IsNullOrWhiteSpace(overrideDb))
                {
                    LogManager.Info($"文档对应数据库不存在，跳过自动连接: {dbPath}");
                    return;
                }

                if (_pathDatabase != null)
                {
                    try
                    {
                        _pathDatabase.Dispose();
                    }
                    catch (Exception disposeEx)
                    {
                        LogManager.Warning($"释放旧数据库连接时出现警告: {disposeEx.Message}");
                    }

                    _pathDatabase = null;
                    _analysisService = null;
                    _databaseDocumentPath = null;
                }

                _pathDatabase = new PathDatabase(documentPath);
                _analysisService = new PathAnalysisService(_pathDatabase);
                _databaseDocumentPath = documentPath;
                LogManager.Info($"路径分析数据库初始化成功，文档路径: {documentPath}");

                // 从数据库加载历史路径到内存
                LoadHistoricalRoutesFromDatabase();
            }
            catch (Exception ex)
            {
                LogManager.Error($"初始化路径分析数据库失败: {ex.Message}", ex);
                LogManager.Error($"数据库路径: {Application.ActiveDocument?.FileName}");
                LogManager.Error($"异常类型: {ex.GetType().Name}");
                // 不重新抛出：外层 OnModelsCollectionChanged 已有独立日志；
                // _pathDatabase 保持 null，后续操作自行判断。
            }
        }

        /// <summary>
        /// 初始化渲染插件的默认值
        /// 从配置文件读取网格大小和物体参数，确保渲染插件在任何情况下都有正确的可视化效果
        /// </summary>
        private void InitializeRenderPluginDefaults()
        {
            try
            {
                var config = ConfigManager.Instance.Current;

                // 从配置读取网格大小
                double gridSizeInMeters = config.PathEditing.CellSizeMeters;
                _renderPlugin.SetGridSize(gridSizeInMeters);
                LogManager.Info($"[渲染插件初始化] 已设置网格大小: {gridSizeInMeters}米（来自配置）");

                // 通行空间参数将在UpdatePassageSpaceViewModel中根据路径类型动态设置
                // 这里不设置默认值，因为不同路径类型的坐标系不同
                LogManager.Info($"[渲染插件初始化] 通行空间参数将在使用时动态设置");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[渲染插件初始化] 设置默认值失败: {ex.Message}", ex);
                // 即使失败也不抛出异常，避免影响PathPlanningManager的初始化
            }
        }

        #endregion

        #region IPathPlanningManager接口实现

        public string ManagerId => _managerId;

        public PathHistoryManager HistoryManager => _historyManager;

        public PathEditState PathEditState
        {
            get { return _pathEditState; }
            private set
            {
                var previousState = _pathEditState;
                _pathEditState = value;

                // 触发状态变更事件
                RaiseEditStateChanged(previousState, value, _editingRoute);

                LogManager.Info($"路径编辑状态变更: {previousState} -> {value}");
            }
        }

        public PathRoute EditingRoute
        {
            get { return _editingRoute; }
            private set { _editingRoute = value; }
        }

        public bool IsInEditableState
        {
            get { return _pathEditState == PathEditState.Creating || _pathEditState == PathEditState.Editing || _pathEditState == PathEditState.AddingPoints; }
        }

        public PathRoute CurrentRoute
        {
            get { return _currentRoute; }
            private set
            {
                var previousRoute = _currentRoute;
                _currentRoute = value;

                // 只有真正的业务操作才触发事件，UI同步不触发事件
                RaiseCurrentRouteChanged(previousRoute, value, triggerEvent: true);
            }
        }

        public IReadOnlyList<PathRoute> Routes => _routes.AsReadOnly();

        /// <summary>
        /// 获取可修改的路线集合（内部使用）
        /// </summary>
        internal List<PathRoute> ModifiableRoutes => _routes;

        public IReadOnlyList<ModelItem> SelectedChannels => _walkableAreas.AsReadOnly();

        public PathPointType CurrentPointType
        {
            get { return _currentPointType; }
            private set { _currentPointType = value; }
        }
        /// <summary>
        /// 是否在自动路径规划模式
        /// </summary>
        public bool IsInAutoPathMode
        {
            get { return _isInAutoPathMode; }
            private set { _isInAutoPathMode = value; }
        }

        public ChannelBounds CombinedChannelBounds => _combinedChannelBounds;

        #endregion

        #region 事件定义

        public event EventHandler<PathPlanningStatusChangedEventArgs> StatusChanged;
        public event EventHandler<PathPlanningErrorOccurredEventArgs> ErrorOccurred;
        public event EventHandler<PathEditStateChangedEventArgs> EditStateChanged;
        public event EventHandler<ChannelSelectionChangedEventArgs> ChannelSelectionChanged;
        public event EventHandler<PathPointOperationEventArgs> PathPointOperation;
        public event EventHandler<RouteGeneratedEventArgs> RouteGenerated;
        public event EventHandler<CurrentRouteChangedEventArgs> CurrentRouteChanged;
        public event EventHandler<PathPointsListUpdatedEventArgs> PathPointsListUpdated;
        
        /// <summary>
        /// 当前路径切换事件（总是触发，包括UI调用SetCurrentRoute时）
        /// 用于需要监听任何路径切换场景的功能（如剖面盒自动跟随）
        /// </summary>
        public event EventHandler<CurrentRouteChangedEventArgs> CurrentRouteSwitched;
        
        /// <summary>
        /// 路径可视化状态变更事件（用于通知UI刷新可视化按钮状态）
        /// </summary>
        public event EventHandler VisualizationStateChanged;
        public event EventHandler<RoutesLoadedEventArgs> RoutesLoaded;

        // 保留原有事件以保持向后兼容
        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<List<ModelItem>> ChannelsSelected;

        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<PathRoute> CurrentRouteChanged_Legacy;

        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<PathRoute> RouteGenerated_Legacy;

        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<string> StatusChanged_Legacy;

        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<string> ErrorOccurred_Legacy;

        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<PathEditState> PathEditStateChanged;

        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<PathPoint> PathPointAddedIn3D;

        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<PathPoint> PathPointRemovedFrom3D;

        [Obsolete("请使用新的强类型事件接口")]
        public event EventHandler<PathRoute> PathPointsListUpdated_Legacy;

        /// <summary>
        #endregion

        #region 事件触发方法

        private void RaiseStatusChanged(string statusMessage, PathPlanningStatusType statusType = PathPlanningStatusType.Info, object additionalData = null)
        {
            try
            {
                var eventArgs = new PathPlanningStatusChangedEventArgs(statusMessage, statusType, additionalData, _managerId);

                // 使用UIStateManager安全地触发事件
                if (_uiStateManager != null)
                {
                    _uiStateManager.QueueUIUpdate(() =>
                    {
                        StatusChanged?.Invoke(this, eventArgs);
                        // 向后兼容的事件
                        StatusChanged_Legacy?.Invoke(this, statusMessage);
                    });
                }
                else
                {
                    StatusChanged?.Invoke(this, eventArgs);
                    StatusChanged_Legacy?.Invoke(this, statusMessage);
                }

                LogManager.Info($"[状态变更] {statusMessage}");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[状态变更] 事件触发失败: {ex.Message}");
            }
        }

        private void RaiseErrorOccurred(string errorMessage, Exception exception = null, PathPlanningErrorLevel errorLevel = PathPlanningErrorLevel.Error)
        {
            try
            {
                var eventArgs = new PathPlanningErrorOccurredEventArgs(errorMessage, exception, errorLevel, _managerId);

                // 使用UIStateManager安全地触发事件
                if (_uiStateManager != null)
                {
                    _uiStateManager.QueueUIUpdate(() =>
                    {
                        ErrorOccurred?.Invoke(this, eventArgs);
                        // 向后兼容的事件
                        ErrorOccurred_Legacy?.Invoke(this, errorMessage);
                    });
                }
                else
                {
                    ErrorOccurred?.Invoke(this, eventArgs);
                    ErrorOccurred_Legacy?.Invoke(this, errorMessage);
                }

                LogManager.Error($"[错误发生] {errorMessage}");
                if (exception != null)
                {
                    LogManager.Error($"[错误详情] {exception}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[错误事件] 触发失败: {ex.Message}");
            }
        }

        private void RaiseEditStateChanged(PathEditState previousState, PathEditState newState, PathRoute editingRoute)
        {
            try
            {
                var eventArgs = new PathEditStateChangedEventArgs(previousState, newState, editingRoute, _managerId);

                if (_uiStateManager != null)
                {
                    _uiStateManager.QueueUIUpdate(() =>
                    {
                        EditStateChanged?.Invoke(this, eventArgs);
                        // 向后兼容的事件
                        PathEditStateChanged?.Invoke(this, newState);
                    });
                }
                else
                {
                    EditStateChanged?.Invoke(this, eventArgs);
                    PathEditStateChanged?.Invoke(this, newState);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[编辑状态变更] 事件触发失败: {ex.Message}");
            }
        }

        private void RaiseChannelSelectionChanged(List<ModelItem> selectedChannels, string selectionMethod)
        {
            try
            {
                var eventArgs = new ChannelSelectionChangedEventArgs(selectedChannels, selectionMethod, _managerId);

                if (_uiStateManager != null)
                {
                    _uiStateManager.QueueUIUpdate(() =>
                    {
                        ChannelSelectionChanged?.Invoke(this, eventArgs);
                        // 向后兼容的事件
                        ChannelsSelected?.Invoke(this, selectedChannels);
                    });
                }
                else
                {
                    ChannelSelectionChanged?.Invoke(this, eventArgs);
                    ChannelsSelected?.Invoke(this, selectedChannels);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[通道选择变更] 事件触发失败: {ex.Message}");
            }
        }

        private void RaisePathPointOperation(PathPointOperationType operationType, PathPoint pathPoint, PathRoute route)
        {
            try
            {
                var eventArgs = new PathPointOperationEventArgs(operationType, pathPoint, route, _managerId);

                if (_uiStateManager != null)
                {
                    _uiStateManager.QueueUIUpdate(() =>
                    {
                        PathPointOperation?.Invoke(this, eventArgs);

                        // 向后兼容的事件
                        if (operationType == PathPointOperationType.Added)
                        {
                            PathPointAddedIn3D?.Invoke(this, pathPoint);
                        }
                        else if (operationType == PathPointOperationType.Removed)
                        {
                            PathPointRemovedFrom3D?.Invoke(this, pathPoint);
                        }
                    });
                }
                else
                {
                    PathPointOperation?.Invoke(this, eventArgs);

                    if (operationType == PathPointOperationType.Added)
                    {
                        PathPointAddedIn3D?.Invoke(this, pathPoint);
                    }
                    else if (operationType == PathPointOperationType.Removed)
                    {
                        PathPointRemovedFrom3D?.Invoke(this, pathPoint);
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径点操作] 事件触发失败: {ex.Message}");
            }
        }

        private void RaiseRouteGenerated(PathRoute route, RouteGenerationMethod generationMethod, double gridSize = -1)
        {
            try
            {
                LogManager.Info($"*** RaiseRouteGenerated被调用: {route?.Name}, Method: {generationMethod}, GridSize: {gridSize} ***");

                // 在触发事件前，进行曲线化计算和保存
                // 注意：Manual方法不需要重新计算，因为PathPointsListUpdated已经计算过了
                if (route != null && route.Points.Count >= 2 && generationMethod != RouteGenerationMethod.Manual)
                {
                    // 使用统一的曲线化和保存方法
                    route.RecalculateAndSaveRoute($"RouteGenerated({generationMethod})");
                }
                else if (generationMethod == RouteGenerationMethod.Manual)
                {
                    LogManager.Info($"*** Manual方法跳过重新计算，PathPointsListUpdated已经计算过了 ***");
                }

                var eventArgs = new RouteGeneratedEventArgs(route, generationMethod, gridSize, _managerId);

                // 检查是否有订阅者
                if (RouteGenerated != null)
                {
                    var invocationList = RouteGenerated.GetInvocationList();
                    LogManager.Info($"*** RouteGenerated事件有 {invocationList.Length} 个订阅者 ***");

                    for (int i = 0; i < invocationList.Length; i++)
                    {
                        var handler = invocationList[i];
                        LogManager.Info($"*** 订阅者 {i}: {handler.Target?.GetType().Name}.{handler.Method.Name} ***");
                    }
                }
                else
                {
                    LogManager.Warning("*** RouteGenerated事件没有订阅者！！！ ***");
                }

                // 测试强制同步处理：使用高优先级QueueUIUpdate代替立即执行
                if (_uiStateManager != null)
                {
                    LogManager.Info("*** 使用高优先级强制同步处理RouteGenerated事件 ***");
                    _uiStateManager.QueueUIUpdateWithForcedSync(() =>
                    {
                        LogManager.Info($"*** 强制同步队列中执行RouteGenerated事件: {route?.Name} ***");
                        RouteGenerated?.Invoke(this, eventArgs);
                        // 向后兼容的事件
                        RouteGenerated_Legacy?.Invoke(this, route);
                        LogManager.Info($"*** RouteGenerated事件强制同步执行完成: {route?.Name} ***");
                    }, UIUpdatePriority.Critical, $"RouteGenerated强制同步事件({route?.Name})");
                }
                else
                {
                    LogManager.Info("*** 直接触发RouteGenerated事件（UIStateManager为null）***");
                    RouteGenerated?.Invoke(this, eventArgs);
                    RouteGenerated_Legacy?.Invoke(this, route);
                    LogManager.Info($"*** RouteGenerated事件直接调用完成: {route?.Name} ***");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"*** [路径生成] 事件触发失败: {ex.Message} ***");
            }
        }

        private void RaiseCurrentRouteChanged(PathRoute previousRoute, PathRoute newRoute, bool triggerEvent)
        {
            try
            {
                var eventArgs = new CurrentRouteChangedEventArgs(previousRoute, newRoute, _managerId);

                // 只有需要触发事件时才执行事件触发逻辑
                if (triggerEvent)
                {
                    if (_uiStateManager != null)
                    {
                        _uiStateManager.QueueUIUpdate(() =>
                        {
                            CurrentRouteChanged?.Invoke(this, eventArgs);
                            // 向后兼容的事件
                            CurrentRouteChanged_Legacy?.Invoke(this, newRoute);
                        });
                    }
                    else
                    {
                        CurrentRouteChanged?.Invoke(this, eventArgs);
                        CurrentRouteChanged_Legacy?.Invoke(this, newRoute);
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[当前路径变更] 事件触发失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 触发可视化状态变更事件
        /// </summary>
        public void RaiseVisualizationStateChanged()
        {
            try
            {
                if (_uiStateManager != null)
                {
                    _uiStateManager.QueueUIUpdate(() =>
                    {
                        VisualizationStateChanged?.Invoke(this, EventArgs.Empty);
                    });
                }
                else
                {
                    VisualizationStateChanged?.Invoke(this, EventArgs.Empty);
                }
                LogManager.Debug("[PathPlanningManager] 可视化状态变更事件已触发");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[可视化状态变更] 事件触发失败: {ex.Message}");
            }
        }

        public void RaisePathPointsListUpdated(PathRoute route, string updateReason)
        {
            try
            {
                // 在触发事件前，检查是否需要重新计算曲线化路径
                // 根据 updateReason 判断：
                // - "编辑完成"：需要重新计算（刚完成编辑）
                // - "路径点修改完成"：需要重新计算（位置变化）
                // - "添加路径点"：需要重新计算（新增点）
                // - "确认添加预览点"：需要重新计算（新增点）
                // - "删除路径点"：需要重新计算（删除点）
                bool needRecalculate = false;

                if (route != null && route.Points.Count >= 2)
                {
                    // 检查 Edges 是否为空
                    if (route.Edges == null || route.Edges.Count == 0)
                    {
                        needRecalculate = true;
                        LogManager.Info($"路径 Edges 为空，需要重新计算: {route.Name}");
                    }
                    // 根据更新原因判断
                    else if (updateReason == "编辑完成" ||
                             updateReason == "路径点修改完成" ||
                             updateReason == "添加路径点" ||
                             updateReason == "确认添加预览点" ||
                             updateReason == "删除路径点并重新分配类型")
                    {
                        needRecalculate = true;
                        LogManager.Info($"根据更新原因需要重新计算曲线化: {route.Name}, 原因: {updateReason}");
                    }
                }

                if (needRecalculate)
                {
                    // 使用统一的曲线化和保存方法
                    route.RecalculateAndSaveRoute($"PathPointsListUpdated({updateReason})");
                }

                var eventArgs = new PathPointsListUpdatedEventArgs(route, updateReason, _managerId);

                if (_uiStateManager != null)
                {
                    _uiStateManager.QueueUIUpdate(() =>
                    {
                        PathPointsListUpdated?.Invoke(this, eventArgs);
                        // 向后兼容的事件
                        PathPointsListUpdated_Legacy?.Invoke(this, route);
                    });
                }
                else
                {
                    PathPointsListUpdated?.Invoke(this, eventArgs);
                    PathPointsListUpdated_Legacy?.Invoke(this, route);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径点列表更新] 事件触发失败: {ex.Message}");
            }
        }

        private void RaiseRoutesLoaded(IReadOnlyList<PathRoute> routes, string loadSource = "Database")
        {
            try
            {
                var eventArgs = new RoutesLoadedEventArgs(routes, loadSource, _managerId);

                if (_uiStateManager != null)
                {
                    _uiStateManager.QueueUIUpdate(() =>
                    {
                        RoutesLoaded?.Invoke(this, eventArgs);
                    });
                }
                else
                {
                    RoutesLoaded?.Invoke(this, eventArgs);
                }

                LogManager.Info($"[路径加载完成] 从{loadSource}加载了 {routes.Count} 条路径");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径加载完成] 事件触发失败: {ex.Message}");
            }
        }

        #endregion

        #region 核心业务方法

        /// <summary>
        /// 切换到查看状态
        /// </summary>
        public void SwitchToViewingState()
        {
            PathEditState = PathEditState.Viewing;
            EditingRoute = null;

            // 智能管理ToolPlugin状态
            ManageToolPluginForEditState();

            RaiseStatusChanged("已切换到查看状态", PathPlanningStatusType.Info);
        }


        /// <summary>
        /// 重置路径编辑状态
        /// </summary>
        public void ResetPathEditState()
        {
            try
            {
                PathEditState = PathEditState.None;
                LogManager.Info("路径编辑状态已重置");
            }
            catch (Exception ex)
            {
                LogManager.Error("重置路径编辑状态失败", ex);
                RaiseErrorOccurred(ex.Message, ex);
            }
        }

        /// <summary>
        /// 清理无效的对象引用
        /// </summary>
        public void ClearInvalidReferences()
        {
            try
            {
                LogManager.Info("[PathPlanningManager] 清理无效对象引用");

                // 重置编辑状态
                PathEditState = PathEditState.None;

                // 清空当前路径
                if (_currentRoute != null)
                {
                    _currentRoute.Points.Clear();
                }

                // 清空通道引用
                if (_walkableAreas != null)
                {
                    _walkableAreas.Clear();
                    LogManager.Info("[PathPlanningManager] 已清空通道引用");
                }

                // 清空组合边界
                _combinedChannelBounds = null;

                LogManager.Info("[PathPlanningManager] 对象引用清理完成");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[PathPlanningManager] 清理对象引用失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 保存当前路线到历史记录
        /// </summary>
        /// <param name="description">保存描述</param>
        public void SaveCurrentRouteToHistory(string description = "手动保存")
        {
            try
            {
                if (CurrentRoute != null)
                {
                    // 创建历史记录条目
                    var entry = new PathHistoryEntry(CurrentRoute.Id, PathHistoryOperationType.ManualSave, CurrentRoute, description);
                    _historyManager?.AddHistoryEntry(entry);
                    LogManager.Info($"路线 '{CurrentRoute.Name}' 已保存到历史记录: {description}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error("保存路线到历史记录失败", ex);
                RaiseErrorOccurred(ex.Message, ex);
            }
        }

        /// <summary>
        /// 清除3D路径标记（保留网格可视化）
        /// </summary>
        public void Clear3DPathMarkers()
        {
            try
            {
                _pathPointMarkers?.Clear();
                // 清除路径标记但保留网格可视化
                _renderPlugin?.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                LogManager.Info("3D路径标记已清除（保留网格可视化）");
            }
            catch (Exception ex)
            {
                LogManager.Error("清除3D路径标记失败", ex);
                RaiseErrorOccurred(ex.Message, ex);
            }
        }

        /// <summary>
        /// 删除路径点
        /// </summary>
        /// <param name="point">要删除的路径点</param>
        public void RemovePathPoint(PathPoint point)
        {
            try
            {
                if (point != null)
                {
                    if (_pathPointMarkers != null)
                    {
                        // 找到对应的PathPointMarker
                        var marker = _pathPointMarkers.FirstOrDefault(m => m.PathPoint?.Id == point.Id);
                        if (marker != null)
                        {
                            _pathPointMarkers.Remove(marker);
                            LogManager.Info($"已从3D中移除路径点标记: {point.Name}");
                        }
                    }

                    // 重新渲染当前路径以反映更改
                    if (_renderPlugin != null && CurrentRoute != null)
                    {
                        _renderPlugin.RenderPath(CurrentRoute);
                        LogManager.Info($"已更新路径可视化: {point.Name}");
                    }

                    // 触发路径点移除事件
                    RaisePathPointOperation(PathPointOperationType.Removed, point, CurrentRoute);

                    // 保存到数据库
                    if (CurrentRoute != null)
                    {
                        SavePathToDatabase(CurrentRoute);
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error("从3D中移除路径点失败", ex);
                RaiseErrorOccurred(ex.Message, ex);
            }
        }

        /// <summary>
        /// 启动点击工具
        /// </summary>
        /// <param name="pointType">点击类型</param>
        public void StartClickTool(PathPointType pointType)
        {
            StartClickTool(pointType, enableRailSnapping: false, enableHoistingMode: false);
        }

        /// <summary>
        /// 启动点击工具（支持空轨吸附）
        /// </summary>
        /// <param name="pointType">点击类型</param>
        /// <param name="enableRailSnapping">是否启用空轨吸附</param>
        public void StartClickTool(PathPointType pointType, bool enableRailSnapping)
        {
            StartClickTool(pointType, enableRailSnapping, enableHoistingMode: false);
        }

        /// <summary>
        /// 启动点击工具（支持空轨吸附和吊装模式）
        /// </summary>
        /// <param name="pointType">点击类型</param>
        /// <param name="enableRailSnapping">是否启用空轨吸附</param>
        /// <param name="enableHoistingMode">是否启用吊装模式</param>
        public void StartClickTool(PathPointType pointType, bool enableRailSnapping, bool enableHoistingMode)
        {
            try
            {
                CurrentPointType = pointType;
                _enableRailSnapping = enableRailSnapping;
                _enableHoistingMode = enableHoistingMode;

                // 检查是否在自动路径模式 - 如果是，则不订阅PathPlanningManager的事件
                bool shouldSubscribeToEvents = !IsInAutoPathMode;
                LogManager.Info($"StartClickTool - 自动路径模式: {IsInAutoPathMode}, 订阅事件: {shouldSubscribeToEvents}, 空轨吸附: {enableRailSnapping}, 吊装模式: {enableHoistingMode}");

                ActivateToolPlugin(shouldSubscribeToEvents);
                PathEditState = PathEditState.AddingPoints;
                LogManager.Info($"点击工具已启动，类型: {pointType}，事件订阅: {shouldSubscribeToEvents}，空轨吸附: {enableRailSnapping}，吊装模式: {enableHoistingMode}");
            }
            catch (Exception ex)
            {
                LogManager.Error("启动点击工具失败", ex);
                RaiseErrorOccurred(ex.Message, ex);
            }
        }

        /// <summary>
        /// 停止点击工具
        /// </summary>
        public void StopClickTool()
        {
            try
            {
                LogManager.Debug("[事件清理] ===== 开始执行StopClickTool - 完整事件订阅清理 =====");

                // 1. 停用ToolPlugin并清理事件订阅
                DeactivateToolPlugin();

                // 2. 简化的事件订阅清理 - 移除危险的反射操作
                LogManager.Debug("[事件清理] 执行安全的事件订阅清理");
                try
                {
                    // 安全地移除事件订阅，多次取消订阅同一处理程序是安全的
                    PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
                    LogManager.Debug("[事件清理] 已安全移除PathPlanningManager事件订阅");
                }
                catch (Exception cleanupEx)
                {
                    LogManager.Error($"[事件清理] 事件清理过程异常: {cleanupEx.Message}");
                }

                // 注意：移除了PathEditState设置，StopClickTool只管理工具插件状态，不修改业务逻辑状态
                LogManager.Debug("[事件清理] ===== StopClickTool执行完成，所有事件订阅已清理 =====");
            }
            catch (Exception ex)
            {
                LogManager.Error("停止点击工具失败", ex);
                RaiseErrorOccurred(ex.Message, ex);
            }
        }

        /// <summary>
        /// 禁用鼠标处理（用于自动路径规划模式）
        /// </summary>
        public void DisableMouseHandling()
        {
            try
            {
                LogManager.Info("禁用PathPlanningManager鼠标处理，进入自动路径规划模式");
                IsInAutoPathMode = true;

                // 取消PathPlanningManager的鼠标事件订阅
                PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
                LogManager.Info("已取消PathPlanningManager的鼠标事件订阅");
            }
            catch (Exception ex)
            {
                LogManager.Error($"禁用鼠标处理失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 启用鼠标处理（用于手动路径编辑模式）
        /// </summary>
        public void EnableMouseHandling()
        {
            try
            {
                LogManager.Info("启用PathPlanningManager鼠标处理，退出自动路径规划模式");
                IsInAutoPathMode = false;

                // 重新订阅PathPlanningManager的鼠标事件
                PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked; // 先取消避免重复
                PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
                LogManager.Info("已重新订阅PathPlanningManager的鼠标事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"启用鼠标处理失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 自动路径规划（支持路径策略）
        /// </summary>
        /// <param name="startPoint">起点</param>
        /// <param name="endPoint">终点</param>
        /// <param name="objectRadius">物体尺寸（米）</param>
        /// <param name="safetyMargin">安全间隙（米）</param>
        /// <param name="gridSize">网格精度（米）</param>
        /// <param name="objectHeight">物体高度（米）</param>
        /// <param name="strategy">路径规划策略</param>
        /// <returns>规划结果</returns>
        public Task<PathRoute> AutoPlanPath(PathPoint startPoint, PathPoint endPoint, double objectRadius, double safetyMargin, double gridSize, double objectHeight, PathStrategy strategy)
        {
            try
            {
                if (startPoint == null || endPoint == null)
                {
                    throw new ArgumentException("起点和终点不能为空");
                }

                LogManager.Info($"开始自动路径规划: {startPoint.Name} -> {endPoint.Name}");
                LogManager.Info($"起点坐标: ({startPoint.Position.X:F2}, {startPoint.Position.Y:F2}, {startPoint.Position.Z:F2})");
                LogManager.Info($"终点坐标: ({endPoint.Position.X:F2}, {endPoint.Position.Y:F2}, {endPoint.Position.Z:F2})");
                LogManager.Info($"物体半径: {objectRadius}m, 安全间隙: {safetyMargin}m, 物体高度: {objectHeight}m");

                RaiseStatusChanged("正在进行自动路径规划...", PathPlanningStatusType.Info);

                // 1. 获取模型边界
                var bounds = GetModelBounds() ?? throw new Exception("无法获取模型边界，请确保模型已加载");
                var hostAdapter = new HostCoordinateAdapter(CoordinateSystemManager.Instance.ResolvedType);
                var hostBoundsMin = new System.Numerics.Vector3((float)bounds.Min.X, (float)bounds.Min.Y, (float)bounds.Min.Z);
                var hostBoundsMax = new System.Numerics.Vector3((float)bounds.Max.X, (float)bounds.Max.Y, (float)bounds.Max.Z);
                var (boundsMinH1, boundsMaxH1, boundsMinH2, boundsMaxH2) =
                    HostPlanarGridHelper.GetHorizontalRange3(hostBoundsMin, hostBoundsMax, hostAdapter);
                LogManager.Info($"模型边界: H1[{boundsMinH1:F2}, {boundsMaxH1:F2}], H2[{boundsMinH2:F2}, {boundsMaxH2:F2}]");

                // 智能选择网格大小
                if (gridSize <= 0)
                {
                    gridSize = CalculateOptimalGridSize(bounds);
                    LogManager.Info($"自动选择网格大小: {gridSize}米");
                }
                else
                {
                    LogManager.Info($"使用用户设置的网格大小: {gridSize}米");
                }

                // 2. 生成网格地图
                RaiseStatusChanged("正在生成网格地图...", PathPlanningStatusType.Info);
                var gridMapGenerator = new GridMapGenerator();
                GridMap gridMap = null;

                try
                {
                    var performanceStart = System.Diagnostics.Stopwatch.StartNew();

                    // 获取当前文档
                    var document = Application.ActiveDocument;
                    LogManager.Info($"网格生成参数 - 边界: H1 {boundsMinH1:F2}->{boundsMaxH1:F2}, H2 {boundsMinH2:F2}->{boundsMaxH2:F2}");
                    LogManager.Info($"网格生成参数 - 网格大小: {gridSize}m, 物体半径: {objectRadius}m, 安全边距: {safetyMargin}m");
                    LogManager.Info($"网格生成参数 - 起点: ({startPoint.Position.X:F2}, {startPoint.Position.Y:F2}, {startPoint.Position.Z:F2})");
                    LogManager.Info($"网格生成参数 - 终点: ({endPoint.Position.X:F2}, {endPoint.Position.Y:F2}, {endPoint.Position.Z:F2})");

                    try
                    {
                        gridMap = gridMapGenerator.GenerateFromBIM(
                            bounds,
                            gridSize,
                            objectRadius,
                            safetyMargin,
                            startPoint.Position,
                            endPoint.Position,
                            objectHeight
                        );
                        LogManager.Info("✅ 网格地图生成成功");
                    }
                    catch (Exception modeEx)
                    {
                        LogManager.Warning($"网格地图生成失败,{modeEx.Message}");
                    }

                    performanceStart.Stop();
                    LogManager.Info($"GridMapGenerator.GenerateFromBIM 调用完成，耗时: {performanceStart.ElapsedMilliseconds}ms");
                    LogManager.Info($"生成的网格统计: {gridMap?.GetStatistics() ?? "NULL"}");
                }
                catch (Exception ex)
                {
                    LogManager.Error($"网格地图生成失败: {ex.Message}");
                    throw; // 直接抛出原始异常，不包装
                }

                // 根据用户设置决定是否进行网格可视化
                if (_showWalkableGrid || _showObstacleGrid || _showUnknownGrid || _showDoorGrid)
                {
                    LogManager.Info("开始网格可视化，显示所有可通行网格单元");
                    VisualizeGridCells(gridMap, objectHeight);
                }

                // 3. 获取通道高度数据
                var channelItems = GetChannelItemsForHeightCalculation(gridMap);
                LogManager.Info($"获取通道数据完成: {channelItems?.Count() ?? 0} 个通道项");

                // 4. 创建ChannelCoverage对象（关键修复）
                ChannelCoverage channelCoverage = null;
                if (channelItems != null && channelItems.Any())
                {
                    LogManager.Info($"创建ChannelCoverage对象，包含 {channelItems.Count()} 个通道项");
                    channelCoverage = new ChannelCoverage
                    {
                        GridMap = gridMap,
                        ChannelItems = channelItems.ToList(),
                        TotalBounds = bounds
                    };
                    LogManager.Info($"ChannelCoverage创建完成: {channelCoverage.GetStatistics()}");
                }
                else
                {
                    LogManager.Error("未找到通道数据，无法进行路径规划");
                    throw new Exception("路径规划需要通道数据，请先进行通道检测");
                }

                // 5. 执行A*路径查找
                RaiseStatusChanged("正在计算最优路径...", PathPlanningStatusType.Info);
                LogManager.Info("=== 开始执行A*路径查找 ===");

                AutoPathFinder pathFinder = null;
                PathFindingResult pathResult = null;

                try
                {
                    pathFinder = new AutoPathFinder();
                    double objectHeightInModelUnits = objectHeight * UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
                    LogManager.Info($"使用2.5D模式进行路径查找，物体高度: {objectHeight}m ({objectHeightInModelUnits:F2}模型单位)，策略: {strategy}");
                    pathResult = pathFinder.FindPath(startPoint.Position, endPoint.Position, gridMap, channelCoverage, objectHeightInModelUnits, strategy);
                    LogManager.Info("FindPath方法调用完成");
                }
                catch (Exception ex)
                {
                    LogManager.Error($"路径查找失败: {ex.Message}");
                    throw; // 直接抛出原始异常，不包装
                }

                // 1. 检查路径查找是否完全失败
                if (pathResult == null)
                {
                    throw new Exception("路径查找失败");
                }

                // 2. 检查是否找到了可用的路径点（至少2个点才能构成路径）
                if (pathResult.PathPoints.Count < 2)
                {
                    throw new Exception("未找到可行路径（起点或终点不可达）");
                }

                // 3. 部分路径也是有效路径，不再抛出异常，继续正常处理

                LogManager.Info($"A*算法找到路径，包含 {pathResult.PathPoints.Count} 个点，完成度: {pathResult.CompletionPercentage:F1}%");

                // 6. 创建PathRoute对象并保存GridMap
                var routeName = $"自动_{DateTime.Now:MMdd_HHmmss}";

                // 🔥 关键修复：在创建路径前设置_currentGridMap，确保GetSpeedLimitAtPosition能正常工作
                _currentGridMap = gridMap;

                var autoRoute = CreateAutoPathRoute(pathResult, routeName);

                // 保存GridMap和参数到PathRoute以便后续恢复网格可视化
                autoRoute.AssociatedGridMap = gridMap;
                autoRoute.GridSize = gridSize;
                // 将objectRadius拆分为长宽（暂时使用相同值，后续可以传入更详细的参数）
                autoRoute.MaxObjectLength = objectRadius * 2;  // 物体半径转换为长度
                autoRoute.MaxObjectWidth = objectRadius * 2;   // 物体半径转换为宽度
                autoRoute.MaxObjectHeight = objectHeight;
                autoRoute.SafetyMargin = safetyMargin;
                LogManager.Info($"已保存GridMap到路径: {routeName}, 网格大小: {gridSize}米");

                // 7. 添加到路径集合
                if (!_routes.Contains(autoRoute))
                {
                    _routes.Add(autoRoute);
                }
                SetCurrentRouteInternal(autoRoute, triggerEvent: true);

                // 8. 确保路径可视化使用正确的网格大小（修复尺寸自适应问题）
                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin != null && gridMap != null)
                {
                    double gridSizeInMeters = UnitsConverter.ConvertToMeters(gridMap.CellSize);
                    renderPlugin.SetGridSize(gridSizeInMeters);
                    LogManager.Debug($"[路径可视化] 设置网格大小为 {gridSizeInMeters:F3}米，确保路径点尺寸正确");
                }

                // 9. 自动绘制路径可视化
                DrawRouteVisualization(autoRoute, isAutoPath: true);

                // 10. 强制设置路径编辑状态为查看状态（修复状态问题）
                // 在所有事件触发之前设置状态，确保不会被后续操作重置
                LogManager.Info("自动路径规划完成，强制设置状态为Viewing");
                PathEditState = PathEditState.Viewing;
                EditingRoute = null; // 确保没有编辑中的路径

                // 11. 触发事件
                RaiseRouteGenerated(autoRoute, RouteGenerationMethod.AutoPlanning, gridSize);


                var statusMessage = $"自动路径规划完成(2.5D模式): {routeName}，使用网格大小 {gridSize:F2}米";

                // 添加完成度信息
                if (!autoRoute.IsComplete)
                {
                    statusMessage += $" (完成度: {autoRoute.CompletionPercentage:F1}%)";
                }

                RaiseStatusChanged(statusMessage, PathPlanningStatusType.Success);

                LogManager.Info($"自动路径规划成功完成: 路径长度 {autoRoute.TotalLength:F2}米，包含 {autoRoute.Points.Count} 个点，使用网格大小 {gridSize:F2}米");
                return Task.FromResult(autoRoute);
            }
            catch (Exception ex)
            {
                LogManager.Error($"自动路径规划失败: {ex.Message}", ex);
                RaiseErrorOccurred(ex.Message, ex); // 使用原始异常消息，不再包装
                return Task.FromResult<PathRoute>(null);
            }
        }

        /// <summary>
        /// 设置当前路线（UI调用版本，不触发事件以避免循环）
        /// </summary>
        /// <param name="route">要设置的路线</param>
        public void SetCurrentRoute(PathRoute route)
        {
            SetCurrentRouteInternal(route, triggerEvent: false);
        }

        /// <summary>
        /// 内部设置当前路线（可选择是否触发事件）
        /// </summary>
        /// <param name="route">要设置的路线</param>
        /// <param name="triggerEvent">是否触发事件</param>
        private void SetCurrentRouteInternal(PathRoute route, bool triggerEvent)
        {
            try
            {
                // 从数据库加载路径数据（如果有的话）
                if (route != null && !string.IsNullOrEmpty(route.Id) && _pathDatabase != null)
                {
                    try
                    {
                        // 从数据库加载完整路径数据（包括路径点）
                        var loadedRoute = _pathDatabase.GetPathRouteSync(route.Id);
                        if (loadedRoute != null && loadedRoute.Points.Count > 0)
                        {
                            // 清空现有路径点并从数据库加载
                            route.Points.Clear();
                            foreach (var point in loadedRoute.Points)
                            {
                                route.Points.Add(point);
                            }
                            // 更新其他属性（不要覆盖TotalLength，因为LoadPathEdges已经根据Edges重新计算了）
                            route.LiftHeight = loadedRoute.LiftHeight;
                            route.RailMountMode = loadedRoute.RailMountMode;
                            route.RailPathDefinitionMode = loadedRoute.RailPathDefinitionMode;
                            route.RailNormalOffset = loadedRoute.RailNormalOffset;
                            route.RailPreferredNormal = loadedRoute.RailPreferredNormal != null
                                ? new Point3D(
                                    loadedRoute.RailPreferredNormal.X,
                                    loadedRoute.RailPreferredNormal.Y,
                                    loadedRoute.RailPreferredNormal.Z)
                                : null;
                            LogManager.Debug($"已从数据库加载路径数据: {route.Name}, 共 {loadedRoute.Points.Count} 个点");
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"从数据库加载路径数据失败: {ex.Message}", ex);
                    }
                }

                // 直接设置字段，绕过事件触发
                var previousRoute = _currentRoute;
                _currentRoute = route;

                // 总是触发 CurrentRouteSwitched 事件（用于剖面盒自动跟随等功能）
                CurrentRouteSwitched?.Invoke(this, new CurrentRouteChangedEventArgs(previousRoute, route, _managerId));

                // 如果需要触发事件（真正的业务操作）
                if (triggerEvent)
                {
                    RaiseCurrentRouteChanged(previousRoute, route, triggerEvent: true);
                }

                // 如果路径有关联的GridMap，加载它用于网格可视化
                if (route?.AssociatedGridMap != null)
                {
                    _currentGridMap = route.AssociatedGridMap;
                    // GridSize是模型单位，转换为米显示
                    double gridSizeMeters = UnitsConverter.ConvertToMeters(route.GridSize);
                    LogManager.Info($"已加载路径 '{route.Name}' 的GridMap，网格大小: {gridSizeMeters:F3}米");

                    // 如果网格可视化开启，立即刷新显示
                    if (IsAnyGridVisualizationEnabled)
                    {
                        LogManager.Info("检测到网格可视化已启用，自动刷新网格显示");
                        RefreshGridVisualization();
                    }
                }
                else
                {
                    // 如果路径没有GridMap，清空当前缓存
                    _currentGridMap = null;
                    if (route != null)
                    {
                        LogManager.Info($"路径 '{route.Name}' 没有关联的GridMap");

                        if (IsAnyGridVisualizationEnabled)
                        {
                            LogManager.Info("检测到网格可视化已启用，尝试按路径保存的自动规划参数重建GridMap");
                            RefreshGridVisualization();
                        }
                    }
                }

                LogManager.Info($"当前路线已设置: {route?.Name ?? "null"}");
            }
            catch (Exception ex)
            {
                LogManager.Error("设置当前路线失败", ex);
                RaiseErrorOccurred(ex.Message, ex);
            }
        }

        /// <summary>
        /// 切换到编辑状态
        /// </summary>
        /// <param name="route">要编辑的路径</param>
        public void SwitchToEditingState(PathRoute route)
        {
            if (route == null)
            {
                throw new ArgumentNullException(nameof(route));
            }

            PathEditState = PathEditState.Editing;
            EditingRoute = route;
            SetCurrentRouteInternal(route, triggerEvent: true);

            // 智能管理ToolPlugin状态
            ManageToolPluginForEditState();

            RaiseStatusChanged($"已切换到编辑状态，正在编辑路径: {route.Name}", PathPlanningStatusType.Info);
        }

        /// <summary>
        /// 选择通道模型
        /// </summary>
        /// <param name="useCurrentSelection">是否使用当前选择的模型</param>
        /// <returns>选择的通道数量</returns>
        public int SelectChannels(bool useCurrentSelection = true)
        {
            try
            {
                _walkableAreas.Clear();

                if (useCurrentSelection)
                {
                    // 使用当前选择的模型
                    var currentSelection = Application.ActiveDocument.CurrentSelection.SelectedItems;
                    if (currentSelection.Any())
                    {
                        _walkableAreas.AddRange(currentSelection);
                        RaiseStatusChanged($"已选择 {_walkableAreas.Count} 个模型作为通道", PathPlanningStatusType.Success);
                    }
                    else
                    {
                        RaiseStatusChanged("未选择任何模型，请先选择通道模型", PathPlanningStatusType.Warning);
                        return 0;
                    }
                }
                else
                {
                    // 直接使用 CategoryAttributeManager 的方法筛选通道，无需额外的包装方法
                    var document = Application.ActiveDocument;
                    if (document != null)
                    {
                        var allLogisticsItems = CategoryAttributeManager.GetAllLogisticsItems();
                        var channelItems = CategoryAttributeManager.FilterByLogisticsType(allLogisticsItems, "通道");
                        _walkableAreas.AddRange(channelItems);
                        LogManager.Info($"[SelectChannels] 通过CategoryAttributeManager直接筛选到 {channelItems.Count} 个通道");
                    }

                    RaiseStatusChanged($"通过类别筛选到 {_walkableAreas.Count} 个通道", PathPlanningStatusType.Success);
                }

                if (_walkableAreas.Any())
                {
                    // 计算组合边界
                    CalculateCombinedBounds();

                    // 触发通道选择变更事件
                    RaiseChannelSelectionChanged(_walkableAreas, useCurrentSelection ? "手动选择" : "类别筛选");
                }

                return _walkableAreas.Count;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"选择通道时发生错误: {ex.Message}", ex);
                return 0;
            }
        }

        /// <summary>
        /// 添加路径到管理器
        /// </summary>
        /// <param name="route">要添加的路径</param>
        /// <returns>是否成功添加</returns>
        public bool AddRoute(PathRoute route)
        {
            try
            {
                if (route == null)
                {
                    RaiseErrorOccurred("无法添加空路径");
                    return false;
                }

                // 检查是否已存在同名路径
                var existingRoute = _routes.FirstOrDefault(r => r.Name == route.Name);
                if (existingRoute != null)
                {
                    // 如果存在同名路径，生成唯一名称
                    int counter = 1;
                    string originalName = route.Name;
                    while (_routes.Any(r => r.Name == route.Name))
                    {
                        route.Name = $"{originalName}_{counter}";
                        counter++;
                    }
                }

                _routes.Add(route);
                RaiseStatusChanged($"已添加路径: {route.Name}", PathPlanningStatusType.Success);

                // 保存到数据库
                SavePathToDatabase(route);

                // AddRoute只负责添加路径到数据集合，不自动设置当前路径
                // 路径选择应该通过专门的选择逻辑处理，而不是添加操作的副作用
                // if (_currentRoute == null || _currentRoute.Points.Count == 0)
                // {
                //     CurrentRoute = route;
                // }

                // 注释掉多余的路径生成事件调用，Manual类型路径通过UI层的RefreshPathRoutes()统一刷新
                // RaiseRouteGenerated(route, RouteGenerationMethod.Manual);

                return true;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"添加路径失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 创建新路径
        /// </summary>
        /// <param name="routeName">路径名称</param>
        /// <returns>新创建的路径</returns>
        public PathRoute CreateNewRoute(string routeName = null)
        {
            if (string.IsNullOrEmpty(routeName))
            {
                routeName = $"路径_{_routes.Count + 1}";
            }

            var newRoute = new PathRoute(routeName);
            _routes.Add(newRoute);
            SetCurrentRouteInternal(newRoute, triggerEvent: true);

            // 保存到数据库
            SavePathToDatabase(newRoute);

            RaiseStatusChanged($"已创建新路径: {routeName}", PathPlanningStatusType.Success);
            return newRoute;
        }

        /// <summary>
        /// 删除路径
        /// </summary>
        /// <param name="route">要删除的路径</param>
        /// <returns>是否成功删除</returns>
        public bool DeleteRoute(PathRoute route)
        {
            if (route == null) return false;

            try
            {
                bool removed = _routes.Remove(route);
                if (removed)
                {
                    // 从数据库删除
                    if (_pathDatabase != null)
                    {
                        try
                        {
                            _pathDatabase.DeletePathRoute(route.Id);
                            LogManager.Info($"已从数据库删除路径: {route.Name}");
                        }
                        catch (Exception dbEx)
                        {
                            LogManager.Error($"从数据库删除路径失败: {dbEx.Message}", dbEx);
                            // 继续执行，不影响内存操作
                        }
                    }

                    if (_currentRoute == route)
                    {
                        var newRoute = _routes.FirstOrDefault() ?? new PathRoute("默认路径");
                        SetCurrentRouteInternal(newRoute, triggerEvent: true);
                    }
                    RaiseStatusChanged($"已删除路径: {route.Name}", PathPlanningStatusType.Success);
                }
                return removed;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"删除路径时发生错误: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 生成路径
        /// </summary>
        /// <param name="route">要生成的路径，为null时使用当前路径</param>
        /// <returns>是否成功生成</returns>
        public bool GeneratePath(PathRoute route = null)
        {
            route = route ?? _currentRoute;
            if (route == null) return false;

            try
            {
                // 验证路径有效性
                if (!route.IsValid())
                {
                    RaiseErrorOccurred("路径无效：必须包含至少一个起点和一个终点");
                    return false;
                }

                // 更新路径关联的通道ID
                route.AssociatedChannelIds.Clear();
                foreach (var channel in _walkableAreas)
                {
                    route.AssociatedChannelIds.Add(channel.InstanceGuid.ToString());
                }

                // 计算预估时间（简单实现）
                CalculateEstimatedTime(route);

                RaiseStatusChanged($"路径生成成功: {route.Name}, 长度: {route.TotalLength:F2}米, 预估时间: {route.EstimatedTime:F1}秒", PathPlanningStatusType.Success);
                RaiseRouteGenerated(route, RouteGenerationMethod.Manual);
                return true;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"生成路径时发生错误: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 开始新建路径
        /// </summary>
        /// <param name="routeName">路径名称</param>
        /// <param name="isRailPath">是否为空轨路径</param>
        /// <param name="pathType">路径类型（默认为地面路径）</param>
        /// <returns>创建的新路径</returns>
        public PathRoute StartCreatingNewRoute(string routeName = null, bool isRailPath = false, PathType pathType = PathType.Ground)
        {
            try
            {
                // 空轨路径不需要自动选择可通行物流模型
                if (!isRailPath && pathType == PathType.Ground)
                {
                    // 自动选择所有可通行的物流模型（先检查是否有可通行的模型）
                    AutoSelectLogisticsChannels();

                    // 检查是否有可通行的物流模型
                    if (_walkableAreas == null || _walkableAreas.Count == 0)
                    {
                        RaiseErrorOccurred("没有找到任何可通行的物流模型，请先为模型设置可通行的物流属性");
                        // 不需要重置状态，因为还没有进入创建状态
                        return null;
                    }
                }

                // 设置为创建状态
                PathEditState = PathEditState.Creating;

                // 创建新路径，并设置路径类型
                var newRoute = new PathRoute(routeName ?? $"人工_{DateTime.Now:MMdd_HHmmss}")
                {
                    PathType = pathType
                };

                if (pathType == PathType.Rail)
                {
                    newRoute.RailPathDefinitionMode = RailPathDefinitionMode.RailCenterLine;
                }

                _editingRoute = newRoute;
                
                // 立即添加到路径集合，确保UI能正确找到Core路径
                if (!_routes.Contains(newRoute))
                {
                    _routes.Add(newRoute);
                }
                
                SetCurrentRouteInternal(newRoute, triggerEvent: true);

                // 如果是吊装路径，清理吊装模式相关状态
                if (pathType == PathType.Hoisting)
                {
                    _enableHoistingMode = false;  // 将在StartClickTool中设置为true
                    _hoistingStartPoint = null;
                    _hoistingLiftHeight = 0;
                    _hoistingGroundIntermediatePoints.Clear();
                    LogManager.Debug($"[吊装模式] 已清理吊装模式状态，准备新建吊装路径");
                }

                // 智能管理ToolPlugin状态
                ManageToolPluginForEditState();

                string statusMessage;
                if (pathType == PathType.Rail || pathType == PathType.Hoisting)
                {
                    statusMessage = $"正在新建空中路径: {newRoute.Name} - 请在3D视图中设置路径点";
                }
                else if (pathType == PathType.Free)
                {
                    statusMessage = $"正在新建自由路径: {newRoute.Name} - 请在3D视图中连续点击设置物体中心轨迹点";
                }
                else
                {
                    statusMessage = $"正在新建地面路径: {newRoute.Name} - 请在3D视图中可通行的物流模型上点击设置路径点";
                }

                RaiseStatusChanged(statusMessage, PathPlanningStatusType.Info);

                return newRoute;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"开始新建路径失败: {ex.Message}", ex);
                // 确保在出错时也重置状态
                SwitchToViewingState();
                return null;
            }
        }

        /// <summary>
        /// 完成当前编辑并保存
        /// </summary>
        /// <returns>是否成功完成编辑</returns>
        /// <summary>
        /// 完成路径编辑
        /// </summary>
        public bool FinishEditing()
        {
            if (!IsInEditableState)
            {
                RaiseErrorOccurred("当前不在编辑状态，无法完成编辑");
                return false;
            }

            try
            {
                // 根据路径类型执行不同的完成逻辑
                if (CurrentRoute != null && CurrentRoute.Points.Count > 1)
                {
                    // 地面路径、空轨路径、自由路径：自动设置最后一个点为终点
                    if (CurrentRoute.PathType == PathType.Ground ||
                        CurrentRoute.PathType == PathType.Rail ||
                        CurrentRoute.PathType == PathType.Free)
                    {
                        var lastPoint = CurrentRoute.Points.Last();
                        if (lastPoint.Type != PathPointType.StartPoint) // 起点不能是终点
                        {
                            lastPoint.Type = PathPointType.EndPoint;
                            lastPoint.Name = GeneratePointName(PathPointType.EndPoint);

                            // 更新3D路径可视化
                            // 重新渲染整个路径以反映类型变更
                            _renderPlugin?.RenderPath(CurrentRoute);

                            string pathTypeName = CurrentRoute.PathType == PathType.Ground ? "地面路径" :
                                CurrentRoute.PathType == PathType.Rail ? "空轨路径" : "自由路径";
                            LogManager.Info($"[{pathTypeName}] 已自动设置最后一个点为终点: {lastPoint.Name}");
                        }
                    }
                    // 吊装路径：添加下降点和落地点
                    else if (CurrentRoute.PathType == PathType.Hoisting)
                    {
                        LogManager.Info($"[吊装路径] 正在完成吊装路径，处理终点和下降点");
                        
                        // 确保至少有起吊点、提升点
                        if (CurrentRoute.Points.Count >= 2)
                        {
                            // 获取起吊点（用于获取地面Z坐标）
                            var startPoint = CurrentRoute.Points.First();
                            
                            // 获取最后一个路径点（用于获取当前的空中XY位置）
                            var lastPoint = CurrentRoute.Points.Last();
                            LogManager.Info($"[吊装路径] 最后一个路径点: {lastPoint.Name}, 位置: ({lastPoint.Position.X:F2}, {lastPoint.Position.Y:F2}, {lastPoint.Position.Z:F2})");
                            
                            var descendPoint = ReuseLastHoistingPointAsDescendPoint(CurrentRoute.Points);
                            LogManager.Info($"[吊装路径] 已将最后一个空中点复用为下降点（终点正上方）: ({descendPoint.Position.X:F2}, {descendPoint.Position.Y:F2}, {descendPoint.Position.Z:F2})");
                            
                            Point3D finalGroundPoint = _hoistingGroundIntermediatePoints.Count > 0
                                ? _hoistingGroundIntermediatePoints[_hoistingGroundIntermediatePoints.Count - 1]
                                : SetHoistingElevation(lastPoint.Position, GetHoistingElevation(startPoint.Position));

                            // 创建落地点（终点）：使用用户最后一次点击的地面点，避免把终点高程错误吸回起点
                            var endPoint = new PathPoint(
                                finalGroundPoint,
                                "落地点",
                                PathPointType.EndPoint);
                            endPoint.Direction = HoistingPointDirection.Vertical;
                            endPoint.Index = CurrentRoute.Points.Count;
                            LogManager.Info($"[吊装路径] 已创建落地点（终点）: ({endPoint.Position.X:F2}, {endPoint.Position.Y:F2}, {endPoint.Position.Z:F2})");

                            // 添加落地点（终点）
                            CurrentRoute.Points.Add(endPoint);
                            LogManager.Info($"[吊装路径] 已复用最后一个空中点作为下降点，并添加落地点，当前共 {CurrentRoute.Points.Count} 个路径点");
                            
                            // 注意：不需要再次调用 OrthogonalizePath，因为添加的只是垂直线段
                            // 垂直线段不会形成斜线，所以不需要优化
                            
                            // 注意：TotalLength 现在是计算属性，自动从几何数据计算，无需手动更新
                            
                            // 检测并移除同一高度层的矩形环路
                            LogManager.Info($"[吊装路径] 开始检测矩形环路，当前路径点数: {CurrentRoute?.Points?.Count ?? 0}");
                            bool loopsRemoved = RemoveRectangularLoops(CurrentRoute);
                            LogManager.Info($"[吊装路径] 矩形环路检测完成，是否移除环路: {loopsRemoved}");
                            
                            // 重新渲染路径
                            _renderPlugin?.RenderPath(CurrentRoute);
                            
                            LogManager.Info($"[吊装路径] 已完成吊装路径，共 {CurrentRoute.Points.Count} 个路径点");
                            
                            // 清理吊装模式临时变量
                            _hoistingStartPoint = null;
                            _hoistingLiftHeight = 0;
                            _hoistingGroundIntermediatePoints.Clear();
                            _enableHoistingMode = false;
                            LogManager.Debug($"[吊装路径] 已清理吊装模式临时变量");
                        }
                        else
                        {
                            LogManager.Warning($"[吊装路径] 路径点不足或没有地面点击记录，无法完成吊装路径");
                        }
                    }
                }

                // 如果是创建模式或添加点模式，将当前路径添加到路径集合
                if ((PathEditState == PathEditState.Creating || PathEditState == PathEditState.AddingPoints) && CurrentRoute != null)
                {
                    if (!_routes.Contains(CurrentRoute))
                    {
                        _routes.Add(CurrentRoute);

                        // 添加历史记录
                        var historyEntry = new PathHistoryEntry(
                            CurrentRoute.Id,
                            PathHistoryOperationType.Created,
                            CurrentRoute,
                            $"创建新路径: {CurrentRoute.Name}");
                        _historyManager.AddHistoryEntry(historyEntry);
                    }
                }

                // 如果是编辑模式，保存编辑历史
                if (_pathEditState == PathEditState.Editing && EditingRoute != null)
                {
                    var historyEntry = new PathHistoryEntry(
                        EditingRoute.Id,
                        PathHistoryOperationType.Edited,
                        EditingRoute,
                        $"编辑路径: {EditingRoute.Name}");
                    _historyManager.AddHistoryEntry(historyEntry);
                }

                // 切换回查看状态
                SwitchToViewingState();

                // 触发路径点列表更新事件
                RaisePathPointsListUpdated(CurrentRoute, "编辑完成");

                // 结束编辑后主动再同步一次当前路径，确保UI中的占位路径能回填完整点列表
                SetCurrentRouteInternal(CurrentRoute, triggerEvent: true);

                // 触发路径生成事件
                RaiseRouteGenerated(CurrentRoute, RouteGenerationMethod.Manual);

                RaiseStatusChanged("路径编辑已完成", PathPlanningStatusType.Success);
                return true;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"完成编辑失败: {ex.Message}", ex);
                return false;
            }
        }

        #region 修改路径点功能

        /// <summary>
        /// 开始修改指定的路径点
        /// </summary>
        /// <param name="pointIndex">要修改的路径点索引</param>
        /// <returns>是否成功开始修改</returns>
        public bool StartEditingPoint(int pointIndex)
        {
            try
            {
                if (CurrentRoute == null || pointIndex < 0 || pointIndex >= CurrentRoute.Points.Count)
                {
                    RaiseErrorOccurred("无效的路径点索引或当前没有路径");
                    return false;
                }

                // 保存原始点和索引
                _editingPointIndex = pointIndex;
                var originalPoint = CurrentRoute.Points[pointIndex];
                _originalPoint = new PathPoint
                {
                    Id = originalPoint.Id,
                    Name = originalPoint.Name,
                    Position = originalPoint.Position,
                    Type = originalPoint.Type
                };

                // 切换到修改路径点状态
                PathEditState = PathEditState.EditingPoint;

                // 激活ToolPlugin以接收3D点击
                ActivateToolPlugin();

                RaiseStatusChanged($"开始修改路径点: {_originalPoint.Name}", PathPlanningStatusType.Info);
                LogManager.Info($"开始修改路径点，索引: {pointIndex}, 名称: {_originalPoint.Name}");

                return true;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"开始修改路径点失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 设置修改路径点时的预览位置
        /// </summary>
        /// <param name="position">新的预览位置</param>
        public void SetEditingPreviewPoint(Point3D position)
        {
            try
            {
                if (PathEditState != PathEditState.EditingPoint || _editingPointIndex == -1)
                {
                    return;
                }

                // 创建预览路径点
                _editingPreviewPoint = new PathPoint
                {
                    Position = position,
                    Name = _originalPoint.Name + "_预览",
                    Type = _originalPoint.Type
                };

                // 更新预览可视化
                UpdateEditingPreviewVisualization();

                LogManager.Info($"设置修改预览点: ({position.X:F3}, {position.Y:F3}, {position.Z:F3})");
            }
            catch (Exception ex)
            {
                LogManager.Error($"设置修改预览点失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 更新吊装路径的关联点（通用方法）
        /// </summary>
        /// <param name="route">路径</param>
        /// <param name="modifiedPointIndex">修改的点的索引</param>
        private void UpdateAerialPathRelatedPoints(PathRoute route, int modifiedPointIndex)
        {
            if (route == null || route.PathType != PathType.Hoisting)
            {
                return;
            }

            var points = route.Points;
            if (points.Count == 0)
            {
                return;
            }

            // 修改起点（索引0）：更新提升点（索引1）的X,Y坐标，同步所有空中点Z
            if (modifiedPointIndex == 0 && points.Count > 1)
            {
                var startPoint = points[0];
                var liftPoint = points[1];
                double newAerialElevation = GetHoistingElevation(startPoint.Position) + route.LiftHeight;
                liftPoint.Position = SetHoistingElevation(startPoint.Position, newAerialElevation);
                // 同步所有其他空中点Z坐标（索引2到n-2）
                for (int i = 2; i <= points.Count - 2; i++)
                {
                    points[i].Position = SetHoistingElevation(points[i].Position, newAerialElevation);
                }
                LogManager.Debug($"[吊装路径] 修改起点，更新提升点位置: ({liftPoint.Position.X:F2}, {liftPoint.Position.Y:F2}, {liftPoint.Position.Z:F2})，同步所有空中点Z坐标");
            }
            // 修改终点（最后一个点）：更新下降点（倒数第二个点）的X,Y坐标
            else if (modifiedPointIndex == points.Count - 1 && points.Count > 1)
            {
                var endPoint = points[modifiedPointIndex];
                var descendPoint = points[modifiedPointIndex - 1];
                descendPoint.Position = SetHoistingElevation(endPoint.Position, GetHoistingElevation(descendPoint.Position));
                LogManager.Debug($"[吊装路径] 修改终点，更新下降点位置: ({descendPoint.Position.X:F2}, {descendPoint.Position.Y:F2}, {descendPoint.Position.Z:F2})");
            }
        }

        /// <summary>
        /// 检测两点之间是否为斜线，如果是则插入中间转折点或修正坐标
        /// 处理三种斜线：XY平面斜线、XZ平面斜线、YZ平面斜线
        /// </summary>
        /// <param name="points">路径点列表</param>
        /// <param name="startIndex">开始检查的索引</param>
        /// <returns>是否进行了修改（插入点或修正坐标）</returns>
        private bool InsertIntermediatePointForDiagonal(IList<PathPoint> points, int startIndex)
        {
            if (points == null || startIndex < 0 || startIndex >= points.Count - 1)
            {
                return false;
            }

            var currentPoint = points[startIndex];
            var nextPoint = points[startIndex + 1];

            // 使用 Info 级别日志以便调试
            LogManager.Debug($"[斜线处理] 检查索引 {startIndex} 和 {startIndex + 1} 之间的连线");
            LogManager.Debug($"[斜线处理] 当前点 [{startIndex}]: {currentPoint.Name}, 位置: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})");
            LogManager.Debug($"[斜线处理] 下一点 [{startIndex + 1}]: {nextPoint.Name}, 位置: ({nextPoint.Position.X:F2}, {nextPoint.Position.Y:F2}, {nextPoint.Position.Z:F2})");

            Point3D canonicalCurrent = ToHoistingCanonicalPoint(currentPoint.Position);
            Point3D canonicalNext = ToHoistingCanonicalPoint(nextPoint.Position);

            double deltaX = Math.Abs(canonicalNext.X - canonicalCurrent.X);
            double deltaY = Math.Abs(canonicalNext.Y - canonicalCurrent.Y);
            double deltaZ = Math.Abs(canonicalNext.Z - canonicalCurrent.Z);

            LogManager.Debug($"[斜线处理] deltaX={deltaX:F2}, deltaY={deltaY:F2}, deltaZ={deltaZ:F2}");

            // 检测三种斜线
            bool isXYDiagonal = deltaX > 0.01 && deltaY > 0.01 && deltaZ < 0.001;  // XY平面斜线
            bool isXZDiagonal = deltaX > 0.01 && deltaZ > 0.001 && deltaY < 0.01;  // XZ平面斜线
            bool isYZDiagonal = deltaY > 0.01 && deltaZ > 0.001 && deltaX < 0.01;  // YZ平面斜线
            bool isXYZDiagonal = deltaX > 0.01 && deltaY > 0.01 && deltaZ > 0.001; // XYZ空间斜线

            LogManager.Debug($"[斜线处理] 斜线检测结果: XY={isXYDiagonal}, XZ={isXZDiagonal}, YZ={isYZDiagonal}, XYZ={isXYZDiagonal}");

            if (!isXYDiagonal && !isXZDiagonal && !isYZDiagonal && !isXYZDiagonal)
            {
                LogManager.Debug($"[斜线处理] 未检测到斜线，跳过处理");
                return false;
            }

            // 处理XY平面斜线（水平斜线）
            if (isXYDiagonal)
            {
                return HandleXYDiagonal(points, startIndex, currentPoint, nextPoint, deltaX, deltaY);
            }

            // 处理XZ平面斜线（垂直斜线：X和Z同时变化）
            if (isXZDiagonal)
            {
                return HandleXZDiagonal(points, startIndex, currentPoint, nextPoint, deltaX, deltaZ);
            }

            // 处理YZ平面斜线（垂直斜线：Y和Z同时变化）
            if (isYZDiagonal)
            {
                return HandleYZDiagonal(points, startIndex, currentPoint, nextPoint, deltaY, deltaZ);
            }

            // 处理XYZ空间斜线（X、Y、Z都变化）
            if (isXYZDiagonal)
            {
                return HandleXYZDiagonal(points, startIndex, currentPoint, nextPoint, deltaX, deltaY, deltaZ);
            }

            return false;
        }

        /// <summary>
        /// 处理XY平面斜线（水平斜线）
        /// 策略：插入中间点将斜线拆分为直角转折，保持用户点击的坐标不变
        /// </summary>
        private bool HandleXYDiagonal(IList<PathPoint> points, int startIndex, PathPoint currentPoint, PathPoint nextPoint, double deltaX, double deltaY)
        {
            LogManager.Debug($"[斜线处理] 检测到XY平面斜线 (deltaX={deltaX:F2}, deltaY={deltaY:F2})");

            // 策略：插入中间点，将斜线拆分为 X-only → Y-only 的两段直角路径
            // 不修改用户点击的坐标，只插入转折点
            // 转折点：X用新点的X，Y用旧点的Y（先X方向移动，再Y方向移动）
            return InsertIntermediatePoint(points, startIndex, currentPoint, nextPoint,
                CreateHorizontalTurnPoint(currentPoint.Position, nextPoint.Position, HoistingPointDirection.Longitudinal),
                HoistingPointDirection.Longitudinal);
        }

        /// <summary>
        /// 处理XZ平面斜线（垂直斜线：X和Z同时变化）
        /// 策略：先水平移动（X变化，Z不变），再垂直移动（Z变化，X不变）
        /// </summary>
        private bool HandleXZDiagonal(IList<PathPoint> points, int startIndex, PathPoint currentPoint, PathPoint nextPoint, double deltaX, double deltaZ)
        {
            LogManager.Debug($"[斜线处理] 检测到XZ平面斜线 (deltaX={deltaX:F2}, deltaZ={deltaZ:F2})");

            // 插入中间点：先水平移动（到新X，旧Z），目标点自然就是（新X，新Z）
            return InsertIntermediatePoint(points, startIndex, currentPoint, nextPoint,
                CreateHorizontalTurnPoint(currentPoint.Position, nextPoint.Position, HoistingPointDirection.Longitudinal),
                HoistingPointDirection.Longitudinal);
        }

        /// <summary>
        /// 处理YZ平面斜线（垂直斜线：Y和Z同时变化）
        /// 策略：先水平移动（Y变化，Z不变），再垂直移动（Z变化，Y不变）
        /// </summary>
        private bool HandleYZDiagonal(IList<PathPoint> points, int startIndex, PathPoint currentPoint, PathPoint nextPoint, double deltaY, double deltaZ)
        {
            LogManager.Debug($"[斜线处理] 检测到YZ平面斜线 (deltaY={deltaY:F2}, deltaZ={deltaZ:F2})");

            // 插入中间点：先水平移动（到新Y，旧Z），目标点自然就是（新Y，新Z）
            return InsertIntermediatePoint(points, startIndex, currentPoint, nextPoint,
                CreateHorizontalTurnPoint(currentPoint.Position, nextPoint.Position, HoistingPointDirection.Lateral),
                HoistingPointDirection.Lateral);
        }

        /// <summary>
        /// 处理XYZ空间斜线（X、Y、Z都变化）
        /// 策略：先水平移动（XY平面，Z不变），再垂直移动（Z变化，XY不变）
        /// 水平移动时如果XY也是斜线，则进一步拆分
        /// </summary>
        private bool HandleXYZDiagonal(IList<PathPoint> points, int startIndex, PathPoint currentPoint, PathPoint nextPoint, double deltaX, double deltaY, double deltaZ)
        {
            LogManager.Debug($"[斜线处理] 检测到XYZ空间斜线 (deltaX={deltaX:F2}, deltaY={deltaY:F2}, deltaZ={deltaZ:F2})");

            // 分两步：
            // 1. 先水平移动到目标XY（保持当前Z）
            // 2. 再垂直移动到目标Z（保持XY不变）

            // 如果水平移动也是斜线（X和Y都变化），则先处理XY斜线
            if (deltaX > 0.01 && deltaY > 0.01)
            {
                // 插入中间点：先X方向移动（保持Y），到目标X后再处理Y和Z
                return InsertIntermediatePoint(points, startIndex, currentPoint, nextPoint,
                    CreateHorizontalTurnPoint(currentPoint.Position, nextPoint.Position, HoistingPointDirection.Longitudinal),
                    HoistingPointDirection.Longitudinal);
            }
            else
            {
                // 水平方向只有一个轴变化，直接插入中间点处理垂直斜线
                // 选择变化较大的水平轴作为先移动的方向
                if (deltaX > deltaY)
                {
                    return InsertIntermediatePoint(points, startIndex, currentPoint, nextPoint,
                        CreateHorizontalTurnPoint(currentPoint.Position, nextPoint.Position, HoistingPointDirection.Longitudinal),
                        HoistingPointDirection.Longitudinal);
                }
                else
                {
                    return InsertIntermediatePoint(points, startIndex, currentPoint, nextPoint,
                        CreateHorizontalTurnPoint(currentPoint.Position, nextPoint.Position, HoistingPointDirection.Lateral),
                        HoistingPointDirection.Lateral);
                }
            }
        }

        /// <summary>
        /// 插入中间点的辅助方法
        /// </summary>
        private bool InsertIntermediatePoint(IList<PathPoint> points, int startIndex, PathPoint currentPoint, PathPoint nextPoint,
            Point3D intermediatePosition, HoistingPointDirection direction)
        {
            int intermediateIndex = points.Count > 0 ? points.Count : 1;
            var intermediatePoint = new PathPoint(intermediatePosition, $"路径点{intermediateIndex}", PathPointType.WayPoint);
            intermediatePoint.Direction = direction;

            int insertPosition = startIndex + 1;
            points.Insert(insertPosition, intermediatePoint);

            // 更新所有点的索引
            for (int i = 0; i < points.Count; i++)
            {
                points[i].Index = i;
            }

            LogManager.Debug($"[斜线处理] 已插入中间点: {intermediatePoint.Name}, 位置: ({intermediatePoint.Position.X:F2}, {intermediatePoint.Position.Y:F2}, {intermediatePoint.Position.Z:F2}) - 方向: {direction}");
            LogManager.Debug($"[斜线处理] 插入位置: 索引 {insertPosition}, 当前路径点总数: {points.Count}");

            return true;
        }

        /// <summary>
        /// 正交化路径：将斜线路径转换为轴对齐的直角路径
        /// 出现斜线时插入转折点，使所有线段平行于X、Y或Z轴
        /// </summary>
        /// <param name="route">要正交化的路径</param>
        /// <param name="startIndex">开始正交化的索引，默认从0开始（处理所有点）。用于增量处理，避免修改已处理的点。</param>
        /// <returns>是否进行了正交化</returns>
        public bool OrthogonalizePath(PathRoute route, int startIndex = 0)
        {
            if (route == null || route.Points.Count < 2)
            {
                return false;
            }

            // 确保startIndex有效
            if (startIndex < 0) startIndex = 0;
            if (startIndex >= route.Points.Count - 1) return false;

            bool hasChanges = false;
            var points = route.Points;
            double tolerance = 0.001; // 容差，用于判断是否在同一直线上
            double minDistance = 1.0; // 最小距离阈值，小于此距离不删除点

            // 第一步：处理斜线，插入转折点或修正坐标
            // 从startIndex开始，只处理新添加的点
            int i = startIndex;
            while (i < points.Count - 1)
            {
                int originalCount = points.Count;
                if (InsertIntermediatePointForDiagonal(points, i))
                {
                    hasChanges = true;
                    // 如果插入了点，points.Count会增加
                    // 新插入的点在位置i+1，继续检查从i开始
                    if (points.Count > originalCount)
                    {
                        // 插入了点，继续检查当前索引（因为插入点可能需要进一步优化）
                        LogManager.Info($"[直角路径优化] 索引{i}处插入了点，继续检查");
                    }
                    else
                    {
                        // 只修改了坐标，继续下一个点
                        i++;
                    }
                }
                else
                {
                    i++;
                }
            }

            // 第二步：清除在同一直线上的多余点
            // 只检查从startIndex开始的新插入点，避免修改已处理的路径
            int startForCollinear = Math.Max(1, startIndex);
            i = startForCollinear;
            while (i < points.Count - 1)
            {
                var prevPoint = points[i - 1];
                var currentPoint = points[i];
                var nextPoint = points[i + 1];

                // 只删除普通的WayPoint，不删除起点、终点、起吊点、提升点、下降点等特殊点
                if (currentPoint.Type != PathPointType.WayPoint)
                {
                    i++;
                    continue;
                }

                // 额外检查：不删除提升点和下降点（通过名称识别）
                if (currentPoint.Name == "提升点" || currentPoint.Name == "下降点")
                {
                    i++;
                    continue;
                }

                // 判断三个点是否在同一直线上（统一在 Canonical 水平面上判断）
                Point3D canonicalPrevPoint = ToHoistingCanonicalPoint(prevPoint.Position);
                Point3D canonicalCurrentPoint = ToHoistingCanonicalPoint(currentPoint.Position);
                Point3D canonicalNextPoint = ToHoistingCanonicalPoint(nextPoint.Position);
                double deltaZ1 = Math.Abs(canonicalCurrentPoint.Z - canonicalPrevPoint.Z);
                double deltaZ2 = Math.Abs(canonicalNextPoint.Z - canonicalCurrentPoint.Z);
                bool sameZ = deltaZ1 < tolerance && deltaZ2 < tolerance;
                
                // 如果Z不同，这三个点一定不共线（一个是垂直过渡点）
                if (!sameZ)
                {
                    i++;
                    continue;
                }
                
                // 在同一平面上，检查XY方向是否共线
                bool sameX = Math.Abs(canonicalPrevPoint.X - canonicalCurrentPoint.X) < tolerance &&
                             Math.Abs(canonicalCurrentPoint.X - canonicalNextPoint.X) < tolerance;
                bool sameY = Math.Abs(canonicalPrevPoint.Y - canonicalCurrentPoint.Y) < tolerance &&
                             Math.Abs(canonicalCurrentPoint.Y - canonicalNextPoint.Y) < tolerance;

                bool isCollinear = sameX || sameY;

                // 额外检查：中间点到前后两点的距离都大于最小距离
                if (isCollinear)
                {
                    double distToPrev = GeometryHelper.CalculatePointDistance(currentPoint.Position, prevPoint.Position);
                    double distToNext = GeometryHelper.CalculatePointDistance(currentPoint.Position, nextPoint.Position);

                    if (distToPrev > minDistance || distToNext > minDistance)
                    {
                        // 删除中间点
                        points.RemoveAt(i);
                        hasChanges = true;
                        LogManager.Info($"[直角路径优化] 删除共线的多余点 {i}: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})");

                        // 不调整索引，因为删除了一个点，新位置的点会在下一次循环被检查
                        continue;
                    }
                    else
                    {
                        LogManager.Debug($"[直角路径优化] 跳过距离过近的共线点 {i}: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})");
                    }
                }

                i++;
            }

            if (hasChanges)
            {
                // 注意：TotalLength 现在是计算属性，自动从几何数据计算，无需手动更新
                LogManager.Info($"[直角路径优化] 路径点优化完成，当前点数: {points.Count}, 路径长度: {route.TotalLength:F2}米");
            }

            return hasChanges;
        }

        /// <summary>
        /// 检测并移除各水平层内的矩形环路
        /// 限制条件：
        /// 1. 只处理同一水平层内的点（Z坐标必须完全相同，只考虑浮点数精度误差）
        /// 2. 不允许处理起点（索引0）和终点（最后一个点）
        /// 3. 不允许跨层检测（不同Z高度的线段不互相检测）
        /// 4. 支持多层吊装路径（多个不同高度的水平层）
        /// 算法原理：按Z坐标分组（严格相等），对每个水平层分别检测正交路径中的相交线段
        /// </summary>
        /// <param name="route">路径</param>
        /// <returns>是否移除了环路</returns>
        public bool RemoveRectangularLoops(PathRoute route)
        {
            if (route == null || route.Points.Count < 4)
            {
                return false;
            }

            bool hasChanges = false;
            var points = route.Points;
            // 浮点数精度容差，用于判断Z坐标是否相等
            const double epsilon = 1e-9;
            
            LogManager.Debug($"[环路检测] 开始检测，路径点数: {points.Count}");

            // 按Z坐标分组，找出所有水平层（排除起点和终点）
            // 使用严格相等比较（只考虑浮点数精度误差）
            var layers = new Dictionary<double, List<int>>();
            for (int i = 1; i < points.Count - 1; i++) // 跳过起点(0)和终点(Count-1)
            {
                double z = GetHoistingElevation(points[i].Position);
                
                // 查找是否已有相同Z坐标的层（考虑浮点数精度）
                bool found = false;
                foreach (var key in layers.Keys)
                {
                    if (Math.Abs(z - key) < epsilon)
                    {
                        layers[key].Add(i);
                        found = true;
                        break;
                    }
                }
                
                if (!found)
                {
                    layers[z] = new List<int> { i };
                }
            }
            
            LogManager.Debug($"[环路检测] 发现{layers.Count}个水平层");
            
            // 按Z坐标从高到低排序处理
            var sortedLayers = layers.OrderByDescending(l => l.Key).ToList();
            int totalDeletedPoints = 0; // 记录已删除的点数，用于更新后续层的索引
            
            // 对每个水平层分别进行环路检测
            for (int layerIdx = 0; layerIdx < sortedLayers.Count; layerIdx++)
            {
                var layer = sortedLayers[layerIdx];
                double layerZ = layer.Key;
                var layerIndices = layer.Value.OrderBy(idx => idx).ToList();
                
                // 更新索引：减去之前层删除的点数
                for (int i = 0; i < layerIndices.Count; i++)
                {
                    layerIndices[i] -= totalDeletedPoints;
                }
                
                // 过滤掉无效索引（小于0或超出范围）
                layerIndices = layerIndices.Where(idx => idx >= 0 && idx < points.Count).ToList();
                
                if (layerIndices.Count < 2)
                {
                    LogManager.Debug($"[环路检测] 层 Z={layerZ:F2} 剩余点太少，跳过");
                    continue; // 该层点太少，无法形成环路
                }
                
                LogManager.Debug($"[环路检测] 处理水平层 Z={layerZ:F2}，包含{layerIndices.Count}个，索引范围: {layerIndices.First()}-{layerIndices.Last()}");
                
                // 对该层进行环路检测
                int pointsBefore = points.Count;
                bool layerHasChanges = RemoveLoopsInLayer(points, layerIndices, epsilon);
                int pointsDeleted = pointsBefore - points.Count;
                totalDeletedPoints += pointsDeleted;
                
                if (layerHasChanges)
                {
                    hasChanges = true;
                }
            }

            if (hasChanges)
            {
                LogManager.Debug($"[环路检测] 完成，当前路径点数: {points.Count}");
            }

            return hasChanges;
        }
        
        /// <summary>
        /// 对单个水平层进行环路检测和移除
        /// </summary>
        /// <param name="points">路径点列表</param>
        /// <param name="layerIndices">该层的点索引列表（已排序）</param>
        /// <param name="epsilon">浮点数精度容差</param>
        /// <returns>是否移除了环路</returns>
        private bool RemoveLoopsInLayer(List<PathPoint> points, List<int> layerIndices, double epsilon)
        {
            if (layerIndices.Count < 2)
            {
                return false;
            }
            
            bool hasChanges = false;
            double layerZ = GetHoistingElevation(points[layerIndices[0]].Position);
            
            // 在该层内进行环路检测
            // n和m是layerIndices列表中的索引位置
            int n = 0;  // 第一个线段的起始索引（在layerIndices中的位置）
            int m = 2;  // 第二个线段相对于n的偏移（在layerIndices中的位置）
            
            while (n + m + 1 < layerIndices.Count)
            {
                // 获取实际的路径点索引
                int idx1 = layerIndices[n];     // 线段1起点
                int idx2 = layerIndices[n + 1]; // 线段1终点
                int idx3 = layerIndices[n + m];     // 线段2起点
                int idx4 = layerIndices[n + m + 1]; // 线段2终点
                
                // 获取线段坐标
                var p1 = points[idx1].Position;
                var p2 = points[idx2].Position;
                var p3 = points[idx3].Position;
                var p4 = points[idx4].Position;
                
                // 确保所有点都在同一层（水平线段，Z坐标严格相同，只考虑浮点数精度）
                if (Math.Abs(GetHoistingElevation(p1) - layerZ) > epsilon || 
                    Math.Abs(GetHoistingElevation(p2) - layerZ) > epsilon ||
                    Math.Abs(GetHoistingElevation(p3) - layerZ) > epsilon ||
                    Math.Abs(GetHoistingElevation(p4) - layerZ) > epsilon)
                {
                    m++;
                    if (n + m + 1 >= layerIndices.Count)
                    {
                        m = 2;
                        n++;
                    }
                    continue;
                }
                
                // 检测两条正交线段是否相交
                Point3D intersection;
                if (GetOrthogonalSegmentIntersection(p1, p2, p3, p4, out intersection))
                {
                    LogManager.Debug($"[环路检测] 层Z={layerZ:F2} 发现相交: 线段{idx1}({points[idx1].Name}-{points[idx2].Name}) 与 线段{idx3}({points[idx3].Name}-{points[idx4].Name})");
                    LogManager.Debug($"[环路检测] 交点: ({intersection.X:F4}, {intersection.Y:F4}, {intersection.Z:F4})");
                    
                    // 检查中间点是否包含特殊点
                    bool containsSpecialPoint = false;
                    for (int k = idx1 + 1; k <= idx3; k++)
                    {
                        if (points[k].Type != PathPointType.WayPoint ||
                            points[k].Name == "提升点" || 
                            points[k].Name == "下降点" ||
                            points[k].Name == "起吊点" ||
                            points[k].Name == "落地点")
                        {
                            containsSpecialPoint = true;
                            break;
                        }
                    }

                    if (containsSpecialPoint)
                    {
                        LogManager.Debug("[环路检测] 环路包含特殊点，跳过");
                        m++;
                        if (n + m + 1 >= layerIndices.Count)
                        {
                            m = 2;
                            n++;
                        }
                        continue;
                    }

                    // 用交点替换 points[idx2]
                    points[idx2].Position = intersection;
                    points[idx2].Name = "路径点";
                    
                    // 删除中间点 (idx2+1 到 idx3)
                    int d = idx3 - idx2;  // 要删除的点数
                    for (int i = idx3 + 1; i < points.Count; i++)
                    {
                        points[i - d] = points[i];
                    }
                    // 移除末尾多余的点
                    points.RemoveRange(points.Count - d, d);
                    
                    // 更新layerIndices（因为删除了点）
                    for (int i = 0; i < layerIndices.Count; i++)
                    {
                        if (layerIndices[i] > idx2 && layerIndices[i] <= idx3)
                        {
                            // 这些点被删除了，标记为-1
                            layerIndices[i] = -1;
                        }
                        else if (layerIndices[i] > idx3)
                        {
                            // 这些点的索引需要向前移动
                            layerIndices[i] -= d;
                        }
                    }
                    layerIndices.RemoveAll(idx => idx == -1);
                    
                    // 从交点重新开始检测
                    m = 2;
                    hasChanges = true;
                    LogManager.Info($"[环路优化] 层Z={layerZ:F2} 已移除环路，删除{d}个点");
                    continue;
                }
                
                m++;
                if (n + m + 1 >= layerIndices.Count)
                {
                    m = 2;
                    n++;
                }
            }

            return hasChanges;
        }

        /// <summary>
        /// 计算两条正交线段的交点
        /// </summary>
        /// <returns>是否相交（线段内部相交，非端点）</returns>
        private bool GetOrthogonalSegmentIntersection(Point3D a1, Point3D a2, Point3D b1, Point3D b2, out Point3D intersection)
        {
            intersection = new Point3D(0, 0, 0);

            Point3D canonicalA1 = ToHoistingCanonicalPoint(a1);
            Point3D canonicalA2 = ToHoistingCanonicalPoint(a2);
            Point3D canonicalB1 = ToHoistingCanonicalPoint(b1);
            Point3D canonicalB2 = ToHoistingCanonicalPoint(b2);

            // 判断线段A是水平还是垂直（在 Canonical 水平面 XY 中）
            bool aIsHorizontal = Math.Abs(canonicalA1.Y - canonicalA2.Y) < 0.001;
            bool aIsVertical = Math.Abs(canonicalA1.X - canonicalA2.X) < 0.001;

            // 判断线段B是水平还是垂直
            bool bIsHorizontal = Math.Abs(canonicalB1.Y - canonicalB2.Y) < 0.001;
            bool bIsVertical = Math.Abs(canonicalB1.X - canonicalB2.X) < 0.001;

            // 必须一条水平一条垂直才可能形成矩形环路
            if ((aIsHorizontal && bIsHorizontal) || (aIsVertical && bIsVertical))
            {
                return false;
            }

            // 确保a是水平，b是垂直
            if (aIsVertical && bIsHorizontal)
            {
                // 交换
                var temp1 = canonicalA1; var temp2 = canonicalA2;
                canonicalA1 = canonicalB1; canonicalA2 = canonicalB2;
                canonicalB1 = temp1; canonicalB2 = temp2;
                aIsHorizontal = true; aIsVertical = false;
                bIsHorizontal = false; bIsVertical = true;
            }

            if (!aIsHorizontal || !bIsVertical)
            {
                return false;
            }

            // 水平线段A: y = a1.Y, x范围 [min(a1.X,a2.X), max(a1.X,a2.X)]
            // 垂直线段B: x = b1.X, y范围 [min(b1.Y,b2.Y), max(b1.Y,b2.Y)]
            
            double aY = canonicalA1.Y;
            double bX = canonicalB1.X;
            double aMinX = Math.Min(canonicalA1.X, canonicalA2.X);
            double aMaxX = Math.Max(canonicalA1.X, canonicalA2.X);
            double bMinY = Math.Min(canonicalB1.Y, canonicalB2.Y);
            double bMaxY = Math.Max(canonicalB1.Y, canonicalB2.Y);

            // 检查垂直线段的X是否在水平线段的X范围内（不包括端点）
            // 且水平线段的Y是否在垂直线段的Y范围内（不包括端点）
            const double eps = 0.001;
            
            bool xInRange = bX > aMinX + eps && bX < aMaxX - eps;
            bool yInRange = aY > bMinY + eps && aY < bMaxY - eps;

            if (xInRange && yInRange)
            {
                intersection = GetHoistingHostAdapter().FromCanonicalPoint(new Point3D(
                    bX,
                    aY,
                    canonicalA1.Z));
                return true;
            }

            return false;
        }

        /// <summary>
        /// 更新路径点位置（保存修改）
        /// </summary>
        /// <returns>是否成功更新</returns>
        public bool UpdatePointPosition()
        {
            try
            {
                if (PathEditState != PathEditState.EditingPoint ||
                    _editingPointIndex == -1 ||
                    _editingPreviewPoint == null ||
                    CurrentRoute == null)
                {
                    RaiseErrorOccurred("当前不在修改路径点状态或没有预览点");
                    return false;
                }

                // 吊装路径：调用专用方法处理
                if (CurrentRoute.PathType == PathType.Hoisting)
                {
                    return UpdateHoistingPathPointPosition();
                }

                // 更新路径点位置（非吊装路径）
                var pointToUpdate = CurrentRoute.Points[_editingPointIndex];
                pointToUpdate.Position = _editingPreviewPoint.Position;

                // 核心修复：调用统一更新函数
                CurrentRoute.RecalculateAndSaveRoute($"修改路径点 {pointToUpdate.Name} 位置");

                // 添加历史记录
                var historyEntry = new PathHistoryEntry(
                    CurrentRoute.Id,
                    PathHistoryOperationType.Edited,
                    CurrentRoute,
                    $"修改路径点 {pointToUpdate.Name} 位置");
                _historyManager.AddHistoryEntry(historyEntry);

                // 清理修改预览可视化（会自动清除预览并重新渲染正常路径）
                ClearEditingPreviewVisualization();

                // 清理修改状态
                ClearEditingState();

                // 切换回查看状态
                PathEditState = PathEditState.Viewing;

                // 停用ToolPlugin
                DeactivateToolPlugin();

                // 更新可视化
                DrawRouteVisualization(CurrentRoute, isAutoPath: false);

                // 立即保存到数据库
                SavePathToDatabase(CurrentRoute);

                // 触发路径点列表更新事件
                RaisePathPointsListUpdated(CurrentRoute, "路径点修改完成");

                RaiseStatusChanged($"路径点 {pointToUpdate.Name} 修改完成", PathPlanningStatusType.Success);
                LogManager.Info($"路径点修改完成: {pointToUpdate.Name}");

                return true;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"确认修改路径点失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 更新路径点位置（带约束的公共方法）
        /// </summary>
        /// <remarks>
        /// 根据路径类型智能处理坐标更新：
        /// - 吊装路径：
        ///   - 空中路径点（提升点、下降点、中间路径点）：只更新XY坐标，保留原有Z坐标（吊装高度）
        ///   - 地面路径点（起吊点、落地点）：更新完整XYZ坐标
        /// - 其他路径类型：更新完整XYZ坐标
        /// </remarks>
        /// <param name="route">路径</param>
        /// <param name="pointIndex">路径点索引</param>
        /// <param name="newPosition">新位置</param>
        /// <returns>是否成功更新</returns>
        public bool UpdatePathPointWithConstraints(PathRoute route, int pointIndex, Point3D newPosition)
        {
            try
            {
                if (route == null || pointIndex < 0 || pointIndex >= route.Points.Count)
                {
                    LogManager.Error($"UpdatePathPointWithConstraints: 无效的参数，route={route}, pointIndex={pointIndex}");
                    return false;
                }

                var pointToUpdate = route.Points[pointIndex];

                // 吊装路径：智能处理Z坐标
                if (route.PathType == PathType.Hoisting)
                {
                    if (route.IsTwoPointVertical)
                    {
                        // 2点垂直路径：自由修改坐标，不限制高度，更新保存的提升高度
                        pointToUpdate.Position = newPosition;
                        route.LiftHeight = Math.Abs(GetHoistingElevation(route.Points[1].Position) - GetHoistingElevation(route.Points[0].Position));
                        LogManager.Info($"[更新路径点] 2点垂直路径 {pointToUpdate.Name}，提升高度已更新为: {UnitsConverter.ConvertToMeters(route.LiftHeight):F3}米");
                        RaiseStatusChanged($"吊装高度: {UnitsConverter.ConvertToMeters(route.LiftHeight):F3}米", PathPlanningStatusType.Info);
                    }
                    else
                    {
                    bool isLiftPoint = pointToUpdate.Name == "提升点";
                    bool isDescendPoint = pointToUpdate.Name == "下降点";
                    bool isStartPoint = pointToUpdate.Name == "起吊点";
                    bool isEndPoint = pointToUpdate.Name == "落地点";

                    // 🔥 新功能：允许修改提升点和下降点的Z坐标来调整吊装高度
                    if (isLiftPoint || isDescendPoint)
                    {
                        // 修改提升点或下降点的Z坐标，同步更新所有空中路径点的Z坐标
                        double newHoistingHeight = GetHoistingElevation(newPosition);
                        double originalZ = GetHoistingElevation(pointToUpdate.Position);
                        double heightDelta = newHoistingHeight - originalZ;

                        // 更新当前点的宿主水平位置与高程
                        pointToUpdate.Position = SetHoistingElevation(newPosition, newHoistingHeight);

                        // 同步更新所有空中路径点的Z坐标
                        foreach (var point in route.Points)
                        {
                            // 只更新空中路径点（提升点、下降点、中间路径点）
                            // 跳过当前正在修改的点，避免重复更新
                            if (point.Name != "起吊点" && point.Name != "落地点" && point != pointToUpdate)
                            {
                                point.Position = OffsetPointAlongHoistingUp(point.Position, heightDelta);
                            }
                        }

                        // 🔥 更新路径的提升高度属性（内部使用模型单位）
                        double hoistingHeightModelUnits = CalculateHoistingHeight(route);
                        route.LiftHeight = hoistingHeightModelUnits;
                        LogManager.Info($"[更新路径点] 吊装路径 {pointToUpdate.Name}，提升高度已调整为: {UnitsConverter.ConvertToMeters(hoistingHeightModelUnits):F3}米");
                        
                        // 使用路径的 LiftHeight 属性显示提升高度（内部是模型单位，转换为米显示）
                        RaiseStatusChanged($"吊装高度: {UnitsConverter.ConvertToMeters(route.LiftHeight):F3}米", PathPlanningStatusType.Info);
                    }
                    // 空中路径点（非提升点、下降点）：只更新XY坐标，保持原有吊装高度
                    else if (!isStartPoint && !isEndPoint)
                    {
                        double originalZ = GetHoistingElevation(pointToUpdate.Position);
                        pointToUpdate.Position = SetHoistingElevation(newPosition, originalZ);
                        LogManager.Info($"[更新路径点] 吊装路径空中点 {pointToUpdate.Name}，保留原有高度: {originalZ:F3}");
                    }
                    // 起吊点/落地点：更新完整位置
                    else
                    {
                        pointToUpdate.Position = newPosition;
                        LogManager.Info($"[更新路径点] 吊装路径地面点 {pointToUpdate.Name}，更新完整位置");
                    }

                    // 吊装路径：自动更新关联点（仅当修改起吊点或落地点时）
                    // 注意：修改提升点/下降点时，已经在上面同步更新了所有空中路径点，不需要再次调用
                    if (isStartPoint || isEndPoint)
                    {
                        UpdateAerialPathRelatedPoints(route, pointIndex);
                    }

                    // 吊装路径：正交化路径（处理斜线和清除多余点）
                    OrthogonalizePath(route);
                    
                    // 吊装路径：检测并移除矩形环路
                    LogManager.Info($"[吊装路径] 修改路径点后检测矩形环路");
                    RemoveRectangularLoops(route);
                    }
                }
                else
                {
                    // 其他路径类型：更新完整位置
                    pointToUpdate.Position = newPosition;
                    LogManager.Info($"[更新路径点] {route.PathType}路径点 {pointToUpdate.Name}，更新完整位置");
                }

                // 调用统一更新函数
                route.RecalculateAndSaveRoute($"更新路径点 {pointToUpdate.Name} 位置");

                // 保存到数据库
                SavePathToDatabase(route);

                // 触发路径点列表更新事件
                RaisePathPointsListUpdated(route, "路径点更新完成");

                LogManager.Info($"路径点更新完成: {pointToUpdate.Name}");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"UpdatePathPointWithConstraints 失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 计算吊装路径的提升高度
        /// </summary>
        /// <param name="route">吊装路径</param>
        /// <returns>提升高度（从起吊点到提升点的高度差）</returns>
        private HostCoordinateAdapter GetHoistingHostAdapter()
        {
            return CoordinateSystemManager.Instance.CreateHostAdapter();
        }

        private Point3D ToHoistingCanonicalPoint(Point3D hostPoint)
        {
            return GetHoistingHostAdapter().ToCanonicalPoint(hostPoint);
        }

        private double GetHoistingElevation(Point3D point)
        {
            return HoistingCoordinateHelper.GetElevation(point, GetHoistingHostAdapter());
        }

        private Point3D SetHoistingElevation(Point3D point, double elevation)
        {
            return HoistingCoordinateHelper.SetElevation(point, elevation, GetHoistingHostAdapter());
        }

        private Point3D OffsetPointAlongHoistingUp(Point3D point, double offset)
        {
            return HoistingCoordinateHelper.OffsetAlongUp(point, offset, GetHoistingHostAdapter());
        }

        private Point3D CreateHorizontalTurnPoint(Point3D currentPoint, Point3D nextPoint, HoistingPointDirection direction)
        {
            bool keepCurrentFirstHorizontalAxis = direction == HoistingPointDirection.Lateral;
            return HoistingCoordinateHelper.CreateHorizontalTurnPoint(
                currentPoint,
                nextPoint,
                keepCurrentFirstHorizontalAxis,
                GetHoistingHostAdapter());
        }

        private double CalculateHoistingHeight(PathRoute route)
        {
            if (route == null || route.PathType != PathType.Hoisting || route.Points.Count < 2)
            {
                return 0.0;
            }

            // 找到起吊点和提升点
            var startPoint = route.Points.FirstOrDefault(p => p.Name == "起吊点");
            var liftPoint = route.Points.FirstOrDefault(p => p.Name == "提升点");

            if (startPoint == null || liftPoint == null)
            {
                return 0.0;
            }

            // 计算高度差（沿宿主 up）
            return GetHoistingElevation(liftPoint.Position) - GetHoistingElevation(startPoint.Position);
        }

        /// <summary>
        /// 更新吊装路径点位置（专用方法，用于3D修改流程）
        /// </summary>
        /// <remarks>
        /// 智能处理吊装路径点的坐标更新：
        /// - 空中路径点（提升点、下降点、中间路径点）：只更新XY坐标，保留原有Z坐标（吊装高度）
        /// - 地面路径点（起吊点、落地点）：更新完整XYZ坐标
        /// </remarks>
        /// <returns>是否成功更新</returns>
        private bool UpdateHoistingPathPointPosition()
        {
            try
            {
                if (PathEditState != PathEditState.EditingPoint ||
                    _editingPointIndex == -1 ||
                    _editingPreviewPoint == null ||
                    CurrentRoute == null)
                {
                    RaiseErrorOccurred("当前不在修改路径点状态或没有预览点");
                    return false;
                }

                // 调用公共方法处理
                bool success = UpdatePathPointWithConstraints(CurrentRoute, _editingPointIndex, _editingPreviewPoint.Position);

                if (success)
                {
                    // 添加历史记录
                    var pointToUpdate = CurrentRoute.Points[_editingPointIndex];
                    var historyEntry = new PathHistoryEntry(
                        CurrentRoute.Id,
                        PathHistoryOperationType.Edited,
                        CurrentRoute,
                        $"修改吊装路径点 {pointToUpdate.Name} 位置");
                    _historyManager.AddHistoryEntry(historyEntry);

                    // 清理修改预览可视化（会自动清除预览并重新渲染正常路径）
                    ClearEditingPreviewVisualization();

                    // 清理修改状态
                    ClearEditingState();

                    // 切换回查看状态
                    PathEditState = PathEditState.Viewing;

                    // 停用ToolPlugin
                    DeactivateToolPlugin();

                    // 更新可视化
                    DrawRouteVisualization(CurrentRoute, isAutoPath: false);

                    RaiseStatusChanged($"吊装路径点 {pointToUpdate.Name} 修改完成", PathPlanningStatusType.Success);
                }

                return success;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"确认修改吊装路径点失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 取消修改路径点
        /// </summary>
        /// <returns>是否成功取消修改</returns>
        public bool CancelEditPoint()
        {
            try
            {
                if (PathEditState != PathEditState.EditingPoint)
                {
                    return true; // 已经不在修改状态，认为成功
                }

                // 清理修改状态
                ClearEditingState();

                // 切换回查看状态
                PathEditState = PathEditState.Viewing;

                // 停用ToolPlugin
                DeactivateToolPlugin();

                // 清理预览可视化
                ClearEditingPreviewVisualization();

                RaiseStatusChanged("已取消路径点修改", PathPlanningStatusType.Info);
                LogManager.Info("已取消路径点修改");

                return true;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"取消修改路径点失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 清理修改路径点的状态
        /// </summary>
        private void ClearEditingState()
        {
            _editingPointIndex = -1;
            _originalPoint = null;
            _editingPreviewPoint = null;
        }

        /// <summary>
        /// 更新修改路径点时的预览可视化
        /// </summary>
        private void UpdateEditingPreviewVisualization()
        {
            try
            {
                if (_renderPlugin == null || CurrentRoute == null || _editingPreviewPoint == null)
                {
                    return;
                }

                // 创建预览路径，替换修改中的路径点
                var previewRoute = CurrentRoute.Clone() as PathRoute;
                previewRoute.Points[_editingPointIndex] = _editingPreviewPoint;

                // 渲染预览路径（使用特殊的预览样式）
                _renderPlugin.RenderPreviewPath(previewRoute);
            }
            catch (Exception ex)
            {
                LogManager.Error($"更新修改预览可视化失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 清理修改路径点时的预览可视化
        /// </summary>
        private void ClearEditingPreviewVisualization()
        {
            try
            {
                if (_renderPlugin == null)
                {
                    return;
                }

                // 清理预览渲染，恢复原始路径渲染
                _renderPlugin.ClearPreview();

                if (CurrentRoute != null)
                {
                    _renderPlugin.RenderPath(CurrentRoute);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"清理修改预览可视化失败: {ex.Message}");
            }
        }

        #endregion

        /// <summary>
        /// 取消当前编辑
        /// </summary>
        /// <returns>是否成功取消编辑</returns>
        public bool CancelEditing()
        {
            if (!IsInEditableState)
            {
                RaiseErrorOccurred("当前不在编辑状态，无法取消编辑");
                return false;
            }

            try
            {
                // 如果是创建模式，清理当前路径
                if (_pathEditState == PathEditState.Creating && CurrentRoute != null)
                {
                    CurrentRoute.Points.Clear();
                    LogManager.Info("已清理新建路径的临时数据");
                }

                // 切换回查看状态
                SwitchToViewingState();

                RaiseStatusChanged("路径编辑已取消", PathPlanningStatusType.Info);
                return true;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"取消编辑失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 在3D视图中添加路径点
        /// </summary>
        /// <param name="worldPoint">3D世界坐标</param>
        /// <param name="pointType">路径点类型，为null时使用当前类型</param>
        /// <returns>添加的路径点，失败时返回null</returns>
        public PathPoint AddPathPointIn3D(Point3D worldPoint, PathPointType? pointType = null)
        {
            // 确保在编辑状态下才能添加点
            if (!IsInEditableState)
            {
                RaiseErrorOccurred("不在编辑状态，无法添加路径点");
                return null;
            }

            // 如果没有当前路径，则无法添加
            if (CurrentRoute == null)
            {
                RaiseErrorOccurred("内部错误：当前路径丢失");
                return null;
            }

            try
            {
                // 确定路径点类型
                PathPointType finalPointType;
                if (pointType.HasValue)
                {
                    finalPointType = pointType.Value;
                }
                else
                {
                    // 自动判断类型：第一个点为起点，其余为路径点
                    finalPointType = (CurrentRoute.Points.Count == 0)
                        ? PathPointType.StartPoint
                        : PathPointType.WayPoint;
                }

                // 创建路径点
                var pathPoint = new PathPoint
                {
                    Name = GeneratePointName(finalPointType),
                    Position = worldPoint,
                    Type = finalPointType
                };

                CurrentRoute.AddPoint(pathPoint);
                LogManager.Info($"路径点已添加: {pathPoint.Name}, 位置: ({worldPoint.X:F2}, {worldPoint.Y:F2}, {worldPoint.Z:F2})");

                // 绘制3D路径可视化（使用与自动路径规划相同的方法）
                try
                {
                    DrawRouteVisualization(CurrentRoute, isAutoPath: false);
                    LogManager.Info($"手工路径3D可视化已更新: {pathPoint.Name}");
                }
                catch (Exception renderEx)
                {
                    LogManager.Error($"绘制手工路径3D可视化失败: {renderEx.Message}");
                }

                // 触发路径点添加事件
                RaisePathPointOperation(PathPointOperationType.Added, pathPoint, CurrentRoute);

                // 触发路径列表更新事件
                RaisePathPointsListUpdated(CurrentRoute, "添加路径点");

                return pathPoint;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"添加路径点失败: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 在3D视图中插入路径点（在指定位置）
        /// </summary>
        /// <param name="worldPoint">3D世界坐标</param>
        /// <param name="pointType">点类型</param>
        /// <returns>插入的路径点</returns>
        public PathPoint InsertPathPointIn3D(Point3D worldPoint, PathPointType? pointType = null)
        {
            var insertInfo = FindNearestLineSegmentWithIndex(worldPoint, CurrentRoute.Points);
            
            if (!insertInfo.HasValue)
            {
                throw new InvalidOperationException("无法确定插入位置");
            }

            PathPointType finalPointType = pointType ?? PathPointType.WayPoint;

            var pathPoint = new PathPoint
            {
                Name = GeneratePointName(finalPointType),
                Position = worldPoint,
                Type = finalPointType
            };

            CurrentRoute.InsertPoint(pathPoint, insertInfo.Value.insertIndex);
            
            DrawRouteVisualization(CurrentRoute, isAutoPath: false);

            RaisePathPointOperation(PathPointOperationType.Inserted, pathPoint, CurrentRoute);
            RaisePathPointsListUpdated(CurrentRoute, "插入路径点");

            return pathPoint;
        }

        /// <summary>
        /// 设置预览点位置（仅用于预览，不添加到路径中）
        /// </summary>
        /// <param name="worldPoint">3D世界坐标</param>
        /// <param name="pointType">点类型</param>
        /// <returns>预览点对象</returns>
        public PathPoint SetPreviewPoint(Point3D worldPoint, PathPointType? pointType = null)
        {
            // 确保在编辑状态下才能设置预览点
            if (!IsInEditableState)
            {
                RaiseErrorOccurred("不在编辑状态，无法设置预览点");
                return null;
            }

            // 如果没有当前路径，则无法设置预览点
            if (CurrentRoute == null)
            {
                RaiseErrorOccurred("内部错误：当前路径丢失");
                return null;
            }

            try
            {
                // 确定路径点类型
                PathPointType finalPointType;
                if (pointType.HasValue)
                {
                    finalPointType = pointType.Value;
                }
                else
                {
                    // 自动判断类型：第一个点为起点，其余为路径点
                    finalPointType = (CurrentRoute.Points.Count == 0)
                        ? PathPointType.StartPoint
                        : PathPointType.WayPoint;
                }

                // 计算预览点应该插入的位置
                _previewInsertIndex = -1; // 重置插入索引
                if (CurrentRoute.Points.Count >= 2)
                {
                    // 如果路径中有至少2个点，计算最佳插入位置
                    var nearestSegment = FindNearestLineSegmentWithIndex(worldPoint, CurrentRoute.Points.ToList());
                    if (nearestSegment.HasValue)
                    {
                        _previewInsertIndex = nearestSegment.Value.insertIndex;
                        LogManager.Info($"预览点计算出插入索引: {_previewInsertIndex}，位于 {nearestSegment.Value.prevPoint.Name} 和 {nearestSegment.Value.nextPoint.Name} 之间");
                    }
                }

                // 创建预览点（不添加到路径中）
                _previewPoint = new PathPoint
                {
                    Name = $"预览-{GeneratePointName(finalPointType)}",
                    Position = worldPoint,
                    Type = finalPointType
                };

                _isPreviewMode = true;
                LogManager.Info($"预览点已设置: {_previewPoint.Name}, 位置: ({worldPoint.X:F2}, {worldPoint.Y:F2}, {worldPoint.Z:F2}), 插入索引: {_previewInsertIndex}");

                // 绘制预览点可视化（灰色）
                try
                {
                    DrawPreviewPointVisualization(_previewPoint);
                    LogManager.Info($"预览点3D可视化已更新: {_previewPoint.Name}");

                    // 如果路径中有足够的点，绘制预览连线
                    if (CurrentRoute.Points.Count >= 2)
                    {
                        DrawPreviewLinesVisualization(_previewPoint, CurrentRoute.Points.ToList());
                        LogManager.Info($"预览连线已绘制: {_previewPoint.Name}");
                    }
                }
                catch (Exception renderEx)
                {
                    LogManager.Error($"绘制预览点3D可视化失败: {renderEx.Message}");
                }

                return _previewPoint;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"设置预览点失败: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 将预览点添加为正式路径点
        /// </summary>
        /// <returns>添加的路径点，如果失败返回null</returns>
        public PathPoint ConvertPreviewToPathPoint()
        {
            if (!_isPreviewMode || _previewPoint == null)
            {
                RaiseErrorOccurred("没有预览点可确认");
                return null;
            }

            if (CurrentRoute == null)
            {
                RaiseErrorOccurred("内部错误：当前路径丢失");
                return null;
            }

            try
            {
                PathPoint confirmPoint;
                
                // 吊装路径：使用专门的空中路径点生成逻辑
                if (CurrentRoute.PathType == PathType.Hoisting)
                {
                    LogManager.Info($"[预览点-吊装路径] 开始创建空中路径点");
                    
                    // 获取上一个路径点
                    Point3D previousPoint;
                    int previousPointIndex;
                    
                    if (_previewInsertIndex >= 0 && _previewInsertIndex < CurrentRoute.Points.Count)
                    {
                        // 插入模式：上一个点是插入位置前的一个点
                        previousPointIndex = _previewInsertIndex - 1;
                        previousPoint = CurrentRoute.Points[previousPointIndex].Position;
                        LogManager.Info($"[预览点-吊装路径] 插入模式，上一个点索引: {previousPointIndex}, 名称: {CurrentRoute.Points[previousPointIndex].Name}");
                    }
                    else if (CurrentRoute.Points.Count > 0)
                    {
                        // 追加模式：上一个点是最后一个点
                        previousPointIndex = CurrentRoute.Points.Count - 1;
                        previousPoint = CurrentRoute.Points[previousPointIndex].Position;
                        LogManager.Info($"[预览点-吊装路径] 追加模式，上一个点索引: {previousPointIndex}, 名称: {CurrentRoute.Points[previousPointIndex].Name}");
                    }
                    else
                    {
                        LogManager.Error("[预览点-吊装路径] 没有上一个路径点");
                        return null;
                    }
                    
                    // 获取吊装高度（LiftHeight内部是模型单位）
                    double liftHeightModelUnits = CurrentRoute.LiftHeight > 0 
                        ? CurrentRoute.LiftHeight 
                        : UnitsConverter.ConvertFromMeters(3.0);
                    double targetElevation = GetHoistingElevation(CurrentRoute.Points[0].Position) + liftHeightModelUnits;
                    
                    // 使用 AerialPathGenerator 生成空中路径点
                    var generator = new AerialPathGenerator();
                    confirmPoint = generator.GenerateSmartHoistingPoint(
                        previousPoint,
                        _previewPoint.Position,  // 用户点击的地面位置
                        targetElevation,
                        CurrentRoute.Points.Count > 0 ? CurrentRoute.Points.Count : 1);
                    
                    LogManager.Info($"[预览点-吊装路径] 已生成空中路径点: {confirmPoint.Name}, 位置: ({confirmPoint.Position.X:F2}, {confirmPoint.Position.Y:F2}, {confirmPoint.Position.Z:F2})");
                    
                    // 插入到正确位置
                    int optimizeStartIndex;
                    if (_previewInsertIndex >= 0 && _previewInsertIndex <= CurrentRoute.Points.Count)
                    {
                        CurrentRoute.InsertPoint(confirmPoint, _previewInsertIndex);
                        LogManager.Info($"[预览点-吊装路径] 已插入到索引 {_previewInsertIndex}");
                        // 从插入位置的前一个点开始优化
                        optimizeStartIndex = Math.Max(0, _previewInsertIndex - 1);
                    }
                    else
                    {
                        // 追加模式：记录添加前的点数
                        optimizeStartIndex = Math.Max(0, CurrentRoute.Points.Count - 1);
                        CurrentRoute.AddPoint(confirmPoint);
                        LogManager.Info($"[预览点-吊装路径] 已追加到末尾");
                    }
                    
                    // 调用正交化方法处理斜线、微小转折和共线点（增量处理）
                    OrthogonalizePath(CurrentRoute, optimizeStartIndex);
                    LogManager.Info($"[预览点-吊装路径] 路径优化完成，当前路径点数: {CurrentRoute.Points.Count}");
                }
                else
                {
                    // 非吊装路径：创建普通路径点
                    confirmPoint = new PathPoint
                    {
                        Name = GeneratePointName(_previewPoint.Type),
                        Position = _previewPoint.Position,
                        Type = _previewPoint.Type
                    };
                    
                    // 根据保存的插入索引决定添加方式
                    if (_previewInsertIndex >= 0 && _previewInsertIndex <= CurrentRoute.Points.Count)
                    {
                        CurrentRoute.InsertPoint(confirmPoint, _previewInsertIndex);
                    }
                    else
                    {
                        CurrentRoute.AddPoint(confirmPoint);
                    }
                }

                // 清除预览状态
                ClearPreviewPoint();

                // 绘制3D路径可视化
                DrawRouteVisualization(CurrentRoute, isAutoPath: false);

                // 触发路径点添加事件
                RaisePathPointOperation(PathPointOperationType.Added, confirmPoint, CurrentRoute);

                // 触发路径列表更新事件
                RaisePathPointsListUpdated(CurrentRoute, "确认添加预览点");

                return confirmPoint;
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"确认预览点失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 清除预览点
        /// </summary>
        public void ClearPreviewPoint()
        {
            if (_isPreviewMode && _previewPoint != null)
            {
                LogManager.Info($"清除预览点: {_previewPoint.Name}");

                // 清除预览点可视化
                try
                {
                    ClearPreviewPointVisualization();
                }
                catch (Exception ex)
                {
                    LogManager.Error($"清除预览点可视化失败: {ex.Message}");
                }
            }

            _previewPoint = null;
            _isPreviewMode = false;
            _previewInsertIndex = -1; // 清除保存的插入索引
        }

        /// <summary>
        /// 绘制预览点可视化（灰色）
        /// </summary>
        /// <param name="previewPoint">预览点</param>
        private void DrawPreviewPointVisualization(PathPoint previewPoint)
        {
            if (_renderPlugin != null && previewPoint != null)
            {
                // 先清除之前的预览点
                _renderPlugin.ClearPreviewPoint();

                // 绘制新的灰色预览点
                _renderPlugin.RenderPreviewPoint(previewPoint);
                LogManager.Info($"预览点可视化已绘制: {previewPoint.Name}");
            }
        }

        /// <summary>
        /// 绘制预览连线的3D可视化（灰色）
        /// </summary>
        /// <param name="previewPoint">预览点</param>
        /// <param name="pathPoints">当前路径点列表</param>
        private void DrawPreviewLinesVisualization(PathPoint previewPoint, List<PathPoint> pathPoints)
        {
            if (_renderPlugin != null && previewPoint != null && pathPoints != null)
            {
                // 绘制预览连线
                _renderPlugin.RenderPreviewLines(previewPoint, pathPoints);
                LogManager.Info($"预览连线可视化已绘制: {previewPoint.Name}");
            }
        }

        /// <summary>
        /// 清除预览点可视化
        /// </summary>
        private void ClearPreviewPointVisualization()
        {
            if (_renderPlugin != null)
            {
                _renderPlugin.ClearPreviewPoint();
                LogManager.Info("预览点可视化已清除");
            }
        }

        /// <summary>
        /// 获取路径统计信息
        /// </summary>
        /// <returns>统计信息字符串</returns>
        public string GetStatistics()
        {
            var stats = $"通道数量: {_walkableAreas.Count}\n";
            stats += $"路径数量: {_routes.Count}\n";

            if (_currentRoute != null)
            {
                stats += $"当前路径: {_currentRoute.Name}\n";
                stats += $"路径点数: {_currentRoute.Points.Count}\n";
                stats += $"路径长度: {_currentRoute.TotalLength:F2}米\n";
                stats += $"预估时间: {_currentRoute.EstimatedTime:F1}秒\n";
            }

            if (_combinedChannelBounds != null)
            {
                double scaleX = 0, scaleY = 0;
                _coordinateConverter?.GetMapScale(out scaleX, out scaleY);
                stats += $"通道范围: {_combinedChannelBounds.MinPoint.X:F2},{_combinedChannelBounds.MinPoint.Y:F2} - {_combinedChannelBounds.MaxPoint.X:F2},{_combinedChannelBounds.MaxPoint.Y:F2}\n";
                stats += $"地图缩放: {scaleX:F4}, {scaleY:F4}";
            }

            return stats;
        }

        /// <summary>
        /// 验证路径管理器状态
        /// </summary>
        /// <returns>验证结果</returns>
        public PathPlanningResult ValidateManagerState()
        {
            try
            {
                var errors = new List<string>();

                // 检查基础组件
                if (_categoryManager == null)
                    errors.Add("类别属性管理器未初始化");

                if (_uiStateManager == null)
                    errors.Add("UI状态管理器未初始化");

                // 检查Navisworks环境
                var document = Application.ActiveDocument;
                if (document == null)
                    errors.Add("当前没有活动的Navisworks文档");
                else if (document.Models == null || !document.Models.Any())
                    errors.Add("当前文档中没有加载的模型");

                // 检查通道选择状态
                if (_walkableAreas.Count == 0)
                    errors.Add("没有选择任何通道模型");

                if (errors.Count > 0)
                {
                    return PathPlanningResult.ValidationFailure($"路径管理器状态验证失败: {string.Join("; ", errors)}");
                }

                return PathPlanningResult.Success("路径管理器状态验证通过");
            }
            catch (Exception ex)
            {
                LogManager.Error("验证路径管理器状态时发生异常", ex);
                return PathPlanningResult.ValidationFailure($"状态验证异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 验证路径有效性
        /// </summary>
        /// <param name="route">要验证的路径</param>
        /// <returns>验证结果</returns>
        public PathPlanningResult ValidateRoute(PathRoute route)
        {
            try
            {
                if (route == null)
                    return PathPlanningResult.ValidationFailure("路径不能为空");

                var errors = new List<string>();
                var warnings = new List<string>();

                // 基本验证
                if (string.IsNullOrWhiteSpace(route.Name))
                    errors.Add("路径名称不能为空");

                if (route.Points.Count < 2)
                    errors.Add("路径至少需要包含2个点");

                // 点类型验证
                var startPoints = route.Points.Where(p => p.Type == PathPointType.StartPoint).ToList();
                var endPoints = route.Points.Where(p => p.Type == PathPointType.EndPoint).ToList();

                if (startPoints.Count == 0)
                    errors.Add("路径必须包含至少一个起点");
                else if (startPoints.Count > 1)
                    warnings.Add($"路径包含多个起点({startPoints.Count}个)");

                if (endPoints.Count == 0)
                    errors.Add("路径必须包含至少一个终点");
                else if (endPoints.Count > 1)
                    warnings.Add($"路径包含多个终点({endPoints.Count}个)");

                // 坐标验证
                foreach (var point in route.Points)
                {
                    if (point.Position == null)
                        errors.Add($"路径点 '{point.Name}' 缺少位置信息");
                }

                // 路径长度验证
                if (route.TotalLength < 0.1)
                    warnings.Add("路径长度过短，可能存在重复点");
                else if (route.TotalLength > 10000)
                    warnings.Add("路径长度过长，可能影响性能");

                // 构建结果
                if (errors.Count > 0)
                {
                    return PathPlanningResult.ValidationFailure($"路径验证失败: {string.Join("; ", errors)}");
                }

                var message = "路径验证通过";
                if (warnings.Count > 0)
                {
                    message += $" (警告: {string.Join("; ", warnings)})";
                }

                return PathPlanningResult.Success(message);
            }
            catch (Exception ex)
            {
                LogManager.Error($"验证路径 '{route?.Name}' 时发生异常", ex);
                return PathPlanningResult.ValidationFailure($"路径验证异常: {ex.Message}");
            }
        }

        #endregion

        #region 辅助方法（暂时保留原有实现，后续会重构）


        private void CalculateCombinedBounds()
        {
            // 保留原有实现，但移除UI相关调用
            if (!_walkableAreas.Any())
            {
                _combinedChannelBounds = null;
                return;
            }

            try
            {
                var conversionFactor = GetUnitsToMetersConversionFactor();
                var units = Application.ActiveDocument.Units;

                var allBounds = new List<BoundingBox3D>();

                foreach (var channel in _walkableAreas)
                {
                    try
                    {
                        var originalBoundingBox = channel.BoundingBox();
                        if (originalBoundingBox != null)
                        {
                            var boundingBoxInMeters = ConvertBoundingBoxToMeters(originalBoundingBox, conversionFactor);
                            allBounds.Add(boundingBoxInMeters);
                        }
                    }
                    catch
                    {
                        continue;
                    }
                }

                if (allBounds.Any())
                {
                    var minX = allBounds.Min(b => b.Min.X);
                    var minY = allBounds.Min(b => b.Min.Y);
                    var minZ = allBounds.Min(b => b.Min.Z);
                    var maxX = allBounds.Max(b => b.Max.X);
                    var maxY = allBounds.Max(b => b.Max.Y);
                    var maxZ = allBounds.Max(b => b.Max.Z);

                    var combinedBoundingBox = new BoundingBox3D(
                        new Point3D(minX, minY, minZ),
                        new Point3D(maxX, maxY, maxZ)
                    );

                    _combinedChannelBounds = new ChannelBounds(combinedBoundingBox);

                    RaiseStatusChanged($"已计算通道边界: {_combinedChannelBounds.MinPoint.X:F2},{_combinedChannelBounds.MinPoint.Y:F2} - {_combinedChannelBounds.MaxPoint.X:F2},{_combinedChannelBounds.MaxPoint.Y:F2}", PathPlanningStatusType.Info);
                }
            }
            catch (Exception ex)
            {
                RaiseErrorOccurred($"计算通道边界时发生错误: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 计算预估时间
        /// 使用配置中的速度限制（转换为模型单位）
        /// </summary>
        private void CalculateEstimatedTime(PathRoute route)
        {
            // 从配置获取速度限制（模型单位/秒）
            double speedLimit = ConfigManager.Instance.Current.Logistics.SpeedLimit;
            if (speedLimit <= 0)
            {
                speedLimit = 0.8; // 默认 0.8 模型单位/秒（约0.8米/秒）
            }
            route.EstimatedTime = route.TotalLength / speedLimit;
        }

        /// <summary>
        /// 生成路径点名称
        /// </summary>
        private string GeneratePointName(PathPointType pointType)
        {
            var currentPoints = _currentRoute?.Points ?? new List<PathPoint>();
            var typeCount = currentPoints.Count(p => p.Type == pointType) + 1;

            switch (pointType)
            {
                case PathPointType.StartPoint:
                    // 起点固定显示为"起点"，不带编号
                    return "起点";
                case PathPointType.EndPoint:
                    // 终点固定显示为"终点"，不带编号
                    return "终点";
                case PathPointType.WayPoint:
                    return $"路径点{typeCount}";
                default:
                    return $"点{typeCount}";
            }
        }

        /// <summary>
        /// 自动选择所有可通行的物流模型
        /// </summary>
        private void AutoSelectLogisticsChannels()
        {
            try
            {
                var document = Application.ActiveDocument;
                if (document?.Models == null) return;

                _walkableAreas.Clear();

                LogManager.Info("[通道自动选择] 开始搜索可通行的物流模型");

                // 使用CategoryAttributeManager统一接口获取物流项目
                var allLogisticsItemsCollection = CategoryAttributeManager.GetAllLogisticsItems();
                LogManager.Info($"[通道自动选择] CategoryAttributeManager找到 {allLogisticsItemsCollection.Count} 个具有物流属性的模型项");

                // 筛选出可通行的物流模型
                var traversableItems = CategoryAttributeManager.FilterTraversableItems(allLogisticsItemsCollection);
                LogManager.Info($"[通道自动选择] 筛选出 {traversableItems.Count} 个可通行的物流模型");

                // 将可通行的物流模型添加到_selectedChannels
                foreach (ModelItem item in traversableItems)
                {
                    _walkableAreas.Add(item);
                    LogManager.Info($"[通道自动选择] 添加可通行模型: '{item.DisplayName}'");
                }

                if (_walkableAreas.Count > 0)
                {
                    // 计算组合边界
                    CalculateCombinedBounds();

                    // 触发通道选择变更事件
                    RaiseChannelSelectionChanged(_walkableAreas, "自动选择");

                    LogManager.Info($"[通道自动选择] ✅ 自动选择了 {_walkableAreas.Count} 个可通行的物流模型");
                }
                else
                {
                    LogManager.Warning("[通道自动选择] ❌ 未找到任何可通行的物流模型");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[通道自动选择] 自动选择可通行物流模型失败: {ex.Message}");
                RaiseErrorOccurred($"自动选择可通行物流模型失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 智能ToolPlugin管理：根据编辑状态自动激活或停用
        /// </summary>
        private void ManageToolPluginForEditState()
        {
            try
            {
                if (IsInEditableState)
                {
                    // 编辑状态：确保ToolPlugin已激活
                    if (!_isToolPluginActive)
                    {
                        ActivateToolPlugin();
                    }
                }
                else
                {
                    // 查看状态：确保ToolPlugin已停用
                    if (_isToolPluginActive)
                    {
                        DeactivateToolPlugin();
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"管理ToolPlugin状态时发生错误: {ex.Message}");
                RaiseErrorOccurred($"管理ToolPlugin状态失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 激活自定义ToolPlugin进行精确点击检测
        /// </summary>
        /// <param name="subscribeToEvents">是否订阅鼠标事件</param>
        private bool ActivateToolPlugin(bool subscribeToEvents = true)
        {
            // 如果已经激活，检查是否需要订阅事件
            if (_isToolPluginActive)
            {
                LogManager.Debug("[ToolPlugin] ToolPlugin已激活，检查事件订阅状态");
                if (subscribeToEvents)
                {
                    // 确保事件订阅（避免重复订阅）
                    PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;
                    PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
                    LogManager.Debug("[ToolPlugin] 已确保PathPlanningManager事件订阅");
                }
                return true;
            }

            try
            {
                LogManager.Debug("[ToolPlugin] ===== 开始激活ToolPlugin =====");
                LogManager.Debug($"[ToolPlugin] 订阅事件: {subscribeToEvents}");
                LogManager.Debug($"[ToolPlugin] 当前应用程序状态: {Application.IsAutomated}");
                LogManager.Debug($"[ToolPlugin] 当前文档状态: {Application.ActiveDocument?.Title ?? "NULL"}");

                // 1. 加载插件程序集
                LogManager.Debug("[ToolPlugin] 步骤1: 加载插件程序集");
                var assemblyPath = PathClickToolPlugin.AssemblyPath;
                LogManager.Debug($"[ToolPlugin] 程序集路径: {assemblyPath}");
                LogManager.Debug($"[ToolPlugin] 程序集文件是否存在: {System.IO.File.Exists(assemblyPath)}");

                Application.Plugins.AddPluginAssembly(assemblyPath);
                LogManager.Debug("[ToolPlugin] ✓ 程序集加载完成");

                // 2. 查找插件
                LogManager.Debug("[ToolPlugin] 步骤2: 查找插件");
                ToolPluginRecord toolPluginRecord = (ToolPluginRecord)Application.Plugins.FindPlugin("PathClickTool.NavisworksTransport");

                if (toolPluginRecord == null)
                {
                    LogManager.Error("[ToolPlugin] ✗ 错误: 无法找到PathClickTool插件");
                    return false;
                }
                LogManager.Debug("[ToolPlugin] ✓ 插件查找成功");

                // 3. 加载插件
                LogManager.Debug("[ToolPlugin] 步骤3: 加载插件");
                var loadedPlugin = toolPluginRecord.LoadPlugin();
                if (loadedPlugin == null)
                {
                    LogManager.Error("[ToolPlugin] ✗ 错误: 插件加载失败");
                    return false;
                }
                LogManager.Debug("[ToolPlugin] ✓ 插件加载成功");

                // 4. 设置为活动工具
                LogManager.Debug("[ToolPlugin] 步骤4: 设置为活动工具");

                // 先重置工具状态，清除可能的导航工具
                // 这一步很重要，确保从导航工具（如Pan、Orbit）切换回自定义工具
                Application.MainDocument.Tool.Value = Tool.None;
                LogManager.Debug("[ToolPlugin] 已重置工具状态为None");

                // 然后设置自定义工具插件
                Application.MainDocument.Tool.SetCustomToolPlugin(loadedPlugin);
                LogManager.Debug("[ToolPlugin] ✓ 工具设置成功");

                // 5. 根据参数决定是否订阅点击事件
                if (subscribeToEvents)
                {
                    LogManager.Debug("[ToolPlugin] 步骤5: 订阅点击事件");
                    PathClickToolPlugin.MouseClicked += OnToolPluginMouseClicked;
                    LogManager.Debug("[ToolPlugin] ✓ PathPlanningManager事件订阅成功");
                }
                else
                {
                    LogManager.Debug("[ToolPlugin] 步骤5: 跳过事件订阅（由外部组件管理）");
                }

                _isToolPluginActive = true;
                LogManager.Info("[ToolPlugin] ===== ToolPlugin激活完成 =====");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[ToolPlugin] 激活异常: {ex.Message}");
                LogManager.Error($"[ToolPlugin] 堆栈: {ex.StackTrace}");
                return false;
            }
        }

        /// <summary>
        /// 重新激活ToolPlugin（供InputMonitor调用）
        /// 用于在工具失活后快速恢复，不重复订阅事件
        /// </summary>
        public void ReactivateToolPlugin()
        {
            try
            {
                // 检查当前状态和实际工具值
                if ((PathEditState == PathEditState.Creating ||
                     PathEditState == PathEditState.AddingPoints ||
                     PathEditState == PathEditState.EditingPoint))
                {
                    // 检查当前工具是否为自定义工具，如果不是则需要重新激活
                    var currentTool = Application.MainDocument.Tool.Value;
                    if (currentTool != Tool.CustomToolPlugin)
                    {
                        LogManager.Debug($"[ReactivateToolPlugin] 当前工具为{currentTool}，开始重新激活ToolPlugin");

                        // 重要：先将激活标志设置为false，强制执行完整的激活流程
                        _isToolPluginActive = false;

                        // 调用现有的激活方法，但不重复订阅事件
                        if (ActivateToolPlugin(false))
                        {
                            LogManager.Info("[ReactivateToolPlugin] ToolPlugin重新激活成功");
                            RaiseStatusChanged("工具已重新激活", PathPlanningStatusType.Info);
                        }
                        else
                        {
                            LogManager.Warning("[ReactivateToolPlugin] ToolPlugin重新激活失败");
                            RaiseErrorOccurred("无法重新激活编辑工具");
                        }
                    }
                    else
                    {
                        LogManager.Debug("[ReactivateToolPlugin] 当前已是CustomToolPlugin，无需重新激活");
                    }
                }
                else
                {
                    LogManager.Debug($"[ReactivateToolPlugin] 跳过重新激活 - PathEditState: {PathEditState}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[ReactivateToolPlugin] 重新激活失败: {ex.Message}");
                RaiseErrorOccurred($"重新激活工具失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 处理ToolPlugin的鼠标点击事件
        /// </summary>
        private void OnToolPluginMouseClicked(object sender, PickItemResult pickResult)
        {
            try
            {
                // 如果在自动路径规划模式，则跳过处理（应该由PathEditingViewModel处理）
                if (IsInAutoPathMode)
                {
                    LogManager.Debug("[ToolPlugin事件] 当前在自动路径规划模式，跳过PathPlanningManager处理");
                    return;
                }

                // 手动路径编辑处理
                ProcessManualPathEditing(pickResult);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[ToolPlugin事件] 处理异常: {ex.Message}");
                LogManager.Error($"[ToolPlugin事件] 堆栈: {ex.StackTrace}");
            }
        }

        /// <summary>
        /// 处理手动路径编辑的鼠标点击
        /// </summary>
        private void ProcessManualPathEditing(PickItemResult pickResult)
        {
            try
            {
                Point3D clickedPoint = pickResult.Point;

                // 吊装模式处理
                if (_enableHoistingMode)
                {
                    if (_hoistingStartPoint == null)
                    {
                        // 第一次点击：记录起点
                        _hoistingStartPoint = clickedPoint;
                        LogManager.Info($"[吊装模式] 已设置起点: ({clickedPoint.X:F2}, {clickedPoint.Y:F2}, {clickedPoint.Z:F2})，弹出吊装高度设置对话框");

                        // 渲染起点标记
                        var startPoint = new PathPoint(clickedPoint, "吊装起点", PathPointType.StartPoint);
                        PathPointRenderPlugin.Instance.RenderPreviewPoint(startPoint);

                        // 在UI线程中弹出吊装高度设置对话框
                        _uiStateManager.QueueUIUpdate(() =>
                        {
                            try
                            {
                                var heightDialog = new NavisworksTransport.UI.WPF.Views.AerialHeightDialog(defaultHeight: 3.0);
                                bool? dialogResult = heightDialog.ShowDialog();

                                // 如果用户取消，则清除起点并退出吊装模式
                                if (dialogResult != true)
                                {
                                    LogManager.Info("用户取消了吊装高度设置，清除起点并退出吊装模式");
                                    _hoistingStartPoint = null;
                                    _enableHoistingMode = false;
                                    _hoistingGroundIntermediatePoints.Clear();
                                    PathPointRenderPlugin.Instance.ClearPreviewPoint();
                                    StopClickTool();
                                    RaiseStatusChanged("已取消创建吊装路径", PathPlanningStatusType.Info);
                                    return;
                                }

                                // 获取用户设置的吊装高度（转换为模型单位存储）
                                double liftHeightMetersInput = heightDialog.LiftHeightMeters;
                                double liftHeightModelUnits = UnitsConverter.ConvertFromMeters(liftHeightMetersInput);
                                _hoistingLiftHeight = liftHeightModelUnits;
                                LogManager.Info($"用户设置的吊装高度: {liftHeightMetersInput:F2}米");

                                // 保存吊装高度到当前路径（内部使用模型单位）
                                if (CurrentRoute != null)
                                {
                                    CurrentRoute.LiftHeight = liftHeightModelUnits;
                                }

                                // 立即生成起吊点和提升点
                                try
                                {
                                    var hoistingStartPoint = new PathPoint(_hoistingStartPoint, "起吊点", PathPointType.StartPoint);
                                    hoistingStartPoint.Direction = HoistingPointDirection.Vertical;
                                    CurrentRoute.AddPoint(hoistingStartPoint);
                                    LogManager.Debug($"[吊装模式] 已添加起吊点: ({hoistingStartPoint.Position.X:F2}, {hoistingStartPoint.Position.Y:F2}, {hoistingStartPoint.Position.Z:F2})");

                                    // 使用已转换的模型单位高度
                                    var liftPoint = new PathPoint(
                                        OffsetPointAlongHoistingUp(_hoistingStartPoint, liftHeightModelUnits),
                                        "提升点",
                                        PathPointType.WayPoint);
                                    liftPoint.Direction = HoistingPointDirection.Vertical;
                                    CurrentRoute.AddPoint(liftPoint);
                                    LogManager.Debug($"[吊装模式] 已添加提升点: ({liftPoint.Position.X:F2}, {liftPoint.Position.Y:F2}, {liftPoint.Position.Z:F2})");

                                    // 渲染路径
                                    if (_renderPlugin != null)
                                    {
                                        _renderPlugin.RenderPath(CurrentRoute);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    LogManager.Error($"[吊装模式] 生成起吊点和提升点失败: {ex.Message}", ex);
                                }

                                // 检查完成模式
                                if (heightDialog.IsTwoPointMode)
                                {
                                    // 2点路径：提升点直接作为终点，无下降段落
                                    LogManager.Info("[吊装模式] 首次点击2点路径，提升点即为终点");

                                    var lastPoint = CurrentRoute.Points.Last();
                                    lastPoint.Type = PathPointType.EndPoint;
                                    lastPoint.Name = "终点";

                                    // 标记为2点纯垂直路径
                                    CurrentRoute.IsTwoPointVertical = true;

                                    // 清理吊装模式临时变量
                                    _hoistingStartPoint = null;
                                    _hoistingLiftHeight = 0;
                                    _hoistingGroundIntermediatePoints.Clear();
                                    _enableHoistingMode = false;

                                    // 渲染最终路径
                                    if (_renderPlugin != null)
                                    {
                                        _renderPlugin.RenderPath(CurrentRoute);
                                    }

                                    // 添加路径到集合
                                    if (!_routes.Contains(CurrentRoute))
                                    {
                                        _routes.Add(CurrentRoute);
                                    }

                                    // 切换回查看状态
                                    SwitchToViewingState();

                                    // 触发事件通知UI刷新
                                    RaisePathPointsListUpdated(CurrentRoute, "2点路径完成");
                                    SetCurrentRouteInternal(CurrentRoute, triggerEvent: true);
                                    RaiseRouteGenerated(CurrentRoute, RouteGenerationMethod.Manual);
                                    RaiseStatusChanged("2点垂直吊装路径创建完成", PathPlanningStatusType.Success);
                                }
                                else if (heightDialog.IsSetAsEndPoint)
                                {
                                    LogManager.Info("[吊装模式] 首次点击设为终点，直接完成路径");
                                    bool finished = FinishEditing();
                                    if (finished && CurrentRoute != null)
                                    {
                                        RaisePathPointsListUpdated(CurrentRoute, "设为终点完成路径");
                                    }
                                    else
                                    {
                                        RaiseStatusChanged("吊装路径完成失败", PathPlanningStatusType.Warning);
                                    }
                                }
                                else
                                {
                                    // 提示用户点击添加转向点
                                    RaiseStatusChanged($"吊装高度已设置为 {liftHeightMetersInput:F2}米，点击添加转向点（点击地面位置），完成后点击完成按钮", PathPlanningStatusType.Info);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogManager.Error($"[吊装模式] 弹出吊装高度对话框失败: {ex.Message}", ex);
                                _hoistingStartPoint = null;
                                _enableHoistingMode = false;
                                _hoistingGroundIntermediatePoints.Clear();
                                PathPointRenderPlugin.Instance.ClearPreviewPoint();
                                StopClickTool();
                                RaiseStatusChanged("设置吊装高度失败，已取消创建吊装路径", PathPlanningStatusType.Warning);
                            }
                        }, UIUpdatePriority.High);

                        return;
                    }
                    else
                    {
                        // 后续点击：添加新的层级（每次都需要输入高度）
                        LogManager.Debug($"[吊装模式] 用户点击，准备添加新层级: ({clickedPoint.X:F2}, {clickedPoint.Y:F2}, {clickedPoint.Z:F2})");

                        // 记录地面点击位置，后续在UI线程中处理
                        Point3D groundPoint = clickedPoint;
                        
                        // 在UI线程中弹出高度对话框并生成路径点
                        _uiStateManager.QueueUIUpdate(() =>
                        {
                            try
                            {
                                // 计算默认高度（上一次的高度，如果没有则使用3米）
                                double defaultHeightMeters = _hoistingLiftHeight > 0 
                                    ? UnitsConverter.ConvertToMeters(_hoistingLiftHeight) 
                                    : 3.0;
                                
                                var heightDialog = new NavisworksTransport.UI.WPF.Views.AerialHeightDialog(defaultHeight: defaultHeightMeters);
                                bool? dialogResult = heightDialog.ShowDialog();

                                // 如果用户取消，则只是跳过这次点击，继续等待下一次点击
                                if (dialogResult != true)
                                {
                                    LogManager.Info("[吊装模式] 用户取消了高度设置，继续等待点击");
                                    RaiseStatusChanged("已取消，继续点击添加层级或点击完成按钮", PathPlanningStatusType.Info);
                                    return;
                                }

                                // 检查用户是否选择"设为终点"（完成路径）
                                bool isSetAsEndPoint = heightDialog.IsSetAsEndPoint;

                                // 获取用户设置的高度
                                double liftHeightMetersInput = heightDialog.LiftHeightMeters;
                                double liftHeightModelUnits = UnitsConverter.ConvertFromMeters(liftHeightMetersInput);
                                double previousHeight = _hoistingLiftHeight;
                                _hoistingLiftHeight = liftHeightModelUnits;
                                
                                // 更新路径的吊装高度（使用最新的高度）
                                if (CurrentRoute != null)
                                {
                                    CurrentRoute.LiftHeight = liftHeightModelUnits;
                                }
                                
                                LogManager.Info($"[吊装模式] 用户设置高度: {liftHeightMetersInput:F2}米，上一高度: {UnitsConverter.ConvertToMeters(previousHeight):F2}米");

                                // 获取上一个路径点
                                Point3D previousPoint;
                                if (CurrentRoute.Points.Count > 0)
                                {
                                    previousPoint = CurrentRoute.Points.Last().Position;
                                    var lastPoint = CurrentRoute.Points.Last();
                                    LogManager.Info($"[吊装模式] 上一路径点: {lastPoint.Name}, Elevation={GetHoistingElevation(lastPoint.Position):F2}");
                                }
                                else
                                {
                                    previousPoint = OffsetPointAlongHoistingUp(_hoistingStartPoint, liftHeightModelUnits);
                                    LogManager.Info($"[吊装模式] 无上一路径点，使用起点+高度: Elevation={GetHoistingElevation(previousPoint):F2}");
                                }

                                // 记录原始地面点击位置
                                _hoistingGroundIntermediatePoints.Add(groundPoint);
                                LogManager.Debug($"[吊装模式] 已记录地面点击点: ({groundPoint.X:F2}, {groundPoint.Y:F2}, {groundPoint.Z:F2})");

                                // 检查高度是否变化（比较沿宿主 up 的绝对高程）
                                double newAbsoluteHeight = GetHoistingElevation(_hoistingStartPoint) + liftHeightModelUnits;
                                double heightDiff = Math.Abs(newAbsoluteHeight - GetHoistingElevation(previousPoint));
                                bool heightChanged = heightDiff > 0.001;
                                
                                LogManager.Info($"[吊装模式] 起点=({_hoistingStartPoint.X:F2}, {_hoistingStartPoint.Y:F2}, {_hoistingStartPoint.Z:F2})");
                                LogManager.Info($"[吊装模式] 相对高度(米)={liftHeightMetersInput:F2}, 相对高度(模型)={liftHeightModelUnits:F2}");
                                LogManager.Info($"[吊装模式] 新绝对高度={newAbsoluteHeight:F2}, 上一位置Elevation={GetHoistingElevation(previousPoint):F2}");
                                
                                // 步骤1：水平移动点（在旧高度上移动到新XY）
                                // 使用 AerialPathGenerator 生成水平路径点
                                LogManager.Info($"[吊装模式] 生成水平路径点: previousPoint=({previousPoint.X:F2}, {previousPoint.Y:F2}, {previousPoint.Z:F2}), groundPoint=({groundPoint.X:F2}, {groundPoint.Y:F2}, {groundPoint.Z:F2})");
                                
                                // 记录添加新点前的点数，用于增量优化
                                int pointCountBefore = CurrentRoute.Points.Count;
                                
                                var generator = new AerialPathGenerator();
                                var aerialPoint = generator.GenerateSmartHoistingPoint(
                                    previousPoint,
                                    groundPoint,
                                    GetHoistingElevation(previousPoint),
                                    CurrentRoute.Points.Count > 0 ? CurrentRoute.Points.Count : 1);

                                if (aerialPoint != null)
                                {
                                    // 添加水平移动路径点
                                    CurrentRoute.AddPoint(aerialPoint);
                                    LogManager.Info($"[吊装模式] 已添加水平路径点: {aerialPoint.Name}, 位置: ({aerialPoint.Position.X:F2}, {aerialPoint.Position.Y:F2}, {aerialPoint.Position.Z:F2})");
                                    
                                    // 更新上一个点为水平路径点
                                    previousPoint = aerialPoint.Position;
                                }

                                // 步骤2：在添加垂直过渡点前，先正交化水平路径（此时所有点在同一高度，可以处理斜线）
                                // 使用增量处理，只处理新添加的点（从添加前最后一个点的索引开始）
                                int orthogonalizeStartIndex = Math.Max(0, pointCountBefore - 1);
                                OrthogonalizePath(CurrentRoute, orthogonalizeStartIndex);

                                // 步骤3：如果需要，添加垂直过渡点
                                if (heightChanged)
                                {
                                    // 高度变化：垂直上升到新高度
                                    LogManager.Info($"[吊装模式] 高度变化，插入垂直过渡点: Elevation={GetHoistingElevation(previousPoint):F2} -> Elevation={newAbsoluteHeight:F2}");
                                    
                                    var verticalTransitionPoint = SetHoistingElevation(previousPoint, newAbsoluteHeight);
                                    var verticalPoint = new PathPoint(
                                        verticalTransitionPoint,
                                        $"高度过渡{CurrentRoute.Points.Count}",
                                        PathPointType.WayPoint);
                                    verticalPoint.Direction = HoistingPointDirection.Vertical;
                                    CurrentRoute.AddPoint(verticalPoint);
                                    LogManager.Info($"[吊装模式] 已添加垂直过渡点: ({verticalTransitionPoint.X:F2}, {verticalTransitionPoint.Y:F2}, {verticalTransitionPoint.Z:F2})");
                                }
                                else
                                {
                                    LogManager.Info($"[吊装模式] 高度未变化，无需垂直过渡");
                                }

                                // 渲染路径
                                if (_renderPlugin != null)
                                {
                                    _renderPlugin.RenderPath(CurrentRoute);
                                }

                                // 如果用户选择"设为终点"，调用 FinishEditing 完成路径
                                if (isSetAsEndPoint)
                                {
                                    LogManager.Info("[吊装模式] 用户选择设为终点，调用 FinishEditing 完成路径");
                                    bool finished = FinishEditing();
                                    if (finished && CurrentRoute != null)
                                    {
                                        // 触发路径列表更新事件，通知UI刷新
                                        RaisePathPointsListUpdated(CurrentRoute, "设为终点完成路径");
                                    }
                                }
                                else
                                {
                                    string transitionText = heightChanged ? "（含高度过渡）" : "";
                                    RaiseStatusChanged($"已添加层级路径点{transitionText}（高度: {liftHeightMetersInput:F2}米），继续点击添加新层级或点击完成按钮", PathPlanningStatusType.Info);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogManager.Error($"[吊装模式] 添加层级失败: {ex.Message}", ex);
                            }
                        }, UIUpdatePriority.High);

                        return;
                    }
                }

                // 如果启用了空轨吸附，先吸附到基准路径
                if (_enableRailSnapping)
                {
                    clickedPoint = SnapToRailBaseline(clickedPoint);
                }

                // 检查当前选中的通道状态
                LogManager.Debug($"[手动编辑] 当前_selectedChannels状态: {(_walkableAreas == null ? "NULL" : $"包含{_walkableAreas.Count}个项目")}");

                // 如果没有选中的通道，尝试实时搜索
                if (_walkableAreas == null || _walkableAreas.Count == 0)
                {
                    LogManager.Debug("[手动编辑] 没有预选通道，开始实时搜索可通行的物流模型");
                    SearchAndSetTraversableChannels();
                }

                // 空轨路径直接添加路径点，不检查可通行物流模型
                if (_enableRailSnapping)
                {
                    LogManager.Debug("[手动编辑] 空轨路径模式，直接添加路径点");
                    var pathPoint = AddPathPointIn3D(clickedPoint);
                    if (pathPoint != null)
                    {
                        LogManager.Debug($"[手动编辑] ✓ 空轨路径点添加成功: {pathPoint.Name}");
                    }
                    else
                    {
                        LogManager.Warning("[手动编辑] ✗ 空轨路径点添加失败");
                    }
                }
                // 地面路径直接处理点击
                else
                {
                    // 手动路径编辑 - 根据当前模式处理点击
                    if (PathEditState == PathEditState.AddingPoints)
                    {
                        // 添加路径点模式 - 使用预览点
                        LogManager.Debug("[手动编辑] 设置预览点位置");
                        var previewPoint = SetPreviewPoint(clickedPoint);

                        if (previewPoint != null)
                        {
                            LogManager.Debug($"[手动编辑] ✓ 预览点已设置: {previewPoint.Name}");
                        }
                        else
                        {
                            LogManager.Warning("[手动编辑] ✗ 预览点设置失败");
                        }
                    }
                    else if (PathEditState == PathEditState.EditingPoint)
                    {
                        // 修改路径点模式 - 设置预览位置
                        LogManager.Debug("[手动编辑] 设置修改路径点预览位置");
                        SetEditingPreviewPoint(clickedPoint);
                        LogManager.Debug($"[手动编辑] ✓ 修改路径点预览位置已设置: ({clickedPoint.X:F3}, {clickedPoint.Y:F3}, {clickedPoint.Z:F3})");
                    }
                    else
                    {
                        // 其他编辑模式 - 保持原有逻辑
                        LogManager.Debug("[手动编辑] 调用AddPathPointIn3D添加路径点");
                        var pathPoint = AddPathPointIn3D(clickedPoint);

                        if (pathPoint != null)
                        {
                            LogManager.Debug($"[手动编辑] ✓ 路径点添加成功: {pathPoint.Name}");
                        }
                        else
                        {
                            LogManager.Warning("[手动编辑] ✗ 路径点添加失败");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[手动编辑] 处理异常: {ex.Message}");
                LogManager.Error($"[手动编辑] 堆栈: {ex.StackTrace}");
            }
        }

        /// <summary>
        /// 将点击点吸附到空轨基准路径
        /// </summary>
        private Point3D SnapToRailBaseline(Point3D clickedPoint)
        {
            try
            {
                // 获取所有空轨基准路径
                var baselinePaths = PathPointRenderPlugin.Instance?.GetAllRailBaselinePaths();
                if (baselinePaths == null || baselinePaths.Count == 0)
                {
                    LogManager.Warning("[空轨吸附] 没有找到空轨基准路径，不进行吸附");
                    return clickedPoint;
                }

                // 找到最近的基准路径投影点
                Point3D nearestPoint = null;
                double minDistance = double.MaxValue;
                double maxSnapDistance = 2.0; // 最大吸附距离（模型单位）

                foreach (var pathPoints in baselinePaths.Values)
                {
                    var snappedPoint = FindNearestPointOnPolyline(pathPoints, clickedPoint);
                    if (snappedPoint == null)
                    {
                        continue;
                    }

                    double distance = CalculateDistance3D(clickedPoint, snappedPoint);
                    if (distance < minDistance)
                    {
                        minDistance = distance;
                        nearestPoint = snappedPoint;
                    }
                }

                if (nearestPoint != null && minDistance <= maxSnapDistance)
                {
                    LogManager.Info($"[空轨吸附] 点击点 ({clickedPoint.X:F2}, {clickedPoint.Y:F2}, {clickedPoint.Z:F2}) 吸附到基准路径投影点 ({nearestPoint.X:F2}, {nearestPoint.Y:F2}, {nearestPoint.Z:F2})，距离 {minDistance:F2}");
                    return nearestPoint;
                }
                else
                {
                    LogManager.Warning($"[空轨吸附] 未找到合适的基准路径点（最近距离: {minDistance:F2}，最大吸附距离: {maxSnapDistance}）");
                    return clickedPoint;
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[空轨吸附] 吸附失败: {ex.Message}");
                return clickedPoint;
            }
        }

        /// <summary>
        /// 计算3D距离
        /// </summary>
        private double CalculateDistance3D(Point3D a, Point3D b)
        {
            double dx = a.X - b.X;
            double dy = a.Y - b.Y;
            double dz = a.Z - b.Z;
            return Math.Sqrt(dx * dx + dy * dy + dz * dz);
        }

        /// <summary>
        /// 查找折线上距离目标点最近的投影点
        /// </summary>
        private Point3D FindNearestPointOnPolyline(List<Point3D> pathPoints, Point3D targetPoint)
        {
            if (pathPoints == null || pathPoints.Count == 0)
            {
                return null;
            }

            if (pathPoints.Count == 1)
            {
                return pathPoints[0];
            }

            Point3D nearestPoint = null;
            double minDistance = double.MaxValue;

            for (int i = 0; i < pathPoints.Count - 1; i++)
            {
                var projectedPoint = ProjectPointToSegment(targetPoint, pathPoints[i], pathPoints[i + 1]);
                double distance = CalculateDistance3D(targetPoint, projectedPoint);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestPoint = projectedPoint;
                }
            }

            return nearestPoint ?? pathPoints[0];
        }

        /// <summary>
        /// 将点投影到线段上
        /// </summary>
        private Point3D ProjectPointToSegment(Point3D point, Point3D segmentStart, Point3D segmentEnd)
        {
            double segmentX = segmentEnd.X - segmentStart.X;
            double segmentY = segmentEnd.Y - segmentStart.Y;
            double segmentZ = segmentEnd.Z - segmentStart.Z;

            double segmentLengthSquared = segmentX * segmentX + segmentY * segmentY + segmentZ * segmentZ;
            if (segmentLengthSquared < 1e-9)
            {
                return segmentStart;
            }

            double pointX = point.X - segmentStart.X;
            double pointY = point.Y - segmentStart.Y;
            double pointZ = point.Z - segmentStart.Z;

            double projection = (pointX * segmentX + pointY * segmentY + pointZ * segmentZ) / segmentLengthSquared;
            projection = Math.Max(0.0, Math.Min(1.0, projection));

            return new Point3D(
                segmentStart.X + projection * segmentX,
                segmentStart.Y + projection * segmentY,
                segmentStart.Z + projection * segmentZ);
        }

        /// <summary>
        /// 搜索并设置可通行的通道
        /// </summary>
        private void SearchAndSetTraversableChannels()
        {
            try
            {
                var document = Application.ActiveDocument;
                if (document?.Models != null)
                {
                    // 使用CategoryAttributeManager统一接口获取物流项目
                    var logisticsItemsCollection = CategoryAttributeManager.GetAllLogisticsItems();
                    LogManager.Debug($"[搜索通道] CategoryAttributeManager找到 {logisticsItemsCollection.Count} 个物流模型");

                    if (logisticsItemsCollection.Count > 0)
                    {
                        // 筛选出可通行的物流模型
                        var traversableItems = CategoryAttributeManager.FilterTraversableItems(logisticsItemsCollection);
                        LogManager.Debug($"[搜索通道] 筛选出 {traversableItems.Count} 个可通行的物流模型");

                        // 临时设置为选中通道
                        if (_walkableAreas == null) _walkableAreas = new List<ModelItem>();
                        _walkableAreas.Clear();

                        foreach (ModelItem item in traversableItems)
                        {
                            _walkableAreas.Add(item);
                            LogManager.Debug($"[搜索通道] 添加可通行模型: '{item.DisplayName}'");
                        }
                    }
                }
            }
            catch (Exception searchEx)
            {
                LogManager.Error($"[搜索通道] 实时搜索失败: {searchEx.Message}");
            }
        }



        /// <summary>
        /// 获取Navisworks文档单位并转换为米的系数
        /// </summary>
        private double GetUnitsToMetersConversionFactor()
        {
            try
            {
                var units = Application.ActiveDocument.Units;

                switch (units)
                {
                    case Units.Millimeters:
                        return 0.001;
                    case Units.Centimeters:
                        return 0.01;
                    case Units.Meters:
                        return 1.0;
                    case Units.Inches:
                        return 0.0254;
                    case Units.Feet:
                        return 0.3048;
                    case Units.Kilometers:
                        return 1000.0;
                    case Units.Micrometers:
                        return 0.000001;
                    case Units.Microinches:
                        return 0.0000000254;
                    case Units.Mils:
                        return 0.0000254;
                    case Units.Yards:
                        return 0.9144;
                    case Units.Miles:
                        return 1609.43;
                    default:
                        return 1.0;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"获取文档单位失败: {ex.Message}，默认为米");
                return 1.0;
            }
        }

        /// <summary>
        /// 转换包围盒到米单位
        /// </summary>
        private BoundingBox3D ConvertBoundingBoxToMeters(BoundingBox3D boundingBox, double conversionFactor)
        {
            var minPoint = new Point3D(
                boundingBox.Min.X * conversionFactor,
                boundingBox.Min.Y * conversionFactor,
                boundingBox.Min.Z * conversionFactor
            );
            var maxPoint = new Point3D(
                boundingBox.Max.X * conversionFactor,
                boundingBox.Max.Y * conversionFactor,
                boundingBox.Max.Z * conversionFactor
            );
            return new BoundingBox3D(minPoint, maxPoint);
        }

        #endregion

        #region IDisposable实现

        public void Dispose()
        {
            try
            {
                // 清理资源
                _renderPlugin?.ClearAllPaths();
                _renderPlugin = null;

                // 停用ToolPlugin
                if (_isToolPluginActive)
                {
                    DeactivateToolPlugin();
                }

                _pathDatabase?.Dispose();
                _pathDatabase = null;
                _analysisService = null;
                _databaseDocumentPath = null;
            }
            catch (Exception ex)
            {
                LogManager.Error($"PathPlanningManager释放时发生错误: {ex.Message}");
            }
        }

        private bool DeactivateToolPlugin()
        {
            if (!_isToolPluginActive)
            {
                LogManager.Debug("[ToolPlugin] ToolPlugin未激活，无需停用");
                return true;
            }

            try
            {
                // 1. 取消事件订阅
                PathClickToolPlugin.MouseClicked -= OnToolPluginMouseClicked;

                // 2. 重置为无活动工具状态
                try
                {
                    // 使用Tool.Select切换到选择工具，确保完全退出ToolPlugin模式
                    // Tool.None可能不足以释放ToolPlugin对键盘输入的拦截
                    Application.MainDocument.Tool.Value = Tool.Select;
                    LogManager.Debug("[ToolPlugin] 已重置工具状态为Select");
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"[ToolPlugin] 重置工具状态失败: {ex.Message}");
                }

                _isToolPluginActive = false;
                LogManager.Debug("[ToolPlugin] ===== ToolPlugin停用完成 =====");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[ToolPlugin] 停用异常: {ex.Message}");
                LogManager.Error($"[ToolPlugin] 堆栈: {ex.StackTrace}");
                return false;
            }
        }

        /// <summary>
        /// 强制重新初始化ToolPlugin（公共接口，避免反射调用）
        /// </summary>
        /// <param name="subscribeToEvents">是否订阅事件</param>
        /// <returns>初始化是否成功</returns>
        public bool ForceReinitializeToolPlugin(bool subscribeToEvents = false)
        {
            try
            {
                LogManager.Debug($"[工具插件重初始化] 开始强制重新初始化ToolPlugin，订阅事件: {subscribeToEvents}");

                // 1. 停用当前ToolPlugin
                bool deactivated = DeactivateToolPlugin();
                LogManager.Debug($"[工具插件重初始化] 停用结果: {deactivated}");

                // 2. 强制重置激活状态
                _isToolPluginActive = false;
                LogManager.Debug("[工具插件重初始化] 已重置激活状态标志");

                // 3. 重新激活ToolPlugin
                bool activated = ActivateToolPlugin(subscribeToEvents);
                LogManager.Debug($"[工具插件重初始化] 激活结果（事件订阅: {subscribeToEvents}）: {activated}");

                if (activated)
                {
                    LogManager.Info("[工具插件重初始化] ToolPlugin重新初始化成功，已获得鼠标焦点");
                }
                else
                {
                    LogManager.Error("[工具插件重初始化] ToolPlugin激活失败");
                }

                return activated;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[工具插件重初始化] 重新初始化ToolPlugin失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 根据当前业务上下文恢复 ToolPlugin 焦点。
        /// 普通手动建/编辑路径应恢复 PathPlanningManager 主链；
        /// 自动路径、装配拾取、多层吊装等外部自管拾取模式则保持外部事件处理。
        /// </summary>
        public bool RestoreToolPluginFocusForCurrentContext()
        {
            try
            {
                bool shouldSubscribeToManagerEvents = !IsInAutoPathMode;
                string contextLabel = shouldSubscribeToManagerEvents
                    ? "普通手动取点"
                    : "外部自管拾取";

                LogManager.Info(
                    $"[工具插件恢复] 按当前上下文恢复焦点: 模式={contextLabel}, " +
                    $"PathEditState={PathEditState}, 订阅PathPlanningManager事件={shouldSubscribeToManagerEvents}");

                return ForceReinitializeToolPlugin(shouldSubscribeToManagerEvents);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[工具插件恢复] 按当前上下文恢复焦点失败: {ex.Message}", ex);
                return false;
            }
        }

        #endregion

        #region 路径计算和保存

        /// <summary>
        /// 重新计算曲线化路径并保存到数据库
        /// </summary>

        #endregion

        #region 公共访问方法

        /// <summary>
        /// 获取PathDatabase实例
        /// </summary>
        public PathDatabase GetPathDatabase()
        {
            return _pathDatabase;
        }

        /// <summary>
        /// 更新路径并保存到数据库
        /// </summary>
        public void UpdateRoute(PathRoute route)
        {
            if (route == null) return;

            // 使用统一的曲线化和保存方法
            route.RecalculateAndSaveRoute("UpdateRoute");
        }

        #endregion

        #region 自动路径规划辅助方法

        /// <summary>
        /// 获取当前模型的边界框
        /// </summary>
        /// <returns>模型边界框</returns>
        private BoundingBox3D GetModelBounds()
        {
            try
            {
                // 如果没有选中的可通行区域，自动搜索
                if (_walkableAreas == null || _walkableAreas.Count == 0)
                {
                    LogManager.Info("未找到预定义的可通行区域，尝试自动搜索...");
                    AutoSelectLogisticsChannels();
                }

                // 检查是否找到可通行区域
                if (_walkableAreas == null || _walkableAreas.Count == 0)
                {
                    LogManager.Error("没有找到任何可通行区域（通道、门、电梯、楼梯等）");
                    throw new InvalidOperationException("无法进行路径规划：模型中没有定义可通行的物流区域。请先设置物流属性。");
                }

                // 使用可通行区域的边界作为路径规划范围
                return CalculateChannelsBounds(_walkableAreas);
            }
            catch (Exception ex)
            {
                LogManager.Error($"获取模型边界失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 计算选中通道的组合边界
        /// </summary>
        private BoundingBox3D CalculateChannelsBounds(List<ModelItem> channels)
        {
            var allBounds = new List<BoundingBox3D>();

            foreach (var channel in channels)
            {
                var bounds = channel.BoundingBox();
                if (bounds != null)
                {
                    allBounds.Add(bounds);
                }
            }

            if (!allBounds.Any()) return null;

            var minX = allBounds.Min(b => b.Min.X);
            var minY = allBounds.Min(b => b.Min.Y);
            var minZ = allBounds.Min(b => b.Min.Z);
            var maxX = allBounds.Max(b => b.Max.X);
            var maxY = allBounds.Max(b => b.Max.Y);
            var maxZ = allBounds.Max(b => b.Max.Z);

            return new BoundingBox3D(
                new Point3D(minX, minY, minZ),
                new Point3D(maxX, maxY, maxZ)
            );
        }

        /// <summary>
        /// 计算最优网格大小
        /// </summary>
        private double CalculateOptimalGridSize(BoundingBox3D bounds)
        {
            try
            {
                return CalculateOptimalGridSizeFromBounds(
                    bounds.Min.X, bounds.Min.Y, bounds.Min.Z,
                    bounds.Max.X, bounds.Max.Y, bounds.Max.Z,
                    CoordinateSystemManager.Instance.ResolvedType);
            }
            catch
            {
                return 0.5; // 默认值改为0.5米，与UI默认设置保持一致
            }
        }

        /// <summary>
        /// 根据宿主包围盒和当前宿主坐标系语义，计算自动路径规划的最优网格大小。
        /// 关键约束：
        /// - 仅修正“水平平面”的解释，不改变历史阈值与业务策略。
        /// - ZUp: 使用 Host XY 平面跨度。
        /// - YUp: 使用 Host XZ 平面跨度。
        /// </summary>
        private static double CalculateOptimalGridSizeFromBounds(
            double minX, double minY, double minZ,
            double maxX, double maxY, double maxZ,
            CoordinateSystemType coordinateSystemType)
        {
            var adapter = new HostCoordinateAdapter(coordinateSystemType);
            var hostMin = new System.Numerics.Vector3((float)minX, (float)minY, (float)minZ);
            var hostMax = new System.Numerics.Vector3((float)maxX, (float)maxY, (float)maxZ);
            var (min1, max1, min2, max2) = HostPlanarGridHelper.GetHorizontalRange3(hostMin, hostMax, adapter);

            var width = max1 - min1;
            var height = max2 - min2;
            var maxDimension = Math.Max(width, height);

            if (maxDimension > 1000) return 5.0;
            if (maxDimension > 500) return 2.0;
            return 0.5;
        }

        /// <summary>
        /// 获取通道模型项用于高度计算
        /// </summary>
        private IEnumerable<ModelItem> GetChannelItemsForHeightCalculation(GridMap gridMap = null)
        {
            var channelItems = new List<ModelItem>();

            try
            {
                // 🔥 关键修复：优先使用网格生成时已确定的通道数据
                if (gridMap?.ChannelItems != null && gridMap.ChannelItems.Any())
                {
                    LogManager.Info($"[通道数据] 使用网格生成时的通道数据，数量: {gridMap.ChannelItems.Count()}");
                    channelItems.AddRange(gridMap.ChannelItems);
                    return channelItems;
                }

                // 如果用户已选择通道，优先使用用户选择的通道
                if (_walkableAreas != null && _walkableAreas.Count > 0)
                {
                    LogManager.Info($"[通道数据] 使用用户选择的通道，数量: {_walkableAreas.Count}");
                    channelItems.AddRange(_walkableAreas);
                    return channelItems;
                }

                // 否则使用CategoryAttributeManager搜索
                LogManager.Info("[通道数据] 用户未选择通道且网格无通道数据，使用CategoryAttributeManager搜索");
                var document = Application.ActiveDocument;
                if (document != null)
                {
                    var foundChannelsCollection = CategoryAttributeManager.GetAllLogisticsItems();
                    foreach (ModelItem item in foundChannelsCollection)
                    {
                        channelItems.Add(item);
                    }
                }

                LogManager.Info($"[通道数据] 找到 {channelItems.Count} 个通道模型项");
                return channelItems;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[通道数据] 获取通道项失败: {ex.Message}");
                return channelItems;
            }
        }

        /// <summary>
        /// 从A*算法结果创建PathRoute对象
        /// </summary>
        private PathRoute CreateAutoPathRoute(PathFindingResult pathResult, string routeName)
        {
            try
            {
                var route = new PathRoute(routeName);
                var pathPoints = pathResult.PathPoints;

                // 设置路径完成状态信息
                route.IsComplete = pathResult.IsComplete;
                route.OriginalEndPoint = pathResult.OriginalEndPoint;
                route.ActualEndPoint = pathResult.ActualEndPoint;
                route.CompletionPercentage = pathResult.CompletionPercentage;

                for (int i = 0; i < pathPoints.Count; i++)
                {
                    var point = pathPoints[i];
                    var pathPoint = new PathPoint
                    {
                        Name = GenerateAutoPathPointName(i, pathPoints.Count),
                        Position = point,
                        Type = DeterminePointType(i, pathPoints.Count),
                        SpeedLimit = GetSpeedLimitAtPosition(point)
                    };
                    route.AddPoint(pathPoint);
                }

                // 注意：AddPoint已经调用RecalculateAndSaveRoute计算了曲线化长度
                // 不需要再调用RecalculateLength()，否则会覆盖正确的曲线长度

                LogManager.Info($"创建自动路径: {routeName}, 点数: {pathPoints.Count}, 长度: {route.TotalLength:F2}米");
                return route;
            }
            catch (Exception ex)
            {
                LogManager.Error($"创建自动路径失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 根据世界坐标获取该位置的限速
        /// </summary>
        /// <param name="worldPosition">世界坐标</param>
        /// <returns>限速值（米/秒），0表示未设置限速</returns>
        private double GetSpeedLimitAtPosition(Point3D worldPosition)
        {
            try
            {
                // 如果没有当前网格地图，返回0
                if (_currentGridMap == null)
                {
                    return 0;
                }

                // 将世界坐标转换为网格坐标
                var gridPos = _currentGridMap.WorldToGrid(worldPosition);

                // 检查网格坐标是否有效
                if (!_currentGridMap.IsValidGridPosition(gridPos))
                {
                    return 0;
                }

                // 获取网格单元格
                var cell = _currentGridMap.GetCell(gridPos);
                return cell?.SpeedLimit ?? 0;
            }
            catch (Exception ex)
            {
                LogManager.Error($"获取位置限速失败: {ex.Message}");
                return 0;
            }
        }

        /// <summary>
        /// 生成自动路径点名称
        /// </summary>
        private string GenerateAutoPathPointName(int index, int totalCount)
        {
            if (index == 0) return "自动起点";
            if (index == totalCount - 1) return "自动终点";
            return $"自动点{index}";
        }

        /// <summary>
        /// 确定路径点类型
        /// </summary>
        private PathPointType DeterminePointType(int index, int totalCount)
        {
            if (index == 0) return PathPointType.StartPoint;
            if (index == totalCount - 1) return PathPointType.EndPoint;
            return PathPointType.WayPoint;
        }


        /// <summary>
        /// 绘制路径可视化
        /// </summary>
        public void DrawRouteVisualization(PathRoute route, bool isAutoPath = false)
        {
            if (route == null) return;

            try
            {
                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin == null)
                {
                    LogManager.Warning("PathPointRenderPlugin实例为空，无法绘制路径");
                    return;
                }

                // 使用新的统一路径渲染API
                renderPlugin.RenderPath(route);

                LogManager.Info($"已渲染路径: {route.Name}，包含 {route.Points.Count} 个路径点");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"路径可视化失败: {ex.Message}");
            }
        }

        #endregion

        #region 辅助方法（检查项目关系）

        /// <summary>
        /// 检查项目是否在选定通道中
        /// </summary>
        /// <param name="item">要检查的项目</param>
        /// <returns>是否在选定通道中</returns>
        private bool IsItemInSelectedChannels(ModelItem item)
        {
            return _walkableAreas.Contains(item) || IsItemChildOfSelectedChannels(item);
        }

        /// <summary>
        /// 检查项目是否为选定通道的子项
        /// </summary>
        /// <param name="item">要检查的项目</param>
        /// <returns>是否为子项</returns>
        private bool IsItemChildOfSelectedChannels(ModelItem item)
        {
            foreach (var channel in _walkableAreas)
            {
                if (IsChildOf(item, channel))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 递归检查是否为子项
        /// </summary>
        /// <param name="child">子项</param>
        /// <param name="parent">父项</param>
        /// <returns>是否为子项</returns>
        private bool IsChildOf(ModelItem child, ModelItem parent)
        {
            var currentParent = child.Parent;
            while (currentParent != null)
            {
                if (currentParent == parent)
                {
                    return true;
                }
                currentParent = currentParent.Parent;
            }
            return false;
        }

        /// <summary>
        /// 状态变更通知（向后兼容方法）
        /// </summary>
        /// <param name="status">状态消息</param>
        private void OnStatusChanged(string status)
        {
            try
            {
                // 使用新的事件触发机制
                RaiseStatusChanged(status, PathPlanningStatusType.Info);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[PathManager] OnStatusChanged方法异常: {ex.Message}");
                LogManager.Error($"[PathManager] 状态消息: {status}");
            }
        }

        #endregion

        #region 预览插入位置计算方法

        /// <summary>
        /// 查找预览点应该插入的最近线段和插入索引
        /// </summary>
        /// <param name="previewPosition">预览点位置</param>
        /// <param name="pathPoints">路径点列表</param>
        /// <returns>最近线段的前后两点以及插入索引，未找到时返回null</returns>
        private (PathPoint prevPoint, PathPoint nextPoint, int insertIndex)? FindNearestLineSegmentWithIndex(Point3D previewPosition, List<PathPoint> pathPoints)
        {
            if (pathPoints == null || pathPoints.Count < 2)
            {
                return null;
            }

            // 对路径点进行排序（按添加顺序，即列表中的索引）
            var sortedPoints = pathPoints.ToList();

            double minDistance = double.MaxValue;
            (PathPoint prevPoint, PathPoint nextPoint, int insertIndex)? 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;
                    // 插入索引应该是nextPoint的索引位置，这样新点会插入到currentPoint和nextPoint之间
                    nearestSegment = (currentPoint, nextPoint, i + 1);
                }
            }

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

        /// <summary>
        /// 计算两点间距离
        /// </summary>
        /// <param name="point1">第一个点</param>
        /// <param name="point2">第二个点</param>
        /// <returns>两点间距离</returns>
        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);
        }

        #endregion

        #region 网格可视化方法

        /// <summary>
        /// 更新网格可视化设置
        /// </summary>
        /// <param name="showWalkable">是否显示可通行网格点</param>
        /// <param name="showObstacle">是否显示障碍物网格点</param>
        /// <param name="showUnknown">是否显示未知区域网格点</param>
        /// <param name="showDoor">是否显示门网格点</param>
        public void UpdateGridVisualizationSettings(bool showWalkable, bool showObstacle, bool showUnknown, bool showDoor = false)
        {
            try
            {
                LogManager.Info($"[网格可视化设置] 更新设置: 通行={showWalkable}, 障碍物={showObstacle}, 未知={showUnknown}, 门={showDoor}");

                _showWalkableGrid = showWalkable;
                _showObstacleGrid = showObstacle;
                _showUnknownGrid = showUnknown;
                _showDoorGrid = showDoor;

                // 如果当前有网格正在显示，重新应用可视化
                RefreshGridVisualization();

                LogManager.Info("[网格可视化设置] 设置更新完成");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[网格可视化设置] 更新设置失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 检查是否有任何网格可视化已启用
        /// </summary>
        public bool IsAnyGridVisualizationEnabled
        {
            get { return _showWalkableGrid || _showObstacleGrid || _showUnknownGrid || _showDoorGrid; }
        }

        /// <summary>
        /// 按自动路径保存的规划参数重建GridMap，用于数据库重载后恢复网格可视化和诊断。
        /// </summary>
        public bool TryRestoreGridMapForRoute(PathRoute route, out GridMap gridMap, out string message)
        {
            gridMap = null;
            message = null;

            try
            {
                if (route == null)
                {
                    message = "路径为空，无法重建GridMap";
                    LogManager.Warning($"[网格可视化] {message}");
                    return false;
                }

                if (route.AssociatedGridMap != null)
                {
                    gridMap = route.AssociatedGridMap;
                    message = $"路径 '{route.Name}' 已有关联GridMap";
                    return true;
                }

                List<PathPoint> orderedPoints = route.Points?.OrderBy(point => point.Index).ToList() ?? new List<PathPoint>();
                if (orderedPoints.Count < 2)
                {
                    message = $"路径 '{route.Name}' 点数不足，无法重建GridMap";
                    LogManager.Warning($"[网格可视化] {message}");
                    return false;
                }

                if (route.GridSize <= 0)
                {
                    message = $"路径 '{route.Name}' 缺少有效网格大小，无法重建GridMap";
                    LogManager.Warning($"[网格可视化] {message}");
                    return false;
                }

                double objectRadius = Math.Max(route.MaxObjectLength, route.MaxObjectWidth) / 2.0;
                if (objectRadius <= 0)
                {
                    message = $"路径 '{route.Name}' 缺少有效物体长宽，无法重建GridMap";
                    LogManager.Warning($"[网格可视化] {message}");
                    return false;
                }

                if (route.SafetyMargin < 0)
                {
                    message = $"路径 '{route.Name}' 安全间隙为负数，无法重建GridMap: {route.SafetyMargin}";
                    LogManager.Warning($"[网格可视化] {message}");
                    return false;
                }

                if (route.MaxObjectHeight <= 0)
                {
                    message = $"路径 '{route.Name}' 缺少有效物体高度，无法重建GridMap";
                    LogManager.Warning($"[网格可视化] {message}");
                    return false;
                }

                BoundingBox3D bounds = GetModelBounds();
                if (bounds == null)
                {
                    message = "无法获取模型边界，无法重建GridMap";
                    LogManager.Warning($"[网格可视化] {message}");
                    return false;
                }

                PathPoint startPoint = orderedPoints.First();
                PathPoint endPoint = orderedPoints.Last();
                LogManager.Info(
                    $"[网格可视化] 开始按路径参数重建GridMap: 路径={route.Name}, 网格={route.GridSize}m, " +
                    $"物体半径={objectRadius}m, 安全间隙={route.SafetyMargin}m, 高度={route.MaxObjectHeight}m");

                var gridMapGenerator = new GridMapGenerator();
                gridMap = gridMapGenerator.GenerateFromBIM(
                    bounds,
                    route.GridSize,
                    objectRadius,
                    route.SafetyMargin,
                    startPoint.Position,
                    endPoint.Position,
                    route.MaxObjectHeight);

                if (gridMap == null)
                {
                    message = $"路径 '{route.Name}' 的GridMap重建失败";
                    LogManager.Warning($"[网格可视化] {message}");
                    return false;
                }

                route.AssociatedGridMap = gridMap;
                if (_currentRoute == route || (_currentRoute != null && _currentRoute.Id == route.Id))
                {
                    _currentGridMap = gridMap;
                    _currentObjectHeight = route.MaxObjectHeight;
                }

                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin != null)
                {
                    renderPlugin.SetGridSize(UnitsConverter.ConvertToMeters(gridMap.CellSize));
                }

                message = $"路径 '{route.Name}' 的GridMap已重建: {gridMap.GetStatistics()}";
                LogManager.Info($"[网格可视化] {message}");
                return true;
            }
            catch (Exception ex)
            {
                message = $"重建GridMap失败: {ex.Message}";
                LogManager.Error($"[网格可视化] {message}", ex);
                gridMap = null;
                return false;
            }
        }

        /// <summary>
        /// 刷新网格可视化（根据当前设置重新显示）
        /// </summary>
        private void RefreshGridVisualization()
        {
            try
            {
                // 清除当前网格可视化
                ClearGridVisualization();

                if (!IsAnyGridVisualizationEnabled)
                {
                    LogManager.Info("[网格可视化] 网格可视化设置已关闭，跳过渲染");
                    return;
                }

                if (_currentGridMap == null && _currentRoute != null)
                {
                    if (!TryRestoreGridMapForRoute(_currentRoute, out GridMap restoredGridMap, out string restoreMessage))
                    {
                        LogManager.Info($"[网格可视化] {restoreMessage}");
                    }
                    else
                    {
                        _currentGridMap = restoredGridMap;
                    }
                }

                // 如果存在缓存的网格地图且有网格可视化设置启用，重新进行可视化
                if (_currentGridMap != null)
                {
                    LogManager.Info("[网格可视化] 使用缓存的网格地图重新渲染");
                    VisualizeGridCells(_currentGridMap, _currentObjectHeight);
                }
                else
                {
                    LogManager.Info("[网格可视化] 无缓存网格地图，且无法通过当前路径参数重建");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[网格可视化] 刷新失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 在3D视图中可视化网格中的可通行单元格
        /// 在每个可通行网格的中心绘制一个绿色小球
        /// </summary>
        /// <param name="gridMap">要可视化的网格地图</param>
        /// <param name="objectHeight">物体高度（米），用于判断层高是否足够</param>
        public void VisualizeGridCells(GridMap gridMap, double objectHeight = 2.0)
        {
            if (gridMap == null)
            {
                LogManager.Warning("[网格可视化] 网格地图为null，无法进行可视化");
                return;
            }

            try
            {
                // 保存当前网格地图和物体高度用于后续刷新
                _currentGridMap = gridMap;
                _currentObjectHeight = objectHeight;
                LogManager.Info($"[网格可视化] 开始可视化网格：{gridMap.Width}x{gridMap.Height}, 物体高度：{objectHeight}m");

                // 获取渲染插件
                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin == null)
                {
                    LogManager.Warning("[网格可视化] PathPointRenderPlugin实例为空，无法绘制网格");
                    return;
                }

                // 设置网格大小以实现自适应点大小
                // gridMap.CellSize是模型单位，需要转换为米
                double gridSizeInMeters = UnitsConverter.ConvertToMeters(gridMap.CellSize);
                renderPlugin.SetGridSize(gridSizeInMeters);

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

                // 创建网格可视化集合
                var gridVis = new GridVisualization("grid_visualization");

                // 统计变量
                int channelCells = 0;
                int unknownCells = 0;
                int obstacleCells = 0;
                int doorCells = 0;
                int totalVisualized = 0;
                int multiLayerCells = 0;

                // 遍历所有网格单元格，根据类型分别收集
                for (int x = 0; x < gridMap.Width; x++)
                {
                    for (int y = 0; y < gridMap.Height; y++)
                    {
                        var cell = gridMap.Cells[x, y];

                        // 当前 GridMap 的索引语义是采样节点：GridToWorld2D(x,y)
                        // 必须直接作为可视化平面位置，不能再按左下角单元取 (x+1,y+1) 平均。
                        var gridPos = new NavisworksTransport.PathPlanning.GridPoint2D(x, y);
                        var gridNode2D = gridMap.GridToWorld2D(gridPos);

                        // 所有网格都基于高度层，统一处理
                        if (cell.HeightLayers != null && cell.HeightLayers.Count > 0)
                        {
                            multiLayerCells++;

                            foreach (var layer in cell.HeightLayers)
                            {
                                double layerZ = layer.Z;

                                GridVisualizationType? cellType = null;

                                // 仅根据 layer.IsWalkable 决定渲染
                                if (layer.IsWalkable)
                                {
                                    // 可通行层 - 门特殊处理，其他统一样式
                                    if (cell.CellType == "门")
                                    {
                                        if (_showDoorGrid)
                                        {
                                            cellType = GridVisualizationType.Door;
                                            doorCells++;
                                        }
                                    }
                                    else
                                    {
                                        // 其他可通行类型统一为通道样式（绿色）
                                        if (_showWalkableGrid)
                                        {
                                            cellType = GridVisualizationType.Walkable;
                                            channelCells++;
                                        }
                                    }
                                }
                                else
                                {
                                    // 不可通行层 - 渲染为障碍物（灰色）
                                    if (_showObstacleGrid)
                                    {
                                        cellType = GridVisualizationType.Obstacle;
                                        obstacleCells++;
                                    }
                                }

                                // 创建该层的可视化标记
                                if (cellType.HasValue)
                                {
                                    var gridNode = gridMap.SetWorldElevation(gridNode2D, layerZ);
                                    var marker = new GridMarker(gridNode, cellType.Value, x, y, layerZ);

                                    // 根据类型添加到对应列表
                                    switch (cellType.Value)
                                    {
                                        case GridVisualizationType.Walkable:
                                            gridVis.Walkable.Add(marker);
                                            break;
                                        case GridVisualizationType.Obstacle:
                                            gridVis.Obstacle.Add(marker);
                                            break;
                                        case GridVisualizationType.Unknown:
                                            gridVis.Unknown.Add(marker);
                                            break;
                                        case GridVisualizationType.Door:
                                            gridVis.Door.Add(marker);
                                            break;
                                    }
                                    totalVisualized++;
                                }
                            }
                        }
                        else if (cell.CellType == "空洞")
                        {
                            // Unknown网格没有高度层，用于调试
                            if (_showUnknownGrid)
                            {
                                double unknownElevation = gridMap.GetWorldElevation(gridNode2D);
                                var gridNode = gridMap.SetWorldElevation(gridNode2D, unknownElevation);
                                var marker = new GridMarker(gridNode, GridVisualizationType.Unknown, x, y, unknownElevation);
                                gridVis.Unknown.Add(marker);
                                unknownCells++;
                                totalVisualized++;
                            }
                        }
                    }
                }

                // 使用新的专门渲染方法（类型安全）
                renderPlugin.RenderGridVisualization(gridVis);

                // 输出统计信息
                LogManager.Info($"[网格可视化] 可视化完成：");
                LogManager.Info($"  - 总网格单元格数：{gridMap.Width * gridMap.Height}");
                LogManager.Info($"  - 多层网格数：{multiLayerCells}");
                LogManager.Info($"  - 可通行层数：{channelCells}");
                LogManager.Info($"  - 门层数：{doorCells}");
                LogManager.Info($"  - Unknown单元格数：{unknownCells}");
                LogManager.Info($"  - 障碍物层数：{obstacleCells}");
                LogManager.Info($"  - 已可视化点数：{totalVisualized}");

                RaiseStatusChanged($"网格可视化完成：显示了 {totalVisualized} 个网格层 (多层网格:{multiLayerCells}, 可通行:{channelCells}, 门:{doorCells}, Unknown:{unknownCells}, 障碍:{obstacleCells})", PathPlanningStatusType.Success);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[网格可视化] 可视化失败: {ex.Message}");
                RaiseErrorOccurred($"网格可视化失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 清除网格可视化
        /// </summary>
        public void ClearGridVisualization()
        {
            try
            {
                LogManager.Info("[网格可视化] 开始清除网格可视化");

                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin != null)
                {
                    // 清除所有网格可视化（使用新的 ID 命名）
                    renderPlugin.RemovePath("grid_visualization_walkable");  // 可通行的网格
                    renderPlugin.RemovePath("grid_visualization_obstacle");   // 障碍物网格
                    renderPlugin.RemovePath("grid_visualization_unknown");    // 未知区域网格
                    renderPlugin.RemovePath("grid_visualization_door");       // 门网格
                    // 清除旧的网格可视化 ID（向后兼容）
                    renderPlugin.RemovePath("grid_visualization_all");
                    renderPlugin.RemovePath("grid_visualization_channel");
                    LogManager.Info("[网格可视化] 网格可视化已清除");
                }
                else
                {
                    LogManager.Warning("[网格可视化] PathPointRenderPlugin实例为空，无法清除可视化");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[网格可视化] 清除可视化失败: {ex.Message}");
            }
        }

        #endregion

        #region 路径分析方法

        /// <summary>
        /// 获取所有路径（供分析使用）
        /// </summary>
        /// <summary>
        /// 按 ID 查询碰撞检测记录（集成测试验证检测记录持久化）。
        /// </summary>
        public CollisionDetectionRecord GetDetectionRecordById(int id)
        {
            return _pathDatabase?.GetDetectionResultById(id);
        }

        /// <summary>
        /// 添加模型项引用（如批处理移动物体），转发到数据库。
        /// </summary>
        public async Task<int> AddModelItemReferenceAsync(
            int referenceId, string referenceType, int modelIndex, string pathId,
            string displayName, string objectName, string role)
        {
            if (_pathDatabase == null)
            {
                return 0;
            }

            return await _pathDatabase.AddModelItemReferenceAsync(
                referenceId, referenceType, modelIndex, pathId, displayName, objectName, role).ConfigureAwait(false);
        }

        /// <summary>
        /// 获取模型项引用（如批处理移动物体），转发到数据库。
        /// </summary>
        public async Task<List<(int ModelIndex, string PathId, string DisplayName, string ObjectName)>> GetModelItemReferencesAsync(
            int referenceId, string referenceType, string role = null)
        {
            if (_pathDatabase == null)
            {
                return new List<(int, string, string, string)>();
            }

            return await _pathDatabase.GetModelItemReferencesAsync(referenceId, referenceType, role).ConfigureAwait(false);
        }

        /// <summary>
        /// 路径分析（效率/安全评分），集成测试验证分析链路。
        /// </summary>
        public PathAnalysisResult AnalyzeRoute(PathRoute route, string strategy = "安全优先")
        {
            if (_analysisService == null)
            {
                throw new InvalidOperationException("路径分析服务未初始化");
            }

            return _analysisService.AnalyzePath(route, strategy);
        }

        public List<PathRoute> GetAllRoutes()
        {
            try
            {
                // 直接返回内存中的路径列表
                // 因为所有路径操作都已同步到数据库，内存列表就是当前的完整列表
                return _routes ?? new List<PathRoute>();
            }
            catch (Exception ex)
            {
                LogManager.Error($"获取所有路径失败: {ex.Message}", ex);
                return new List<PathRoute>();
            }
        }

        /// <summary>
        /// 分析多条路径并进行对比
        /// </summary>
        /// <param name="routeIds">要分析的路径ID列表</param>
        /// <param name="strategy">分析策略</param>
        /// <returns>对比结果</returns>
        public PathComparisonResult AnalyzePathsAndCompare(List<string> routeIds, string strategy)
        {
            try
            {
                if (_analysisService == null)
                {
                    LogManager.Error("路径分析服务未初始化");
                    return null;
                }

                // 获取要分析的路径
                var routesToAnalyze = _routes?.Where(r => routeIds.Contains(r.Id)).ToList();
                if (routesToAnalyze == null || routesToAnalyze.Count == 0)
                {
                    LogManager.Warning("未找到要分析的路径");
                    return null;
                }

                // 执行分析和对比
                var result = _analysisService.CompareRoutes(routesToAnalyze, strategy);

                return result;
            }
            catch (Exception ex)
            {
                LogManager.Error($"路径分析失败: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 从数据库加载历史路径到内存
        /// </summary>
        private void LoadHistoricalRoutesFromDatabase()
        {
            try
            {
                var historicalRoutes = _pathDatabase.GetAllPathRoutes();
                if (historicalRoutes != null && historicalRoutes.Count > 0)
                {
                    // 使用HashSet记录已存在的路径ID，避免重复
                    var existingIds = new HashSet<string>(_routes.Select(r => r.Id));
                    int loadedCount = 0;

                    // 加载历史路径（跳过已存在的）
                    foreach (var route in historicalRoutes)
                    {
                        if (!existingIds.Contains(route.Id))
                        {
                            _routes.Add(route);
                            loadedCount++;
                            //LogManager.Info($"加载历史路径: {route.Name}, ID={route.Id}, 长度={route.TotalLength:F2}米");
                        }
                    }

                    if (loadedCount > 0)
                    {
                        LogManager.Info($"成功从数据库加载 {loadedCount} 条历史路径（总计 {historicalRoutes.Count} 条）");
                    }
                    else
                    {
                        LogManager.Info($"数据库中的 {historicalRoutes.Count} 条路径已全部在内存中");
                    }

                    // 历史路径加载完成后，触发RoutesLoaded事件通知UI刷新
                    RaiseRoutesLoaded(_routes.AsReadOnly(), "Database");
                    LogManager.Info($"已触发RoutesLoaded事件，通知UI刷新历史路径列表");
                }
                else
                {
                    LogManager.Info("数据库中没有历史路径记录");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"加载历史路径失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 保存路径时同时保存到数据库
        /// </summary>
        public void SavePathToDatabase(PathRoute route)
        {
            try
            {
                if (route == null)
                {
                    return;
                }

                if (_pathDatabase == null)
                {
                    DatabaseInitialize(createIfMissing: true);
                }

                if (_pathDatabase != null)
                {
                    _pathDatabase.SavePathRoute(route);
                    LogManager.Info($"路径已保存到数据库: {route.Name}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"保存路径到数据库失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取Instance单例（为兼容现有代码）
        /// </summary>
        public static PathPlanningManager Instance
        {
            get
            {
                if (_activePathManager == null)
                {
                    LogManager.Warning("PathPlanningManager未初始化，创建新实例");
                    _activePathManager = new PathPlanningManager();
                }
                return _activePathManager;
            }
        }

        #endregion

        #region 静态方法

        /// <summary>
        /// 静态方法：获取当前活动的路径管理器
        /// </summary>
        /// <returns>当前活动的路径管理器</returns>
        public static PathPlanningManager GetActivePathManager()
        {
            return _activePathManager;
        }

        internal static PathPoint ReuseLastHoistingPointAsDescendPoint(IList<PathPoint> points)
        {
            if (points == null)
            {
                throw new ArgumentNullException(nameof(points));
            }

            if (points.Count == 0)
            {
                throw new ArgumentException("吊装路径至少需要一个空中点才能复用为下降点。", nameof(points));
            }

            PathPoint descendPoint = points[points.Count - 1];
            descendPoint.Name = "下降点";
            descendPoint.Type = PathPointType.WayPoint;
            descendPoint.Direction = HoistingPointDirection.Vertical;
            descendPoint.Index = points.Count - 1;
            return descendPoint;
        }

        #endregion
    }
}
