using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows;
using System.Windows.Input;
using System.Threading.Tasks;
using System.Linq;
using System.IO;
using System.Text;
using System.Numerics;
using Microsoft.Win32;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;
using NavisApplication = Autodesk.Navisworks.Api.Application;
using NavisworksTransport.Core;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Commands;
using NavisworksTransport.UI.WPF.Views;
using NavisworksTransport.UI.WPF.Models;
using NavisworksTransport.Utils;
using NavisworksTransport.Utils.CoordinateSystem;
using NavisworksTransport.Utils.GeometryAnalysis;

namespace NavisworksTransport.UI.WPF.ViewModels
{
    /// <summary>
    /// 路径策略选项辅助类
    /// </summary>
    public class PathStrategyOption
    {
        /// <summary>
        /// 策略值
        /// </summary>
        public PathStrategy Value { get; set; }

        /// <summary>
        /// 显示名称
        /// </summary>
        public string DisplayName { get; set; }

        /// <summary>
        /// 详细描述
        /// </summary>
        public string Description { get; set; }
    }

    /// <summary>
    /// Rail 构型选项辅助类
    /// </summary>
    /// <typeparam name="T">枚举类型</typeparam>
    public class RailConfigOption<T>
    {
        /// <summary>
        /// 配置值
        /// </summary>
        public T Value { get; set; }

        /// <summary>
        /// 显示名称
        /// </summary>
        public string DisplayName { get; set; }

        /// <summary>
        /// 详细描述
        /// </summary>
        public string Description { get; set; }
    }

    /// <summary>
    /// 路径编辑页面专用ViewModel
    /// </summary>
    public class PathEditingViewModel : ViewModelBase, IDisposable
    {
        #region 私有字段

        private PathPlanningManager _pathPlanningManager;
        private readonly UIStateManager _uiStateManager;
        private readonly PathDataManager _pathDataManager;

        // 路径集合
        private ObservableCollection<PathRouteViewModel> _pathRoutes;
        private PathRouteViewModel _selectedPathRoute;
        private PathPointViewModel _selectedPathPoint;
        private bool _isPathEditMode;

        // 自动路径规划参数
        private string _autoPathStartPoint = "未选择";
        private string _autoPathEndPoint = "未选择";
        private Point3D _startPoint3D;
        private Point3D _endPoint3D;
        private bool _hasStartPoint = false;
        private bool _hasEndPoint = false;
        private bool _isSelectingStartPoint = false;
        private bool _isSelectingEndPoint = false;

        // 物体参数 - 改为三个独立参数(从配置初始化)
        private double _objectLength;  // 物体长度(米)
        private double _objectWidth;   // 物体宽度(米)
        private double _objectHeight;  // 物体高度(米)
        private double _safetyMargin;  // 安全间隙(米)

        // 网格大小参数(从配置初始化)
        private bool _isGridSizeManuallyEnabled = false;  // 是否启用手动网格大小设置
        private double _gridSize;  // 网格大小(米)

        // 可视化参数
        private bool _showWalkableGrid = false;
        private bool _showObstacleGrid = false;
        private bool _showUnknownGrid = false;
        private bool _showDoorGrid = false;
        private GridPointType _gridPointType = GridPointType.Rectangle;
        // 三种渲染模式独立开关
        private bool _showControlVisualization = true;  // 默认显示控制点连线
        private bool _showPathLines = true;             // 默认显示路径线(地面连线)
        private bool _showObjectSpace = false;         // 默认不显示通行空间
        // 渲染模式已改为独立开关(_showControlVisualization, _showPathLines, _showObjectSpace)
        // 下面的互斥属性已废弃并删除

        // 路径策略参数
        private PathStrategyOption _selectedPathStrategy;
        private ObservableCollection<PathStrategyOption> _pathStrategyOptions;
        private ObservableCollection<RailConfigOption<RailMountMode>> _railMountModeOptions;
        private const double DefaultAssemblyReferenceRodLengthInMeters = 20.0;
        private static readonly double DefaultAssemblyReferenceRodDiameterInMeters = CalculateDefaultAssemblyReferenceRodDiameterInMeters();
        private const double DefaultAssemblyAnchorVerticalOffsetInMeters = 0.0;
        private const double AssemblyVisualizationPointDiameterInMeters = 0.05;
        private const double RailNormalOffsetNudgeStepInMeters = 0.1;
        private const double DefaultAssemblySphereCenterX = 0.0;
        private const double DefaultAssemblySphereCenterY = 0.0;
        private const double DefaultAssemblySphereCenterZ = 0.0;
        private readonly RailAssemblyWorkflowContext _railAssemblyContext = new RailAssemblyWorkflowContext(
            DefaultAssemblyReferenceRodLengthInMeters,
            DefaultAssemblyReferenceRodDiameterInMeters,
            DefaultAssemblyAnchorVerticalOffsetInMeters,
            DefaultAssemblySphereCenterX,
            DefaultAssemblySphereCenterY,
            DefaultAssemblySphereCenterZ);
        private const string AssemblyAnchorMarkerPathId = "assembly_anchor_marker";
        private const string AssemblyCenterGuideLinePathId = "assembly_center_guide_line";
        private const string AssemblyReferenceLinePathId = "assembly_reference_line";
        private const string AssemblyEndFaceSeedPathId = "assembly_end_face_seed_points";
        private const string AssemblyEndFaceCenterPathId = "assembly_end_face_center";
        private const string AssemblyEndFaceNormalPathId = "assembly_end_face_normal";
        private const string AssemblyInstallationPickPointPathId = "assembly_install_pick_point";
        private const string AssemblyInstallationAnchorPointPathId = "assembly_install_anchor_point";
        private const string AssemblyInstallationCenterLinePathId = "assembly_install_center_line";
        private const string AssemblyInstallationOffsetLinePathId = "assembly_install_offset_line";
        private const string AssemblyInstallationPlanePathId = "assembly_install_plane";
        private const double AssemblyInstallationPlanePaddingInMeters = 0.5;
        private const double AssemblyInstallationLineLengthScale = 1.2;

        private string _assemblyTerminalObjectName
        {
            get => _railAssemblyContext.TerminalObjectName;
            set => _railAssemblyContext.TerminalObjectName = value;
        }

        private string _assemblyTerminalObjectInfo
        {
            get => _railAssemblyContext.TerminalObjectInfo;
            set => _railAssemblyContext.TerminalObjectInfo = value;
        }

        private double _assemblyReferenceRodLengthInMeters
        {
            get => _railAssemblyContext.ReferenceRodLengthInMeters;
            set => _railAssemblyContext.ReferenceRodLengthInMeters = value;
        }

        private double _assemblyReferenceRodDiameterInMeters
        {
            get => _railAssemblyContext.ReferenceRodDiameterInMeters;
            set => _railAssemblyContext.ReferenceRodDiameterInMeters = value;
        }

        private double _assemblyAnchorVerticalOffsetInMeters
        {
            get => _railAssemblyContext.AnchorVerticalOffsetInMeters;
            set => _railAssemblyContext.AnchorVerticalOffsetInMeters = value;
        }

        private double _assemblySphereCenterX
        {
            get => _railAssemblyContext.SphereCenterX;
            set => _railAssemblyContext.SphereCenterX = value;
        }

        private double _assemblySphereCenterY
        {
            get => _railAssemblyContext.SphereCenterY;
            set => _railAssemblyContext.SphereCenterY = value;
        }

        private double _assemblySphereCenterZ
        {
            get => _railAssemblyContext.SphereCenterZ;
            set => _railAssemblyContext.SphereCenterZ = value;
        }

        private string _assemblyStartPointText
        {
            get => _railAssemblyContext.StartPointText;
            set => _railAssemblyContext.StartPointText = value;
        }

        private RailMountMode _assemblyMountMode
        {
            get => _railAssemblyContext.MountMode;
            set => _railAssemblyContext.MountMode = value;
        }

        private bool _hasAssemblyTerminalObject
        {
            get => _railAssemblyContext.HasTerminalObject;
            set => _railAssemblyContext.HasTerminalObject = value;
        }

        private bool _isSelectingAssemblyStartPoint
        {
            get => _railAssemblyContext.IsSelectingStartPoint;
            set => _railAssemblyContext.IsSelectingStartPoint = value;
        }

        private bool _isSelectingAssemblyEndFacePoints
        {
            get => _railAssemblyContext.IsSelectingEndFacePoints;
            set => _railAssemblyContext.IsSelectingEndFacePoints = value;
        }

        private bool _isSelectingAssemblyInstallationPoint
        {
            get => _railAssemblyContext.IsSelectingInstallationPoint;
            set => _railAssemblyContext.IsSelectingInstallationPoint = value;
        }

        private RailAssemblyWorkflowMode _railAssemblyWorkflowMode
        {
            get => _railAssemblyContext.WorkflowMode;
            set => _railAssemblyContext.WorkflowMode = value;
        }

        private bool _hasAssemblyEndFaceAnalysis
        {
            get => _railAssemblyContext.HasEndFaceAnalysis;
            set => _railAssemblyContext.HasEndFaceAnalysis = value;
        }

        private bool _hasAssemblyInstallationReference
        {
            get => _railAssemblyContext.HasInstallationReference;
            set => _railAssemblyContext.HasInstallationReference = value;
        }

        private ModelItem _assemblyTerminalObject
        {
            get => _railAssemblyContext.TerminalObject;
            set => _railAssemblyContext.TerminalObject = value;
        }

        private Point3D _assemblyStartPoint
        {
            get => _railAssemblyContext.StartPoint;
            set => _railAssemblyContext.StartPoint = value;
        }

        private Point3D _assemblyEndFaceCenterPoint
        {
            get => _railAssemblyContext.EndFaceCenterPoint;
            set => _railAssemblyContext.EndFaceCenterPoint = value;
        }

        private Vector3 _assemblyEndFaceNormal
        {
            get => _railAssemblyContext.EndFaceNormal;
            set => _railAssemblyContext.EndFaceNormal = value;
        }

        private Point3D _assemblyInstallationPickPoint
        {
            get => _railAssemblyContext.InstallationPickPoint;
            set => _railAssemblyContext.InstallationPickPoint = value;
        }

        private Point3D _assemblyInstallationBaseAnchorPoint
        {
            get => _railAssemblyContext.InstallationBaseAnchorPoint;
            set => _railAssemblyContext.InstallationBaseAnchorPoint = value;
        }

        private Point3D _assemblyInstallationAnchorPoint
        {
            get => _railAssemblyContext.InstallationAnchorPoint;
            set => _railAssemblyContext.InstallationAnchorPoint = value;
        }

        private Vector3 _assemblyInstallationPlaneNormal
        {
            get => _railAssemblyContext.InstallationPlaneNormal;
            set => _railAssemblyContext.InstallationPlaneNormal = value;
        }

        private Vector3 _assemblyInstallationPlaneSpanDirection
        {
            get => _railAssemblyContext.InstallationPlaneSpanDirection;
            set => _railAssemblyContext.InstallationPlaneSpanDirection = value;
        }

        private double _assemblyInstallationOffsetDistanceInMeters
        {
            get => _railAssemblyContext.InstallationOffsetDistanceInMeters;
            set => _railAssemblyContext.InstallationOffsetDistanceInMeters = value;
        }

        private string _assemblyInstallationReferenceRouteId
        {
            get => _railAssemblyContext.InstallationReferenceRouteId;
            set => _railAssemblyContext.InstallationReferenceRouteId = value;
        }

        private List<Point3D> _assemblyInstallationSeedPoints => _railAssemblyContext.InstallationSeedPoints;

        private List<Point3D> _assemblyEndFaceSeedPoints => _railAssemblyContext.EndFaceSeedPoints;

        // 自动路径起点和终点的路径对象引用(用于正确的ID管理)
        private PathRoute _autoPathStartPointRoute = null;
        private PathRoute _autoPathEndPointRoute = null;


        // 资源清理管理
        private bool _disposed = false;

        // 多层吊装模式
        private bool _isMultiLevelHoistingMode = false;
        private ObservableCollection<HoistingLevelItem> _multiLevelItems = new ObservableCollection<HoistingLevelItem>();
        private ObservableCollection<HoistingLayerEditItem> _hoistingLayerEditItems = new ObservableCollection<HoistingLayerEditItem>();
        private Point3D _multiLevelStartPoint;
        private Point3D _multiLevelEndPoint;
        private bool _hasMultiLevelStartPoint = false;
        private bool _hasMultiLevelEndPoint = false;
        private string _multiLevelStartPointText = "未选择";
        private string _multiLevelEndPointText = "未选择";
        private string _multiLevelStatsText = "层级数: 0 | 预估路径点数: 0";
        private string _hoistingLayerEditHintText = "选择一条吊装路径后,可在这里按层编辑相对起点的绝对高度。";
        private bool _isSelectingMultiLevelStartPoint = false;
        private bool _isSelectingMultiLevelEndPoint = false;
        private HoistingLevelItem _currentSelectingLevelTarget;

        #endregion

        #region 公共属性

        public ObservableCollection<PathRouteViewModel> PathRoutes
        {
            get => _pathRoutes;
            set => SetProperty(ref _pathRoutes, value);
        }

        public PathRouteViewModel SelectedPathRoute
        {
            get => _selectedPathRoute;
            set
            {
                if (SetProperty(ref _selectedPathRoute, value))
                {
                    // 路径变更时清除选中的路径点
                    SelectedPathPoint = null;
                    ResetRailAssemblyWorkflowState(announce: false);

                    // 🔧 修复:同步PathPlanningManager的CurrentRoute
                    if (_pathPlanningManager != null && value != null)
                    {
                        // 查找对应的Core路径对象
                        var coreRoute = _pathPlanningManager.Routes?.FirstOrDefault(r => r.Id == value.Id)
                            ?? _pathPlanningManager.Routes?.FirstOrDefault(r => r.Name == value.Name);
                        if (coreRoute != null)
                        {
                            if (coreRoute.PathType == PathType.Rail)
                            {
                                AssemblyMountMode = coreRoute.RailMountMode;
                                _assemblyAnchorVerticalOffsetInMeters = UnitsConverter.ConvertToMeters(coreRoute.RailNormalOffset);
                                OnPropertyChanged(nameof(AssemblyAnchorVerticalOffsetInMeters));
                            }

                            ApplyStoredAutoPlanningParameters(coreRoute);

                            // 🔥 先设置可视化模式(在 SetCurrentRoute 之前,确保事件触发时状态已就绪)
                            UpdatePassageSpaceVisualizationForPathType(coreRoute.PathType);

                            _pathPlanningManager.SetCurrentRoute(coreRoute);
                            LogManager.Info($"UI路径切换:已同步PathPlanningManager的CurrentRoute到 {value.Name}");

                            // 新建路径流程里禁止自动改视角,避免打断建路径操作。
                            if (_pathPlanningManager.PathEditState == PathEditState.Creating)
                            {
                                LogManager.Info($"UI路径切换:当前处于新建路径流程,跳过自动视角调整: {value.Name}");
                            }
                            // 自动调整视角到路径中心(只有路径有点时才调整)
                            else if (coreRoute.Points.Count > 0)
                            {
                                try
                                {
                                    ViewpointHelper.AdjustViewpointForPath(coreRoute);
                                    LogManager.Info($"UI路径切换:已自动调整视角: {value.Name}, 类型={coreRoute.PathType}");
                                }
                                catch (Exception ex)
                                {
                                    LogManager.Error($"UI路径切换:调整视角失败: {ex.Message}");
                                }
                            }
                            else
                            {
                                LogManager.Info($"UI路径切换:路径还没有点,跳过视角调整: {value.Name}");
                            }
                        }
                        else
                        {
                            LogManager.Warning($"UI路径切换:未找到对应的Core路径 {value.Name}");
                        }
                    }
                    else if (_pathPlanningManager != null && value == null)
                    {
                        // 如果选择了null,也要同步清除CurrentRoute
                        _pathPlanningManager.SetCurrentRoute(null);
                        LogManager.Info("UI路径切换:已清除PathPlanningManager的CurrentRoute");
                    }

                    // 更新命令状态
                    OnPropertyChanged(nameof(CanExecuteStartEdit));
                    OnPropertyChanged(nameof(CanExecuteEndEdit));
                    OnPropertyChanged(nameof(CanExecuteClearPath));
                    OnPropertyChanged(nameof(CanExecuteExportPath));
                    OnPropertyChanged(nameof(CanExecuteSaveAsPath));
                    OnPropertyChanged(nameof(CanExecuteModifyPoint));

                    // 🔥 路径类型改变时,检查是否可以使用路径线
                    OnPropertyChanged(nameof(CanUsePathLines));
                    OnPropertyChanged(nameof(IsRailRouteSelected));
                    OnPropertyChanged(nameof(IsHoistingRouteSelected));
                    OnPropertyChanged(nameof(SelectedRailMountMode));
                    OnPropertyChanged(nameof(SelectedRailNormalOffsetInMeters));
                    OnPropertyChanged(nameof(CanRepositionRailStartPoint));
                    OnPropertyChanged(nameof(CanApplyHoistingLayerHeights));
                    NotifyRailAssemblyCommandStateChanged();
                    if (!CanUsePathLines && ShowPathLines)
                    {
                        // 吊装和空轨路径不能使用路径线,自动关闭
                        ShowPathLines = false;
                        LogManager.Info("[路径可视化] 切换到吊装/空轨路径,自动关闭路径线");
                    }

                    RefreshHoistingLayerEditItemsFromSelectedRoute();

                    // 实现路径选择时的可视化切换
                    UpdatePathVisualization();
                }
            }
        }

        public PathPointViewModel SelectedPathPoint
        {
            get => _selectedPathPoint;
            set
            {
                if (SetProperty(ref _selectedPathPoint, value))
                {
                    // 更新修改路径点按钮的启用状态
                    OnPropertyChanged(nameof(CanExecuteModifyPoint));

                    // 路径点选中可视化:将选中的路径点显示为预览样式
                    try
                    {
                        if (value != null)
                        {
                            // 从PathPointViewModel创建PathPoint对象
                            var pathPoint = new PathPoint(
                                new Point3D(value.X, value.Y, value.Z),
                                value.Name,
                                value.Type
                            )
                            {
                                Id = value.Id
                            };

                            // 将选中的路径点设为预览样式
                            PathPointRenderPlugin.Instance.RenderPreviewPoint(pathPoint);
                            LogManager.Info($"路径点已设为预览样式: {value.Name}");
                        }
                        else
                        {
                            // 清除预览样式
                            PathPointRenderPlugin.Instance.ClearPreviewPoint();
                            LogManager.Info("已清除路径点预览样式");
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"路径点选中可视化失败: {ex.Message}");
                    }
                }
            }
        }

        public bool IsRailRouteSelected => SelectedPathRoute?.PathType == PathType.Rail;
        public bool IsHoistingRouteSelected => SelectedPathRoute?.PathType == PathType.Hoisting;

        public ObservableCollection<RailConfigOption<RailMountMode>> RailMountModeOptions
        {
            get => _railMountModeOptions;
        }

        public RailMountMode SelectedRailMountMode
        {
            get => GetSelectedCoreRoute()?.RailMountMode ?? RailMountMode.UnderRail;
            set
            {
                var coreRoute = GetSelectedCoreRoute();
                if (coreRoute == null || coreRoute.PathType != PathType.Rail || coreRoute.RailMountMode == value)
                {
                    return;
                }

                coreRoute.RailMountMode = value;
                AssemblyMountMode = value;
                ApplyRailRouteConfigurationChange(coreRoute, $"安装方式已更新为 {value}");
                OnPropertyChanged(nameof(SelectedRailMountMode));
            }
        }

        public double SelectedRailNormalOffsetInMeters
        {
            get
            {
                var coreRoute = GetSelectedCoreRoute();
                if (coreRoute == null || coreRoute.PathType != PathType.Rail)
                {
                    return 0.0;
                }

                return UnitsConverter.ConvertToMeters(coreRoute.RailNormalOffset);
            }
            set
            {
                var coreRoute = GetSelectedCoreRoute();
                if (coreRoute == null || coreRoute.PathType != PathType.Rail)
                {
                    return;
                }

                double offsetInModelUnits = UnitsConverter.ConvertFromMeters(value);
                if (Math.Abs(coreRoute.RailNormalOffset - offsetInModelUnits) < 1e-6)
                {
                    return;
                }

                _assemblyAnchorVerticalOffsetInMeters = value;
                OnPropertyChanged(nameof(AssemblyAnchorVerticalOffsetInMeters));
                coreRoute.RailNormalOffset = offsetInModelUnits;
                if (IsAssemblyInstallationReferenceActiveForRoute(coreRoute))
                {
                    UpdateAssemblyInstallationAnchorFromVerticalOffset();
                    PersistAssemblyInstallationReferenceToRailRoute(coreRoute, $"安装法向偏移已更新为 {value:F3} 米");
                }
                else
                {
                    ApplyRailRouteConfigurationChange(coreRoute, $"安装法向偏移已更新为 {value:F3} 米");
                }
                OnPropertyChanged(nameof(SelectedRailNormalOffsetInMeters));
            }
        }

        public string AssemblyTerminalObjectName
        {
            get => _assemblyTerminalObjectName;
            set
            {
                if (string.Equals(_assemblyTerminalObjectName, value, StringComparison.Ordinal))
                {
                    return;
                }

                _assemblyTerminalObjectName = value;
                OnPropertyChanged(nameof(AssemblyTerminalObjectName));
            }
        }

        public string AssemblyTerminalObjectInfo
        {
            get => _assemblyTerminalObjectInfo;
            set
            {
                if (string.Equals(_assemblyTerminalObjectInfo, value, StringComparison.Ordinal))
                {
                    return;
                }

                _assemblyTerminalObjectInfo = value;
                OnPropertyChanged(nameof(AssemblyTerminalObjectInfo));
            }
        }

        public double AssemblyReferenceRodLengthInMeters
        {
            get => _assemblyReferenceRodLengthInMeters;
            set
            {
                if (Math.Abs(_assemblyReferenceRodLengthInMeters - value) < 1e-9)
                {
                    return;
                }

                _assemblyReferenceRodLengthInMeters = value;
                OnPropertyChanged(nameof(AssemblyReferenceRodLengthInMeters));
            }
        }

        public double AssemblyReferenceRodDiameterInMeters
        {
            get => _assemblyReferenceRodDiameterInMeters;
            set
            {
                if (Math.Abs(_assemblyReferenceRodDiameterInMeters - value) < 1e-9)
                {
                    return;
                }

                _assemblyReferenceRodDiameterInMeters = value;
                OnPropertyChanged(nameof(AssemblyReferenceRodDiameterInMeters));
            }
        }

        public double AssemblyAnchorVerticalOffsetInMeters
        {
            get => _assemblyAnchorVerticalOffsetInMeters;
            set
            {
                if (Math.Abs(_assemblyAnchorVerticalOffsetInMeters - value) < 1e-9)
                {
                    return;
                }

                _assemblyAnchorVerticalOffsetInMeters = value;
                OnPropertyChanged(nameof(AssemblyAnchorVerticalOffsetInMeters));

                if (HasAssemblyTerminalObject)
                {
                    var coreRoute = GetSelectedCoreRoute();
                    if (_hasAssemblyInstallationReference)
                    {
                        UpdateAssemblyInstallationAnchorFromVerticalOffset();
                        if (IsAssemblyInstallationReferenceActiveForRoute(coreRoute))
                        {
                            PersistAssemblyInstallationReferenceToRailRoute(coreRoute, $"安装法向偏移已更新为 {value:F3} 米");
                        }
                    }
                    RefreshAssemblyTerminalObjectInfo();
                    if (coreRoute != null &&
                        coreRoute.PathType == PathType.Rail &&
                        AssemblyReferencePathManager.Instance.HasReferenceLine)
                    {
                        RefreshSelectedRailReferenceLineVisuals();
                    }
                    else
                    {
                        RefreshAssemblyReferenceRodIfNeeded();
                    }
                }
            }
        }

        public double AssemblySphereCenterX
        {
            get => _assemblySphereCenterX;
            set
            {
                if (Math.Abs(_assemblySphereCenterX - value) < 1e-9)
                {
                    return;
                }

                _assemblySphereCenterX = value;
                OnPropertyChanged(nameof(AssemblySphereCenterX));

                if (HasAssemblyTerminalObject)
                {
                    RefreshAssemblyTerminalObjectInfo();
                    RefreshAssemblyReferenceRodIfNeeded();
                }
            }
        }

        public double AssemblySphereCenterY
        {
            get => _assemblySphereCenterY;
            set
            {
                if (Math.Abs(_assemblySphereCenterY - value) < 1e-9)
                {
                    return;
                }

                _assemblySphereCenterY = value;
                OnPropertyChanged(nameof(AssemblySphereCenterY));

                if (HasAssemblyTerminalObject)
                {
                    RefreshAssemblyTerminalObjectInfo();
                    RefreshAssemblyReferenceRodIfNeeded();
                }
            }
        }

        public double AssemblySphereCenterZ
        {
            get => _assemblySphereCenterZ;
            set
            {
                if (Math.Abs(_assemblySphereCenterZ - value) < 1e-9)
                {
                    return;
                }

                _assemblySphereCenterZ = value;
                OnPropertyChanged(nameof(AssemblySphereCenterZ));

                if (HasAssemblyTerminalObject)
                {
                    RefreshAssemblyTerminalObjectInfo();
                    RefreshAssemblyReferenceRodIfNeeded();
                }
            }
        }

        public bool HasAssemblyTerminalObject
        {
            get => _hasAssemblyTerminalObject;
            set
            {
                if (_hasAssemblyTerminalObject == value)
                {
                    return;
                }

                _hasAssemblyTerminalObject = value;
                OnPropertyChanged(nameof(HasAssemblyTerminalObject));
            }
        }

        public string AssemblyStartPointText
        {
            get => _assemblyStartPointText;
            set
            {
                if (string.Equals(_assemblyStartPointText, value, StringComparison.Ordinal))
                {
                    return;
                }

                _assemblyStartPointText = value;
                OnPropertyChanged(nameof(AssemblyStartPointText));
            }
        }

        public RailMountMode AssemblyMountMode
        {
            get => _assemblyMountMode;
            set
            {
                if (_assemblyMountMode == value)
                {
                    return;
                }

                _assemblyMountMode = value;
                OnPropertyChanged(nameof(AssemblyMountMode));

                if (HasAssemblyTerminalObject)
                {
                    RefreshAssemblyTerminalObjectInfo();
                    RefreshAssemblyReferenceRodIfNeeded();
                }
            }
        }

        public bool IsSelectingAssemblyStartPoint
        {
            get => _isSelectingAssemblyStartPoint;
            set
            {
                if (_isSelectingAssemblyStartPoint == value)
                {
                    return;
                }

                _isSelectingAssemblyStartPoint = value;
                OnPropertyChanged(nameof(IsSelectingAssemblyStartPoint));
            }
        }
        /// <summary>
        /// 更新路径可视化显示:清理其他路径,只显示当前选中的路径
        /// </summary>
        private async void UpdatePathVisualization()
        {
            await SafeExecuteAsync(() =>
            {
                try
                {
                    if (PathPointRenderPlugin.Instance == null)
                    {
                        LogManager.Warning("PathPointRenderPlugin实例为空,无法更新路径可视化");
                        return;
                    }

                    // 0. 先同步物体参数到渲染插件
                    SyncObjectParametersToRenderPlugin();

                    // 检查是否在编辑状态
                    bool isInEditMode = _pathPlanningManager?.IsInEditableState ?? false;

                    // 1. 清理现有的路径可视化,但保留网格可视化和正在编辑的路径
                    if (isInEditMode)
                    {
                        // 在编辑状态,不清空路径,避免清空正在编辑的路径
                        LogManager.Debug("[路径可视化] 在编辑状态,跳过清空路径可视化");
                    }
                    else
                    {
                        // 不在编辑状态,清空所有路径可视化,但保留网格可视化
                        PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                    }

                    // 2. 如果有选中的路径,则显示该路径
                    if (_selectedPathRoute != null && _selectedPathRoute.Points.Count > 0)
                    {
                        // 查找对应的Core路径对象
                        var coreRoute = _pathPlanningManager?.Routes?.FirstOrDefault(r => r.Id == _selectedPathRoute.Id)
                            ?? _pathPlanningManager?.Routes?.FirstOrDefault(r => r.Name == _selectedPathRoute.Name);
                        if (coreRoute != null)
                        {
                            // 使用PathPlanningManager的绘制方法来保持一致性
                            _pathPlanningManager.DrawRouteVisualization(coreRoute, isAutoPath: false);
                            LogManager.Info($"[路径可视化] 已显示选中路径: {_selectedPathRoute.Name},包含 {_selectedPathRoute.Points.Count} 个点");
                        }
                        else
                        {
                            LogManager.Warning($"[路径可视化] 未找到对应的Core路径: {_selectedPathRoute.Name}");
                        }
                    }

                    RefreshSelectedRailInstallationReferenceVisuals();

                    // 3. 恢复网格可视化(如果网格可视化已启用且当前路径有关联的GridMap)
                    if (_pathPlanningManager?.IsAnyGridVisualizationEnabled == true)
                    {
                        // 检查当前路径是否有关联的GridMap
                        var currentRoute = _pathPlanningManager.CurrentRoute;
                        if (currentRoute?.AssociatedGridMap != null)
                        {
                            // 通过PathPlanningManager的RefreshGridVisualization方法恢复网格
                            // 这会使用当前路径的AssociatedGridMap来重新渲染网格
                            var refreshMethod = typeof(PathPlanningManager).GetMethod("RefreshGridVisualization",
                                System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                            if (refreshMethod != null)
                            {
                                refreshMethod.Invoke(_pathPlanningManager, null);
                            }
                            else
                            {
                                LogManager.Warning("[路径可视化] 无法找到RefreshGridVisualization方法");
                            }
                        }
                        else
                        {
                            LogManager.Debug("[路径可视化] 当前路径没有关联的GridMap,跳过网格恢复");
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Error($"[路径可视化] 更新路径可视化失败: {ex.Message}", ex);
                }
            }, "更新路径可视化");
        }

        public bool IsPathEditMode
        {
            get => _isPathEditMode;
            set => SetProperty(ref _isPathEditMode, value);
        }

        #region 自动路径规划属性

        public string AutoPathStartPoint
        {
            get => _autoPathStartPoint;
            set => SetProperty(ref _autoPathStartPoint, value);
        }

        public string AutoPathEndPoint
        {
            get => _autoPathEndPoint;
            set => SetProperty(ref _autoPathEndPoint, value);
        }

        #region 多层吊装属性

        public bool IsMultiLevelHoistingMode
        {
            get => _isMultiLevelHoistingMode;
            set => SetProperty(ref _isMultiLevelHoistingMode, value);
        }

        public ObservableCollection<HoistingLevelItem> MultiLevelItems
        {
            get => _multiLevelItems;
            set => SetProperty(ref _multiLevelItems, value);
        }

        public ObservableCollection<HoistingLayerEditItem> HoistingLayerEditItems
        {
            get => _hoistingLayerEditItems;
            set => SetProperty(ref _hoistingLayerEditItems, value);
        }

        public string HoistingLayerEditHintText
        {
            get => _hoistingLayerEditHintText;
            set => SetProperty(ref _hoistingLayerEditHintText, value);
        }

        public string MultiLevelStartPointText
        {
            get => _multiLevelStartPointText;
            set => SetProperty(ref _multiLevelStartPointText, value);
        }

        public string MultiLevelEndPointText
        {
            get => _multiLevelEndPointText;
            set => SetProperty(ref _multiLevelEndPointText, value);
        }

        public string MultiLevelStatsText
        {
            get => _multiLevelStatsText;
            set => SetProperty(ref _multiLevelStatsText, value);
        }

        public bool CanCreateMultiLevelPath => _hasMultiLevelStartPoint && _hasMultiLevelEndPoint && _multiLevelItems.Count > 0;
        public bool CanApplyHoistingLayerHeights => IsHoistingRouteSelected &&
                                                    SelectedPathRoute != null &&
                                                    HoistingLayerEditItems.Count > 0;

        #endregion

        public double ObjectLength
        {
            get => _objectLength;
            set
            {
                if (SetProperty(ref _objectLength, value))
                {
                    SyncObjectParametersToRenderPlugin();
                    OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                }
            }
        }

        public double ObjectWidth
        {
            get => _objectWidth;
            set
            {
                if (SetProperty(ref _objectWidth, value))
                {
                    SyncObjectParametersToRenderPlugin();
                    OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                }
            }
        }

        public double ObjectHeight
        {
            get => _objectHeight;
            set
            {
                if (SetProperty(ref _objectHeight, value))
                {
                    SyncObjectParametersToRenderPlugin();
                    OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                }
            }
        }

        public double SafetyMargin
        {
            get => _safetyMargin;
            set
            {
                // 限制精度到2位小数
                var roundedValue = Math.Round(value, 2);
                if (SetProperty(ref _safetyMargin, roundedValue))
                {
                    SyncObjectParametersToRenderPlugin();
                    OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                }
            }
        }

        public bool IsGridSizeManuallyEnabled
        {
            get => _isGridSizeManuallyEnabled;
            set
            {
                if (SetProperty(ref _isGridSizeManuallyEnabled, value))
                {
                    OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                }
            }
        }

        public double GridSize
        {
            get => _gridSize;
            set
            {
                // 限制精度到1位小数
                var roundedValue = Math.Round(value, 1);
                if (SetProperty(ref _gridSize, roundedValue))
                {
                    OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                }
            }
        }

        private void ApplyStoredAutoPlanningParameters(PathRoute route)
        {
            if (route == null)
            {
                return;
            }

            bool hasAnyStoredValue =
                route.MaxObjectLength > 0 ||
                route.MaxObjectWidth > 0 ||
                route.MaxObjectHeight > 0 ||
                route.SafetyMargin > 0 ||
                route.GridSize > 0;

            if (!hasAnyStoredValue)
            {
                LogManager.Debug($"[自动路径参数同步] 路径 {route.Name} 没有保存自动规划参数,保持当前输入值");
                return;
            }

            var appliedFields = new List<string>();

            if (route.MaxObjectLength > 0 && Math.Abs(ObjectLength - route.MaxObjectLength) > 1e-6)
            {
                ObjectLength = route.MaxObjectLength;
                appliedFields.Add($"长度={route.MaxObjectLength:F3}m");
            }

            if (route.MaxObjectWidth > 0 && Math.Abs(ObjectWidth - route.MaxObjectWidth) > 1e-6)
            {
                ObjectWidth = route.MaxObjectWidth;
                appliedFields.Add($"宽度={route.MaxObjectWidth:F3}m");
            }

            if (route.MaxObjectHeight > 0 && Math.Abs(ObjectHeight - route.MaxObjectHeight) > 1e-6)
            {
                ObjectHeight = route.MaxObjectHeight;
                appliedFields.Add($"高度={route.MaxObjectHeight:F3}m");
            }

            if (route.SafetyMargin > 0 && Math.Abs(SafetyMargin - route.SafetyMargin) > 1e-6)
            {
                SafetyMargin = route.SafetyMargin;
                appliedFields.Add($"安全间隙={route.SafetyMargin:F3}m");
            }

            if (route.GridSize > 0)
            {
                if (!IsGridSizeManuallyEnabled)
                {
                    IsGridSizeManuallyEnabled = true;
                    appliedFields.Add("启用手动网格");
                }

                if (Math.Abs(GridSize - route.GridSize) > 1e-6)
                {
                    GridSize = route.GridSize;
                    appliedFields.Add($"网格={route.GridSize:F3}m");
                }
            }

            if (appliedFields.Count > 0)
            {
                LogManager.Info($"[自动路径参数同步] 已从路径 {route.Name} 同步: {string.Join(", ", appliedFields)}");
            }
            else
            {
                LogManager.Debug($"[自动路径参数同步] 路径 {route.Name} 的自动规划参数与当前输入一致");
            }
        }

        #region 可视化参数属性

        /// <summary>
        /// 是否显示可通行网格点
        /// </summary>
        public bool ShowWalkableGrid
        {
            get => _showWalkableGrid;
            set
            {
                if (SetProperty(ref _showWalkableGrid, value))
                {
                    OnGridVisualizationChanged();
                }
            }
        }

        /// <summary>
        /// 是否显示障碍物网格点
        /// </summary>
        public bool ShowObstacleGrid
        {
            get => _showObstacleGrid;
            set
            {
                if (SetProperty(ref _showObstacleGrid, value))
                {
                    OnGridVisualizationChanged();
                }
            }
        }

        /// <summary>
        /// 是否显示未知区域网格点
        /// </summary>
        public bool ShowUnknownGrid
        {
            get => _showUnknownGrid;
            set
            {
                if (SetProperty(ref _showUnknownGrid, value))
                {
                    OnGridVisualizationChanged();
                }
            }
        }

        /// <summary>
        /// 是否显示门网格点
        /// </summary>
        public bool ShowDoorGrid
        {
            get => _showDoorGrid;
            set
            {
                if (SetProperty(ref _showDoorGrid, value))
                {
                    OnGridVisualizationChanged();
                }
            }
        }

        /// <summary>
        /// 网格点类型
        /// </summary>
        public GridPointType GridPointType
        {
            get => _gridPointType;
            set
            {
                if (SetProperty(ref _gridPointType, value))
                {
                    OnPropertyChanged(nameof(IsRectanglePointType));
                    OnPropertyChanged(nameof(IsCirclePointType));
                    OnGridPointTypeChanged();
                }
            }
        }

        /// <summary>
        /// 是否使用立方体点类型
        /// </summary>
        public bool IsRectanglePointType
        {
            get => _gridPointType == GridPointType.Rectangle;
            set
            {
                if (value)
                {
                    GridPointType = GridPointType.Rectangle;
                }
            }
        }

        /// <summary>
        /// 是否使用圆形点类型
        /// </summary>
        public bool IsCirclePointType
        {
            get => _gridPointType == GridPointType.Circle;
            set
            {
                if (value)
                {
                    GridPointType = GridPointType.Circle;
                }
            }
        }

        /// <summary>
        /// 是否显示控制点连线(独立开关)
        /// </summary>
        public bool ShowControlVisualization
        {
            get => _showControlVisualization;
            set
            {
                if (SetProperty(ref _showControlVisualization, value))
                {
                    OnControlVisualizationChanged();
                }
            }
        }

        /// <summary>
        /// 是否显示路径线/地面连线(独立开关)
        /// </summary>
        public bool ShowPathLines
        {
            get => _showPathLines;
            set
            {
                // 吊装和空轨路径不能使用路径线
                if (value && !CanUsePathLines)
                {
                    LogManager.Warning("[路径可视化] 吊装和空轨路径不能使用路径线");
                    return;
                }
                if (SetProperty(ref _showPathLines, value))
                {
                    OnPathVisualizationModeChanged();
                }
            }
        }

        /// <summary>
        /// 是否显示通行空间(独立开关)
        /// </summary>
        public bool ShowObjectSpace
        {
            get => _showObjectSpace;
            set
            {
                if (SetProperty(ref _showObjectSpace, value))
                {
                    OnPathVisualizationModeChanged();
                }
            }
        }

        /// <summary>
        /// 当前路径是否可以使用路径线
        /// 地面路径可以使用路径线,吊装和空轨路径不能使用路径线
        /// </summary>
        public bool CanUsePathLines
        {
            get
            {
                if (SelectedPathRoute == null) return true;
                // 只有地面路径可以使用路径线
                return SelectedPathRoute.PathType == PathType.Ground;
            }
        }

        /// <summary>
        /// 是否使用标准连线模式(向后兼容,根据独立开关计算)
        /// </summary>
        public bool IsStandardLineMode
        {
            get => _showPathLines && !_showObjectSpace;
            set
            {
                if (value)
                {
                    ShowPathLines = true;
                    ShowObjectSpace = false;
                }
            }
        }

        /// <summary>
        /// 是否使用物体通行空间模式(向后兼容,等同于 ShowObjectSpace)
        /// </summary>
        public bool IsObjectSpaceMode
        {
            get => _showObjectSpace;
            set => ShowObjectSpace = value;
        }

        /// <summary>
        /// 是否使用带状连线模式(向后兼容,等同于 ShowPathLines)
        /// </summary>
        public bool IsRibbonLineMode
        {
            get => _showPathLines;
            set => ShowPathLines = value;
        }

        #endregion

        /// <summary>
        /// 路径策略选项集合
        /// </summary>
        public ObservableCollection<PathStrategyOption> PathStrategyOptions
        {
            get => _pathStrategyOptions;
        }

        /// <summary>
        /// 当前选择的路径策略
        /// </summary>
        public PathStrategyOption SelectedPathStrategy
        {
            get => _selectedPathStrategy;
            set
            {
                if (SetProperty(ref _selectedPathStrategy, value))
                {
                    OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                }
            }
        }

        public bool IsSelectingStartPoint
        {
            get => _isSelectingStartPoint;
            set => SetProperty(ref _isSelectingStartPoint, value);
        }

        public bool IsSelectingEndPoint
        {
            get => _isSelectingEndPoint;
            set => SetProperty(ref _isSelectingEndPoint, value);
        }

        #endregion


        public PathPlanningManager PathPlanningManager
        {
            get => _pathPlanningManager;
            set
            {
                if (_pathPlanningManager != value)
                {
                    // 取消旧的事件订阅
                    if (_pathPlanningManager != null)
                    {
                        UnsubscribeFromPathPlanningManager();
                    }

                    _pathPlanningManager = value;

                    // 订阅新的事件
                    if (_pathPlanningManager != null)
                    {
                        SubscribeToPathPlanningManager();
                    }
                }
            }
        }

        #endregion

        #region 命令

        public ICommand NewPathCommand { get; private set; }
        public ICommand NewRailPathCommand { get; private set; }
        public ICommand NewFreePathCommand { get; private set; }
        public ICommand NewHoistingPathCommand { get; private set; }
        public ICommand NewMultiLevelHoistingPathCommand { get; private set; }
        public ICommand DuplicatePathCommand { get; private set; }
        public ICommand DeletePathCommand { get; private set; }
        public ICommand RenamePathCommand { get; private set; }
        public ICommand StartEditCommand { get; private set; }
        public ICommand EndEditCommand { get; private set; }
        public ICommand ClearPathCommand { get; private set; }
        public ICommand DeletePointCommand { get; private set; }
        public ICommand ModifyPointCommand { get; private set; }
        public ICommand CancelModifyPointCommand { get; private set; }
        public ICommand SelectStartPointCommand { get; private set; }
        public ICommand SelectEndPointCommand { get; private set; }
        public ICommand EditPointCoordinatesCommand { get; private set; }
        public ICommand AutoPlanPathCommand { get; private set; }
        public ICommand ClearAutoPathCommand { get; private set; }
        public ICommand ImportPathCommand { get; private set; }
        public ICommand ExportPathCommand { get; private set; }
        public ICommand SaveAsPathCommand { get; private set; }
        public ICommand CaptureAssemblyTerminalObjectForCreateCommand { get; private set; }
        public ICommand ReCaptureAssemblyTerminalObjectForEditCommand { get; private set; }
        public ICommand SelectAssemblyStartPointForCreateCommand { get; private set; }
        public ICommand RepositionRailStartPointCommand { get; private set; }
        public ICommand PickAssemblyInstallationCommand { get; private set; }
        public ICommand ClearAssemblyReferenceRodCommand { get; private set; }
        public ICommand CancelRailAssemblyWorkflowCommand { get; private set; }
        public ICommand AnalyzeAssemblyEndFaceCommand { get; private set; }
        public ICommand DecreaseSelectedRailNormalOffsetCommand { get; private set; }
        public ICommand IncreaseSelectedRailNormalOffsetCommand { get; private set; }

        // 多层吊装命令
        public ICommand SelectMultiLevelStartPointCommand { get; private set; }
        public ICommand SelectMultiLevelEndPointCommand { get; private set; }
        public ICommand AddMultiLevelCommand { get; private set; }
        public ICommand DeleteMultiLevelCommand { get; private set; }
        public ICommand PickMultiLevelTargetCommand { get; private set; }
        public ICommand CreateMultiLevelPathCommand { get; private set; }
        public ICommand CancelMultiLevelHoistingCommand { get; private set; }
        public ICommand ApplyHoistingLayerHeightsCommand { get; private set; }

        #endregion

        #region Can Execute属性

        public bool CanExecuteAutoPlanPath => _hasStartPoint && _hasEndPoint &&
                                            ObjectLength > 0 && ObjectWidth > 0 && ObjectHeight > 0 &&
                                            SafetyMargin >= 0;

        public bool CanExecuteNewPath => !IsSelectingStartPoint && !IsSelectingEndPoint;

        public bool CanExecuteNewRailPath => !IsSelectingStartPoint && !IsSelectingEndPoint;

        public bool CanExecuteNewFreePath => !IsSelectingStartPoint && !IsSelectingEndPoint;

        public bool CanExecuteStartEdit => SelectedPathRoute != null &&
                                         (_pathPlanningManager?.PathEditState == PathEditState.Viewing);

        public bool CanExecuteEndEdit => (_pathPlanningManager?.PathEditState == PathEditState.Creating ||
                                        _pathPlanningManager?.PathEditState == PathEditState.Editing ||
                                        _pathPlanningManager?.PathEditState == PathEditState.AddingPoints ||
                                        _pathPlanningManager?.PathEditState == PathEditState.EditingPoint) ||
                                        CanCancelRailAssemblyWorkflow;

        public bool CanExecuteClearPath => SelectedPathRoute != null && SelectedPathRoute.Points.Count > 0;

        public bool CanExecuteExportPath => _pathPlanningManager?.Routes?.Count > 0 || SelectedPathRoute != null;

        public bool CanExecuteSaveAsPath => PathRoutes?.Any(r => r.IsSelected) == true
            || (SelectedPathRoute != null && SelectedPathRoute.Points.Count > 0);
        public bool CanSelectAssemblyStartPointForCreate => HasAssemblyTerminalObject &&
                                                            _pathPlanningManager != null &&
                                                            AssemblyReferencePathManager.Instance.HasReferenceLine &&
                                                            !IsSelectingAssemblyStartPoint &&
                                                            !_isSelectingAssemblyEndFacePoints &&
                                                            !_isSelectingAssemblyInstallationPoint;
        public bool CanRepositionRailStartPoint => HasAssemblyTerminalObject &&
                                                   IsRailRouteSelected &&
                                                   SelectedPathRoute != null &&
                                                   _pathPlanningManager != null &&
                                                   AssemblyReferencePathManager.Instance.HasReferenceLine &&
                                                   !IsSelectingAssemblyStartPoint &&
                                                   !_isSelectingAssemblyEndFacePoints &&
                                                   !_isSelectingAssemblyInstallationPoint;
        public bool CanPickAssemblyInstallation => HasAssemblyTerminalObject &&
                                                    _pathPlanningManager != null &&
                                                    !IsSelectingAssemblyStartPoint &&
                                                    !IsSelectingAssemblyEndFacePoints &&
                                                    !_isSelectingAssemblyInstallationPoint;
        public bool CanAnalyzeAssemblyEndFace => HasAssemblyTerminalObject &&
                                                         _pathPlanningManager != null &&
                                                         !IsSelectingAssemblyStartPoint &&
                                                         !IsSelectingAssemblyEndFacePoints &&
                                                         !_isSelectingAssemblyInstallationPoint;



        public bool IsSelectingAssemblyEndFacePoints => _isSelectingAssemblyEndFacePoints;
        public bool CanCancelRailAssemblyWorkflow => _railAssemblyWorkflowMode != RailAssemblyWorkflowMode.None ||
                                                     HasAssemblyTerminalObject ||
                                                     _isSelectingAssemblyStartPoint ||
                                                     _isSelectingAssemblyEndFacePoints ||
                                                     _isSelectingAssemblyInstallationPoint ||
                                                     _hasAssemblyEndFaceAnalysis ||
                                                     _hasAssemblyInstallationReference;

        private bool IsRailCreateWorkflowActive => _railAssemblyWorkflowMode == RailAssemblyWorkflowMode.CreateNewRailPath;
        private bool IsRailEditingWorkflowActive => _railAssemblyWorkflowMode == RailAssemblyWorkflowMode.EditSelectedRail;

        private static bool IsRailAssemblyEditMode(RailAssemblyWorkflowMode workflowMode)
        {
            return workflowMode == RailAssemblyWorkflowMode.EditSelectedRail;
        }

        private static string GetRailAssemblyWorkflowLabel(RailAssemblyWorkflowMode workflowMode)
        {
            return IsRailAssemblyEditMode(workflowMode)
                ? "编辑现有Rail路径"
                : "新建Rail路径";
        }

        private bool ShouldShowAssemblyReferenceLineVisuals()
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                return false;
            }

            return IsRailEditingWorkflowActive || _hasAssemblyInstallationReference;
        }

        public bool CanExecuteModifyPoint => SelectedPathPoint != null &&
                                            _pathPlanningManager?.PathEditState != PathEditState.EditingPoint;
        public bool CanExecuteCancelModifyPoint => _pathPlanningManager?.PathEditState == PathEditState.EditingPoint;

        #endregion

        #region 构造函数

        /// <summary>
        /// 构造函数,需要传入主ViewModel以支持统一状态栏
        /// </summary>
        /// <param name="mainViewModel">主ViewModel,用于统一状态栏</param>
        public PathEditingViewModel(LogisticsControlViewModel mainViewModel) : base()
        {
            try
            {
                // 设置主ViewModel引用到基类
                SetMainViewModel(mainViewModel);

                _uiStateManager = UIStateManager.Instance;
                _pathDataManager = new PathDataManager();
                // 不在构造函数中创建PathPlanningManager,由外部设置
                _pathPlanningManager = null;

                if (_uiStateManager == null)
                {
                    throw new InvalidOperationException("UIStateManager初始化失败");
                }

                // PathPlanningManager将在外部设置,这里不需要检查

                // 初始化集合
                PathRoutes = new ObservableCollection<PathRouteViewModel>();

                // 初始化路径策略选项
                InitializePathStrategyOptions();
                InitializeRailConfigOptions();

                // 从配置加载参数
                LoadParametersFromConfig();

                // 订阅配置变更事件
                SubscribeToConfigChanges();

                // 初始化命令
                InitializeCommands();

                // 初始化物体参数同步(在PathPointRenderPlugin实例不为空时才同步)
                // 如果PathPointRenderPlugin尚未初始化,将在属性变更时自动同步
                SyncObjectParametersToRenderPlugin();

                // 注意:不在这里订阅PathPlanningManager事件,
                // 因为PathPlanningManager还没有设置,事件订阅在PathPlanningManager属性setter中处理

                LogManager.Info("PathEditingViewModel构造函数执行完成 - 支持统一状态栏");
            }
            catch (Exception ex)
            {
                LogManager.Error($"PathEditingViewModel构造函数异常: {ex.Message}", ex);
                UpdateMainStatus("初始化失败,请检查日志");
                throw;
            }
        }

        #endregion

        #region 初始化方法

        /// <summary>
        /// 初始化路径策略选项
        /// </summary>
        private void InitializePathStrategyOptions()
        {
            _pathStrategyOptions = new ObservableCollection<PathStrategyOption>
            {
                new PathStrategyOption
                {
                    Value = PathStrategy.Shortest,
                    DisplayName = "最短路径",
                    Description = "标准A*算法,选择路径总长度最短的路径"
                },
                new PathStrategyOption
                {
                    Value = PathStrategy.Straightest,
                    DisplayName = "直线优先",
                    Description = "优先选择主方向直线路径,减少转弯次数"
                },
                new PathStrategyOption
                {
                    Value = PathStrategy.SafestCenter,
                    DisplayName = "安全优先",
                    Description = "基于障碍物距离选择安全路径,适合大型物体居中行驶"
                }
            };

            // 默认选择最短路径策略(向后兼容)
            _selectedPathStrategy = _pathStrategyOptions.FirstOrDefault(x => x.Value == PathStrategy.Shortest);
        }

        /// <summary>
        /// 初始化 Rail 构型选项
        /// </summary>
        private void InitializeRailConfigOptions()
        {
            _railMountModeOptions = new ObservableCollection<RailConfigOption<RailMountMode>>
            {
                new RailConfigOption<RailMountMode>
                {
                    Value = RailMountMode.UnderRail,
                    DisplayName = "轨下安装",
                    Description = "安装头位于双轨下方,构件从轨道平面下侧连接"
                },
                new RailConfigOption<RailMountMode>
                {
                    Value = RailMountMode.OverRail,
                    DisplayName = "轨上安装",
                    Description = "安装头位于双轨上方,构件从轨道平面上侧连接"
                }
            };

        }

        private PathRoute GetSelectedCoreRoute()
        {
            if (_pathPlanningManager == null || SelectedPathRoute == null)
            {
                return null;
            }

            return _pathPlanningManager.Routes?.FirstOrDefault(route => route.Id == SelectedPathRoute.Id)
                ?? _pathPlanningManager.Routes?.FirstOrDefault(route => route.Name == SelectedPathRoute.Name);
        }

        private void ApplyRailRouteConfigurationChange(PathRoute coreRoute, string logMessage)
        {
            coreRoute.LastModified = DateTime.Now;

            SyncObjectParametersToRenderPlugin();
            _pathPlanningManager.DrawRouteVisualization(coreRoute, isAutoPath: false);
            _pathPlanningManager.SavePathToDatabase(coreRoute);
            _pathPlanningManager.RaiseVisualizationStateChanged();

            LogManager.Info($"[Rail构型] {coreRoute.Name}: {logMessage}");
        }

        private void SetRailAssemblyWorkflowMode(RailAssemblyWorkflowMode mode)
        {
            if (_railAssemblyWorkflowMode == mode)
            {
                return;
            }

            _railAssemblyWorkflowMode = mode;
            NotifyRailAssemblyCommandStateChanged();
        }

        private void NotifyRailAssemblyCommandStateChanged()
        {
            OnPropertyChanged(nameof(CanAnalyzeAssemblyEndFace));
            OnPropertyChanged(nameof(CanSelectAssemblyStartPointForCreate));
            OnPropertyChanged(nameof(CanRepositionRailStartPoint));
            OnPropertyChanged(nameof(CanPickAssemblyInstallation));
            OnPropertyChanged(nameof(CanCancelRailAssemblyWorkflow));
            OnPropertyChanged(nameof(CanExecuteEndEdit));
        }

        private bool HasSelectedRailInstallationReference()
        {
            var coreRoute = GetSelectedCoreRoute();
            return coreRoute != null &&
                   coreRoute.PathType == PathType.Rail &&
                   coreRoute.RailPreferredNormal != null;
        }

        private int GetRoutePointIndexByType(PathRoute route, PathPointType pointType, int fallbackIndex)
        {
            if (route?.Points == null || route.Points.Count == 0)
            {
                return -1;
            }

            for (int i = 0; i < route.Points.Count; i++)
            {
                if (route.Points[i].Type == pointType)
                {
                    return i;
                }
            }

            return fallbackIndex >= 0 && fallbackIndex < route.Points.Count
                ? fallbackIndex
                : -1;
        }

        private bool IsAssemblyInstallationReferenceActiveForRoute(PathRoute route)
        {
            return route != null &&
                   route.PathType == PathType.Rail &&
                   _hasAssemblyInstallationReference &&
                   _assemblyInstallationAnchorPoint != null &&
                   !string.IsNullOrWhiteSpace(_assemblyInstallationReferenceRouteId) &&
                   string.Equals(_assemblyInstallationReferenceRouteId, route.Id, StringComparison.Ordinal);
        }

        private int GetRailRouteInstallationPointIndex(PathRoute route)
        {
            return GetRoutePointIndexByType(route, PathPointType.EndPoint, route?.Points?.Count - 1 ?? -1);
        }

        private int GetRailRouteStartPointIndex(PathRoute route)
        {
            return GetRoutePointIndexByType(route, PathPointType.StartPoint, 0);
        }

        private bool TryBuildRailRouteReferenceLine(PathRoute route, out AssemblyReferenceLine referenceLine)
        {
            referenceLine = null;
            if (route == null || route.PathType != PathType.Rail || route.Points == null || route.Points.Count < 2)
            {
                return false;
            }

            int startIndex = GetRailRouteStartPointIndex(route);
            int endIndex = GetRailRouteInstallationPointIndex(route);
            if (startIndex < 0 || endIndex < 0 || startIndex == endIndex)
            {
                return false;
            }

            Point3D startPoint = route.Points[startIndex].Position;
            Point3D endPoint = route.Points[endIndex].Position;
            Vector3D direction = new Vector3D(
                startPoint.X - endPoint.X,
                startPoint.Y - endPoint.Y,
                startPoint.Z - endPoint.Z);
            double lengthSquared = direction.X * direction.X + direction.Y * direction.Y + direction.Z * direction.Z;
            if (lengthSquared < 1e-9)
            {
                return false;
            }

            referenceLine = new AssemblyReferenceLine(startPoint, endPoint, direction.Normalize());
            return true;
        }

        private void RefreshSelectedRailReferenceLineVisuals(string statusMessage = null)
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                ClearAssemblyReferenceLineVisuals();
                return;
            }

            AssemblyReferenceLine referenceLine;

            if (IsRailEditingWorkflowActive)
            {
                // 编辑状态:使用默认杆长度构建参考线,方便选择更远的起点
                try
                {
                    referenceLine = BuildAssemblyReferenceLine();
                }
                catch
                {
                    ClearAssemblyReferenceLineVisuals();
                    return;
                }
            }
            else
            {
                // 非编辑状态:使用路径实际长度
                var coreRoute = GetSelectedCoreRoute();
                if (!TryBuildRailRouteReferenceLine(coreRoute, out referenceLine))
                {
                    ClearAssemblyReferenceLineVisuals();
                    return;
                }
            }

            AssemblyReferencePathManager.Instance.CreateOrUpdateReferenceRod(
                referenceLine.StartPoint,
                referenceLine.EndPoint,
                AssemblyReferenceRodDiameterInMeters);
            AssemblyStartPointText = $"({referenceLine.StartPoint.X:F2}, {referenceLine.StartPoint.Y:F2}, {referenceLine.StartPoint.Z:F2})";
            RefreshAssemblyTerminalObjectInfo(referenceLine.StartPoint, referenceLine.EndPoint);
            RenderAssemblyReferenceLine(referenceLine);
            NotifyRailAssemblyCommandStateChanged();

            if (!string.IsNullOrWhiteSpace(statusMessage))
            {
                UpdateMainStatus(statusMessage);
            }
        }

        private void PersistAssemblyInstallationReferenceToRailRoute(PathRoute route, string logMessage)
        {
            if (route == null)
            {
                throw new ArgumentNullException(nameof(route));
            }

            if (route.PathType != PathType.Rail)
            {
                throw new InvalidOperationException("只有 Rail 路径支持安装点参数更新。");
            }

            if (!_hasAssemblyInstallationReference || _assemblyInstallationAnchorPoint == null)
            {
                throw new InvalidOperationException("当前没有可应用的安装点参考。");
            }

            int installationPointIndex = GetRailRouteInstallationPointIndex(route);
            if (installationPointIndex < 0)
            {
                throw new InvalidOperationException("当前 Rail 路径没有可更新的终点。");
            }

            // 获取当前起点索引
            int startPointIndex = GetRailRouteStartPointIndex(route);
            if (startPointIndex < 0)
            {
                throw new InvalidOperationException("当前 Rail 路径没有可更新的起点。");
            }

            // 计算原路径长度(起点到终点的距离)
            Point3D currentStartPoint = route.Points[startPointIndex].Position;
            Point3D currentEndPoint = route.Points[installationPointIndex].Position;
            double pathLength = GeometryHelper.CalculatePointDistance(currentStartPoint, currentEndPoint);

            // 更新终点(安装点)
            if (!_pathPlanningManager.UpdatePathPointWithConstraints(route, installationPointIndex, _assemblyInstallationAnchorPoint))
            {
                throw new InvalidOperationException("更新 Rail 路径安装点失败。");
            }

            // 根据新终点和原路径长度重新计算起点位置
            Point3D newStartPoint = CalculateRailStartPointFromEndPoint(_assemblyInstallationAnchorPoint, pathLength);
            if (!_pathPlanningManager.UpdatePathPointWithConstraints(route, startPointIndex, newStartPoint))
            {
                throw new InvalidOperationException("更新 Rail 路径起点失败。");
            }

            route.RailPreferredNormal = CreatePersistedAssemblyPreferredNormal();
            route.RailNormalOffset = UnitsConverter.ConvertFromMeters(AssemblyAnchorVerticalOffsetInMeters);
            route.LastModified = DateTime.Now;
            _assemblyInstallationReferenceRouteId = route.Id;

            _pathPlanningManager.SavePathToDatabase(route);
            _pathPlanningManager.DrawRouteVisualization(route, isAutoPath: false);
            _pathPlanningManager.RaiseVisualizationStateChanged();

            if (SelectedPathRoute != null && SelectedPathRoute.Id == route.Id)
            {
                SyncPathViewModelFromCoreRoute(SelectedPathRoute, route, preserveSelection: true);
                OnPropertyChanged(nameof(SelectedRailNormalOffsetInMeters));
                NotifyRailAssemblyCommandStateChanged();
                RefreshAssemblyTerminalObjectInfo();
                RefreshSelectedRailInstallationReferenceVisuals();
                RefreshSelectedRailReferenceLineVisuals();
            }

            LogManager.Info($"[Rail构型] {route.Name}: {logMessage},起点已同步更新为 ({newStartPoint.X:F3}, {newStartPoint.Y:F3}, {newStartPoint.Z:F3})");
        }

        private void RefreshSelectedRailInstallationReferenceVisuals()
        {
            var coreRoute = GetSelectedCoreRoute();
            if (!IsAssemblyInstallationReferenceActiveForRoute(coreRoute))
            {
                ClearAssemblyInstallationReferenceVisuals();
                return;
            }

            RenderAssemblyInstallationPickPoints(_assemblyInstallationSeedPoints);
            RenderAssemblyInstallationAnchorPoint(_assemblyInstallationAnchorPoint);
            RenderAssemblyInstallationCenterLine(_assemblyInstallationPickPoint, GetCurrentAssemblyOpticalAxisDirection());
            RenderAssemblyInstallationPlane(_assemblyInstallationAnchorPoint, GetCurrentAssemblyOpticalAxisDirection(), _assemblyInstallationPlaneSpanDirection);
        }

        private void AdjustSelectedRailNormalOffset(double deltaInMeters)
        {
            var coreRoute = GetSelectedCoreRoute();
            if (coreRoute == null || coreRoute.PathType != PathType.Rail)
            {
                return;
            }

            double currentOffsetInMeters = UnitsConverter.ConvertToMeters(coreRoute.RailNormalOffset);
            double nextOffsetInMeters = Math.Round(currentOffsetInMeters + deltaInMeters, 3);
            SelectedRailNormalOffsetInMeters = nextOffsetInMeters;
        }

        /// <summary>
        /// 从配置文件加载参数
        /// </summary>
        private void LoadParametersFromConfig()
        {
            try
            {
                var config = ConfigManager.Instance.Current;

                // 从 PathEditing 配置加载所有参数(使用米单位接口)
                _gridSize = config.PathEditing.CellSizeMeters;
                _objectLength = config.PathEditing.ObjectLengthMeters;
                _objectWidth = config.PathEditing.ObjectWidthMeters;
                _objectHeight = config.PathEditing.ObjectHeightMeters;
                _safetyMargin = config.PathEditing.SafetyMarginMeters;

                LogManager.Info($"从配置加载参数 - 物体: {_objectLength:F1}x{_objectWidth:F1}x{_objectHeight:F1}米, 安全间隙: {_safetyMargin:F2}米, 网格: {_gridSize:F1}米");
            }
            catch (Exception ex)
            {
                LogManager.Error($"加载配置参数失败: {ex.Message}", ex);
                // 使用默认值,不抛出异常
            }
        }

        #region 配置变更处理

        /// <summary>
        /// 订阅配置变更事件
        /// </summary>
        private void SubscribeToConfigChanges()
        {
            try
            {
                // 订阅特定类别的配置变更事件
                ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged;
                LogManager.Info("PathEditingViewModel 已订阅配置变更事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 取消订阅配置变更事件
        /// </summary>
        private void UnsubscribeFromConfigChanges()
        {
            try
            {
                ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged;
                LogManager.Info("PathEditingViewModel 已取消订阅配置变更事件");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 配置变更事件处理
        /// </summary>
        private void OnCategoryConfigurationChanged(object sender, Tuple<ConfigCategory, ConfigurationChangedEventArgs> args)
        {
            try
            {
                var category = args.Item1;
                var eventArgs = args.Item2;

                // 只处理 PathEditing 相关的配置变更
                if (category == ConfigCategory.PathEditing || category == ConfigCategory.All)
                {
                    LogManager.Info($"收到 PathEditing 配置变更通知,正在更新参数...");

                    // 从配置重新加载参数
                    LoadParametersFromConfig();

                    // 触发属性变更通知,更新UI
                    OnPropertiesChanged(
                        nameof(ObjectLength),
                        nameof(ObjectWidth),
                        nameof(ObjectHeight),
                        nameof(SafetyMargin),
                        nameof(GridSize)
                    );

                    // 同步物体参数到渲染插件
                    SyncObjectParametersToRenderPlugin();

                    // 更新状态栏
                    string source = eventArgs.IsExternalChange ? "外部修改" : "内部更新";
                    UpdateMainStatus($"配置已更新 ({source}) - 物体参数: {ObjectLength:F1}x{ObjectWidth:F1}x{ObjectHeight:F1}米");

                    LogManager.Info($"PathEditing 配置参数已更新完成 - 来源: {source}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex);
            }
        }

        #endregion

        private void InitializeCommands()
        {
            NewPathCommand = new RelayCommand(async () => await ExecuteNewPathAsync(), () => CanExecuteNewPath);
            NewRailPathCommand = new RelayCommand(async () => await ExecuteNewRailPathAsync(), () => CanExecuteNewRailPath);
            NewFreePathCommand = new RelayCommand(async () => await ExecuteNewFreePathAsync(), () => CanExecuteNewFreePath);
            NewHoistingPathCommand = new RelayCommand(async () => await ExecuteNewHoistingPathAsync());
            NewMultiLevelHoistingPathCommand = new RelayCommand(async () => await ExecuteNewMultiLevelHoistingPathAsync());
            SelectMultiLevelStartPointCommand = new RelayCommand(async () => await ExecuteSelectMultiLevelStartPointAsync());
            SelectMultiLevelEndPointCommand = new RelayCommand(async () => await ExecuteSelectMultiLevelEndPointAsync());
            AddMultiLevelCommand = new RelayCommand(() => ExecuteAddMultiLevel());
            DeleteMultiLevelCommand = new RelayCommand<HoistingLevelItem>((item) => ExecuteDeleteMultiLevel(item));
            PickMultiLevelTargetCommand = new RelayCommand<HoistingLevelItem>((item) => ExecutePickMultiLevelTarget(item));
            CreateMultiLevelPathCommand = new RelayCommand(async () => await ExecuteCreateMultiLevelPathAsync(), () => CanCreateMultiLevelPath);
            CancelMultiLevelHoistingCommand = new RelayCommand(() => ExecuteCancelMultiLevelHoisting());
            DuplicatePathCommand = new RelayCommand(async () => await ExecuteDuplicatePathAsync());
            DeletePathCommand = new RelayCommand(async () => await ExecuteDeletePathAsync());
            RenamePathCommand = new RelayCommand(async () => await ExecuteRenamePathAsync());
            StartEditCommand = new RelayCommand(async () => await ExecuteAddPathPointAsync(), () => CanExecuteStartEdit);
            EndEditCommand = new RelayCommand(async () => await ExecuteEndEditAsync(), () => CanExecuteEndEdit);
            ClearPathCommand = new RelayCommand(async () => await ExecuteClearPathAsync(), () => CanExecuteClearPath);
            DeletePointCommand = new RelayCommand<PathPointViewModel>(async (point) => await ExecuteDeletePointAsync(point));
            ModifyPointCommand = new RelayCommand(async () => await ExecuteModifyPointAsync(), () => CanExecuteModifyPoint);
            CancelModifyPointCommand = new RelayCommand(async () => await ExecuteCancelModifyPointAsync(), () => CanExecuteCancelModifyPoint);
            SelectStartPointCommand = new RelayCommand(async () => await ExecuteSelectStartPointAsync());
            SelectEndPointCommand = new RelayCommand(async () => await ExecuteSelectEndPointAsync());
            EditPointCoordinatesCommand = new RelayCommand<PathPointViewModel>(ExecuteEditPointCoordinates);
            AutoPlanPathCommand = new RelayCommand(async () => await ExecuteAutoPlanPathAsync(), () => CanExecuteAutoPlanPath);
            ClearAutoPathCommand = new RelayCommand(async () => await ExecuteClearAutoPathAsync());
            ImportPathCommand = new RelayCommand(async () => await ExecuteImportPathAsync());
            ExportPathCommand = new RelayCommand(async () => await ExecuteExportPathAsync(), () => CanExecuteExportPath);
            SaveAsPathCommand = new RelayCommand(async () => await ExecuteSaveAsPathAsync(), () => CanExecuteSaveAsPath);
            CaptureAssemblyTerminalObjectForCreateCommand = new RelayCommand(async () => await ExecuteCaptureAssemblyTerminalObjectAsync(RailAssemblyWorkflowMode.CreateNewRailPath));
            ReCaptureAssemblyTerminalObjectForEditCommand = new RelayCommand(async () => await ExecuteCaptureAssemblyTerminalObjectAsync(RailAssemblyWorkflowMode.EditSelectedRail));
            SelectAssemblyStartPointForCreateCommand = new RelayCommand(async () => await ExecuteSelectAssemblyStartPointAsync(), () => CanSelectAssemblyStartPointForCreate);
            RepositionRailStartPointCommand = new RelayCommand(async () => await ExecuteRepositionRailStartPointAsync(), () => CanRepositionRailStartPoint);
            PickAssemblyInstallationCommand = new RelayCommand(() => BeginAssemblyInstallationPick(), () => CanPickAssemblyInstallation);
            ClearAssemblyReferenceRodCommand = new RelayCommand(() => ExecuteClearAssemblyReferenceRod());
            CancelRailAssemblyWorkflowCommand = new RelayCommand(() => ExecuteCancelRailAssemblyWorkflow(), () => CanCancelRailAssemblyWorkflow);
            AnalyzeAssemblyEndFaceCommand = new RelayCommand(() => BeginAssemblyEndFacePick(), () => CanAnalyzeAssemblyEndFace);
            DecreaseSelectedRailNormalOffsetCommand = new RelayCommand(() => AdjustSelectedRailNormalOffset(-RailNormalOffsetNudgeStepInMeters));
            IncreaseSelectedRailNormalOffsetCommand = new RelayCommand(() => AdjustSelectedRailNormalOffset(RailNormalOffsetNudgeStepInMeters));
            ApplyHoistingLayerHeightsCommand = new RelayCommand(async () => await ExecuteApplyHoistingLayerHeightsAsync(), () => CanApplyHoistingLayerHeights);
        }

        #endregion

        #region 命令实现 - 从LogisticsControlViewModelcopy.cs迁移

        #region 路径管理命令

        private async Task ExecuteCaptureAssemblyTerminalObjectAsync(RailAssemblyWorkflowMode mode)
        {
            await SafeExecuteAsync(() =>
            {
                ClearNonGridPathVisualizations("[直线装配] 捕获箱体");

                var document = NavisApplication.ActiveDocument;
                var selectedItem = document?.CurrentSelection?.SelectedItems?.FirstOrDefault();
                if (selectedItem == null)
                {
                    throw new InvalidOperationException("请先在 Navisworks 中选择终点处已安装的箱体");
                }

                if (!ModelItemAnalysisHelper.IsModelItemValid(selectedItem))
                {
                    throw new InvalidOperationException("当前选择对象无效,请重新选择终点箱体");
                }

                SetRailAssemblyWorkflowMode(mode);

                _assemblyTerminalObject = selectedItem;
                _assemblyStartPoint = Point3D.Origin;
                HasAssemblyTerminalObject = true;
                AssemblyStartPointText = "未选择";
                AssemblyTerminalObjectName = ModelItemAnalysisHelper.GetSafeDisplayName(selectedItem);
                bool isEditMode = IsRailAssemblyEditMode(mode);

                ResetAssemblyEndFaceAnalysisState();
                if (!isEditMode)
                {
                    ResetAssemblyInstallationReferenceState();
                }
                RefreshAssemblyTerminalObjectInfo();
                ClearAssemblyAnchorMarker();
                ClearAssemblyEndFaceAnalysisVisuals();
                if (!isEditMode)
                {
                    ClearAssemblyInstallationReferenceVisuals();
                }
                NotifyRailAssemblyCommandStateChanged();

                if (isEditMode)
                {
                    // 编辑态重选箱体后,只恢复可由当前 Rail 路径和终点箱体稳定重建的可视化。
                    // 安装参考面依赖安装拾取点、安装面 span 等会话态数据,这些数据当前未持久化到 PathRoute,
                    // 因此这里不尝试恢复安装参考面,避免后续误以为"少了一次刷新调用"是 bug。
                    RefreshSelectedPathVisualizationForAssemblyEdit();
                    RefreshAssemblyReferenceRodIfNeeded();
                }
                else
                {
                    // 新建路径时隐藏其他路径的辅助线
                    ClearAssemblyReferenceLineVisuals();
                }

                UpdateMainStatus($"已捕获终点箱体: {AssemblyTerminalObjectName}");
                LogManager.Info($"[直线装配] 已捕获终点箱体: {AssemblyTerminalObjectName}");
            }, "捕获终点箱体");
        }

        private void RefreshSelectedPathVisualizationForAssemblyEdit()
        {
            if (_selectedPathRoute == null || _selectedPathRoute.Points.Count == 0 || _pathPlanningManager == null)
            {
                return;
            }

            var coreRoute = _pathPlanningManager.Routes?.FirstOrDefault(route => route.Id == _selectedPathRoute.Id)
                ?? _pathPlanningManager.Routes?.FirstOrDefault(route => route.Name == _selectedPathRoute.Name);
            if (coreRoute == null)
            {
                return;
            }

            _pathPlanningManager.DrawRouteVisualization(coreRoute, isAutoPath: false);
        }

        private void ClearNonGridPathVisualizations(string context)
        {
            if (PathPointRenderPlugin.Instance == null)
            {
                return;
            }

            try
            {
                PathPointRenderPlugin.Instance.ClearPathsExcept(
                    "grid_visualization_all",
                    "grid_visualization_channel",
                    "grid_visualization_unknown",
                    "grid_visualization_obstacle",
                    "grid_visualization_door");
                LogManager.Info($"{context}:已清除现有路径可视化显示(保留网格可视化)");
            }
            catch (Exception ex)
            {
                LogManager.Error($"{context}:清除现有路径可视化失败: {ex.Message}", ex);
                throw;
            }
        }

        private async Task ExecuteSelectAssemblyStartPointAsync()
        {
            await SafeExecuteAsync(() =>
            {
                if (_pathPlanningManager == null)
                {
                    throw new InvalidOperationException("路径规划管理器未初始化,无法选择装配起点");
                }

                if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
                {
                    throw new InvalidOperationException("终点箱体未设置或已失效,请重新捕获终点箱体");
                }

                if (!AssemblyReferencePathManager.Instance.HasReferenceLine)
                {
                    throw new InvalidOperationException("请先选择安装点,系统生成终端安装辅助线后才能取起点");
                }

                ClearAssemblyInstallationReferenceVisuals();
                BeginAssemblyStartPointSelection(
                    statusMessage: "请在辅助线附近点击一个起点,系统会自动吸附到辅助线上并生成直线路径",
                    logMessage: "[直线装配] 已进入起点拾取模式",
                    toolPluginFailureMessage: "ToolPlugin 初始化失败,请重试");
            }, "选择终端安装起点");
        }

        private async Task ExecuteRepositionRailStartPointAsync()
        {
            await SafeExecuteAsync(() =>
            {
                if (_pathPlanningManager == null)
                {
                    throw new InvalidOperationException("路径规划管理器未初始化,无法重选起点。");
                }

                if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
                {
                    throw new InvalidOperationException("终点箱体未设置或已失效,请先捕获终点箱体。");
                }

                var selectedRailRoute = GetSelectedCoreRoute();
                if (selectedRailRoute == null || selectedRailRoute.PathType != PathType.Rail)
                {
                    throw new InvalidOperationException("请先选中一条需要编辑起点的 Rail 路径。");
                }

                SetRailAssemblyWorkflowMode(RailAssemblyWorkflowMode.EditSelectedRail);
                RefreshSelectedRailReferenceLineVisuals();
                if (!AssemblyReferencePathManager.Instance.HasReferenceLine)
                {
                    throw new InvalidOperationException("当前 Rail 路径无法生成辅助线,请先检查路径起点和终点。");
                }

                ClearAssemblyInstallationReferenceVisuals();
                BeginAssemblyStartPointSelection(
                    statusMessage: "请在辅助线附近点击新的起点位置,系统会自动吸附到辅助线上并更新当前 Rail 路径。",
                    logMessage: "[Rail构型] 已进入起点重选模式",
                    toolPluginFailureMessage: "ToolPlugin 初始化失败,请重试。");
            }, "重选 Rail 路径起点");
        }

        private void ExecuteClearAssemblyReferenceRod()
        {
            try
            {
                ClearAssemblyReferenceLineVisuals();
                ClearAssemblyEndFaceAnalysisVisuals();
                ClearAssemblyInstallationReferenceVisuals();
                UpdateMainStatus("已隐藏终端安装辅助线");
                LogManager.Info("[直线装配] 已隐藏辅助线");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 隐藏辅助线失败: {ex.Message}");
            }
        }


        private async void OnAssemblyReferenceMouseClicked(object sender, PickItemResult pickResult)
        {
            try
            {
                if (!IsSelectingAssemblyStartPoint || pickResult == null)
                {
                    return;
                }

                Point3D projectedStartPoint = AssemblyReferencePathManager.Instance.ProjectPointToReferenceLine(pickResult.Point);
                _assemblyStartPoint = projectedStartPoint;
                AssemblyStartPointText = $"({projectedStartPoint.X:F2}, {projectedStartPoint.Y:F2}, {projectedStartPoint.Z:F2})";
                LogManager.Info(
                    $"[直线装配] 点击点=({pickResult.Point.X:F2}, {pickResult.Point.Y:F2}, {pickResult.Point.Z:F2})," +
                    $"投影起点=({projectedStartPoint.X:F2}, {projectedStartPoint.Y:F2}, {projectedStartPoint.Z:F2})");

                await SafeExecuteAsync(() =>
                {
                    ApplyAssemblyStartPointForCurrentWorkflow(projectedStartPoint);

                    CleanupAssemblyReferenceSelection();
                }, "生成终端安装路径");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 处理起点拾取失败: {ex.Message}", ex);
                UpdateMainStatus($"终端安装起点拾取失败: {ex.Message}");
                CleanupAssemblyReferenceSelection();
            }
        }


        private void PrepareRailAssemblyWorkflowForMode(
            RailAssemblyWorkflowMode workflowMode,
            string editActionDescription,
            bool syncMountModeFromRoute)
        {
            PathRoute selectedRailRoute = null;
            if (IsRailAssemblyEditMode(workflowMode))
            {
                selectedRailRoute = RequireSelectedRailRouteForAssemblyEdit(editActionDescription);
                if (syncMountModeFromRoute)
                {
                    AssemblyMountMode = selectedRailRoute.RailMountMode;
                }
            }

            SetRailAssemblyWorkflowMode(workflowMode);
        }

        private PathRoute RequireSelectedRailRouteForAssemblyEdit(string errorMessage)
        {
            var selectedRailRoute = GetSelectedCoreRoute();
            if (selectedRailRoute == null || selectedRailRoute.PathType != PathType.Rail)
            {
                throw new InvalidOperationException(errorMessage);
            }

            return selectedRailRoute;
        }

        private void BeginAssemblyStartPointSelection(string statusMessage, string logMessage, string toolPluginFailureMessage)
        {
            CleanupAssemblyReferenceSelection();

            _pathPlanningManager.DisableMouseHandling();
            IsSelectingAssemblyStartPoint = true;
            NotifyRailAssemblyCommandStateChanged();

            PathClickToolPlugin.MouseClicked -= OnAssemblyReferenceMouseClicked;
            PathClickToolPlugin.MouseClicked += OnAssemblyReferenceMouseClicked;

            if (!ForceReinitializeToolPlugin(subscribeToEvents: false))
            {
                CleanupAssemblyReferenceSelection();
                throw new InvalidOperationException(toolPluginFailureMessage);
            }

            _pathPlanningManager.StartClickTool(PathPointType.StartPoint);
            UpdateMainStatus(statusMessage);
            LogManager.Info(logMessage);
        }

        private void BeginAssemblyEndFacePick()
        {
            CleanupAssemblyReferenceSelection();
            CleanupAssemblyEndFaceSelection(clearVisuals: false);
            CleanupAssemblyInstallationSelection();
            ClearAssemblyEndFaceAnalysisVisuals();
            ResetAssemblyEndFaceAnalysisState();
            ClearAssemblyInstallationReferenceVisuals();
            ResetAssemblyInstallationReferenceState();
            _assemblyEndFaceSeedPoints.Clear();

            _pathPlanningManager.DisableMouseHandling();
            _isSelectingAssemblyEndFacePoints = true;
            NotifyRailAssemblyCommandStateChanged();

            // 激活取面工具
            try
            {
                var assemblyPath = FaceInferToolPlugin.AssemblyPath;
                NavisApplication.Plugins.AddPluginAssembly(assemblyPath);
                var record = (ToolPluginRecord)NavisApplication.Plugins.FindPlugin("FaceInferTool.NavisworksTransport");
                var loadedPlugin = record.LoadPlugin();
                NavisApplication.MainDocument.Tool.Value = Tool.None;
                NavisApplication.MainDocument.Tool.SetCustomToolPlugin(loadedPlugin);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 激活取面工具失败: {ex.Message}", ex);
                CleanupAssemblyEndFaceSelection(clearVisuals: true);
                throw new InvalidOperationException("取面工具激活失败,请重试。");
            }

            FaceInferToolPlugin.FaceInferred += OnEndFaceInferred;

            UpdateMainStatus("请在终点箱体端面上点击一下,系统将自动分析端面中心。");
            LogManager.Info("[直线装配] 已进入快速取端面模式");
        }

        private void OnEndFaceInferred(object sender, FaceInferResult result)
        {
            FaceInferToolPlugin.FaceInferred -= OnEndFaceInferred;

            // 恢复选择工具
            try { NavisApplication.MainDocument.Tool.Value = Tool.Select; } catch { }

            if (!result.IsValid)
            {
                CleanupAssemblyEndFaceSelection(clearVisuals: false);
                var reason = result.FailureReason ?? "未命中有效表面。";
                DialogHelper.ShowStatusAndDialog(reason, "取端面失败", reason, UpdateMainStatus, System.Windows.MessageBoxImage.Warning);
                return;
            }

            // PickItemFromPoint 返回的是底层几何节点，需要沿父链检查是否属于终点箱体
            var pickItem = result.ModelItem;
            var matched = pickItem != null && (
                pickItem == _assemblyTerminalObject ||
                pickItem.AncestorsAndSelf.Any(a => a == _assemblyTerminalObject));
            if (!matched)
            {
                CleanupAssemblyEndFaceSelection(clearVisuals: false);
                LogManager.Debug($"[直线装配] 取面命中 {ModelItemAnalysisHelper.GetSafeDisplayName(pickItem)}, 非终点箱体");
                DialogHelper.ShowStatusAndDialog(
                    "点击的不是终点箱体。",
                    "取端面失败",
                    "点击的不是终点箱体。\n请确认已先选择终点箱体，然后在其端面点击。",
                    UpdateMainStatus,
                    System.Windows.MessageBoxImage.Warning);
                return;
            }

            try
            {
                var endFaceResult = AssemblyEndFaceAnalyzer.Analyze(
                    _assemblyTerminalObject,
                    result.HitPoint,
                    result.Normal);

                if (!endFaceResult.IsReliable)
                {
                    CleanupAssemblyEndFaceSelection(clearVisuals: false);
                    UpdateMainStatus($"端面分析失败: {endFaceResult.DiagnosticMessage}");
                    return;
                }

                Point3D centerPoint = AssemblyEndFaceAnalyzer.ToPoint3D(endFaceResult.Center);
                Point3D sphereCenterPoint = new Point3D(
                    AssemblySphereCenterX, AssemblySphereCenterY, AssemblySphereCenterZ);
                Vector3 orientedNormal = AssemblyEndFaceAnalyzer.OrientNormalTowardTarget(
                    endFaceResult.Normal,
                    new Vector3((float)centerPoint.X, (float)centerPoint.Y, (float)centerPoint.Z),
                    new Vector3((float)sphereCenterPoint.X, (float)sphereCenterPoint.Y, (float)sphereCenterPoint.Z));

                _hasAssemblyEndFaceAnalysis = true;
                _assemblyEndFaceCenterPoint = centerPoint;
                _assemblyEndFaceNormal = orientedNormal;
                RenderAssemblyEndFaceCenter(centerPoint);
                RenderAssemblyEndFaceNormal(centerPoint, orientedNormal);
                RefreshAssemblyTerminalObjectInfo();
                RefreshAssemblyReferenceRodIfNeeded();
                UpdateMainStatus($"端面分析完成:中心=({centerPoint.X:F2}, {centerPoint.Y:F2}, {centerPoint.Z:F2}),三角形={endFaceResult.CandidateTriangleCount}");
                LogManager.Info(
                    $"[直线装配] 快速取端面完成: 中心=({centerPoint.X:F3}, {centerPoint.Y:F3}, {centerPoint.Z:F3}), " +
                    $"法向=({orientedNormal.X:F4}, {orientedNormal.Y:F4}, {orientedNormal.Z:F4}), " +
                    $"三角形={endFaceResult.CandidateTriangleCount}");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 端面分析失败: {ex.Message}", ex);
                DialogHelper.ShowStatusAndDialog(
                    ex.Message,
                    "取端面失败",
                    ex.Message,
                    UpdateMainStatus,
                    System.Windows.MessageBoxImage.Warning,
                    5000);
            }
            finally
            {
                _isSelectingAssemblyEndFacePoints = false;
                NotifyRailAssemblyCommandStateChanged();
            }
        }

        private void BeginAssemblyInstallationPick()
        {
            CleanupAssemblyReferenceSelection();
            CleanupAssemblyInstallationSelection();
            ClearAssemblyInstallationReferenceVisuals();
            ResetAssemblyInstallationReferenceState();
            _assemblyInstallationSeedPoints.Clear();

            _pathPlanningManager.DisableMouseHandling();
            _isSelectingAssemblyInstallationPoint = true;
            NotifyRailAssemblyCommandStateChanged();

            try
            {
                var assemblyPath = FaceInferToolPlugin.AssemblyPath;
                NavisApplication.Plugins.AddPluginAssembly(assemblyPath);
                var record = (ToolPluginRecord)NavisApplication.Plugins.FindPlugin("FaceInferTool.NavisworksTransport");
                var loadedPlugin = record.LoadPlugin();
                NavisApplication.MainDocument.Tool.Value = Tool.None;
                NavisApplication.MainDocument.Tool.SetCustomToolPlugin(loadedPlugin);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 激活取面工具失败: {ex.Message}", ex);
                CleanupAssemblyInstallationSelection();
                throw new InvalidOperationException("取面工具激活失败,请重试。");
            }

            FaceInferToolPlugin.FaceInferred += OnInstallationFaceInferred;
            UpdateMainStatus("请在终点箱体安装面上点击一下。");
            LogManager.Info("[直线装配] 已进入选安装面模式");
        }

        private void OnInstallationFaceInferred(object sender, FaceInferResult result)
        {
            FaceInferToolPlugin.FaceInferred -= OnInstallationFaceInferred;
            try { NavisApplication.MainDocument.Tool.Value = Tool.Select; } catch { }

            if (_assemblyTerminalObject == null)
            {
                CleanupAssemblyInstallationSelection();
                DialogHelper.ShowStatusAndDialog(
                    "尚未捕获终点箱体。",
                    "选安装面失败",
                    "尚未捕获终点箱体。",
                    UpdateMainStatus,
                    System.Windows.MessageBoxImage.Warning);
                return;
            }

            if (!result.IsValid)
            {
                CleanupAssemblyInstallationSelection();
                var reason = result.FailureReason ?? "未命中有效表面。";
                DialogHelper.ShowStatusAndDialog(reason, "选安装面失败", reason, UpdateMainStatus, System.Windows.MessageBoxImage.Warning);
                return;
            }

            var pickItem = result.ModelItem;
            var matched = pickItem != null && (
                pickItem == _assemblyTerminalObject ||
                pickItem.AncestorsAndSelf.Any(a => a == _assemblyTerminalObject));
            if (!matched)
            {
                CleanupAssemblyInstallationSelection();
                DialogHelper.ShowStatusAndDialog(
                    "取面失败: 请确认点击的是终点箱体的表面。",
                    "选安装面失败",
                    "点击的不是终点箱体。\n请确认已先选择终点箱体，然后在其表面点击。",
                    UpdateMainStatus,
                    System.Windows.MessageBoxImage.Warning);
                return;
            }

            try
            {
                Point3D opticalAxisReferencePoint = GetAssemblyOpticalAxisReferencePoint();
                Point3D sphereCenterPoint = new Point3D(AssemblySphereCenterX, AssemblySphereCenterY, AssemblySphereCenterZ);
                Vector3 opticalAxisDirection = new Vector3(
                    (float)(opticalAxisReferencePoint.X - sphereCenterPoint.X),
                    (float)(opticalAxisReferencePoint.Y - sphereCenterPoint.Y),
                    (float)(opticalAxisReferencePoint.Z - sphereCenterPoint.Z));

                var refResult = AssemblyInstallationReferenceBuilder.BuildFromFaceNormal(
                    new Vector3((float)opticalAxisReferencePoint.X, (float)opticalAxisReferencePoint.Y, (float)opticalAxisReferencePoint.Z),
                    opticalAxisDirection,
                    new Vector3((float)result.HitPoint.X, (float)result.HitPoint.Y, (float)result.HitPoint.Z),
                    new Vector3((float)result.Normal.X, (float)result.Normal.Y, (float)result.Normal.Z));

                _hasAssemblyInstallationReference = true;
                _assemblyInstallationPickPoint = AssemblyEndFaceAnalyzer.ToPoint3D(refResult.PickPoint);
                _assemblyInstallationBaseAnchorPoint = AssemblyEndFaceAnalyzer.ToPoint3D(refResult.AnchorPoint);
                _assemblyInstallationPlaneNormal = refResult.PlaneNormal;
                _assemblyInstallationPlaneSpanDirection = refResult.PlaneSpanDirection;
                _assemblyInstallationOffsetDistanceInMeters = UnitsConverter.ConvertToMeters(refResult.OffsetDistance);
                _assemblyAnchorVerticalOffsetInMeters = DefaultAssemblyAnchorVerticalOffsetInMeters;
                OnPropertyChanged(nameof(AssemblyAnchorVerticalOffsetInMeters));
                UpdateAssemblyInstallationAnchorFromVerticalOffset();

                _assemblyInstallationSeedPoints.Add(result.HitPoint);
                _assemblyInstallationSeedPoints.Add(result.HitPoint);
                RenderAssemblyInstallationPickPoints(_assemblyInstallationSeedPoints);
                RenderAssemblyInstallationCenterLine(
                    AssemblyEndFaceAnalyzer.ToPoint3D(refResult.InstallLineBasePoint), refResult.OpticalAxisDirection);

                RefreshAssemblyTerminalObjectInfo();
                RefreshAssemblyReferenceRodIfNeeded();
                NotifyRailAssemblyCommandStateChanged();

                ApplyAssemblyInstallationReferenceForCurrentWorkflow();
                CleanupAssemblyInstallationSelection(clearVisuals: false);

                var anchorPt = AssemblyEndFaceAnalyzer.ToPoint3D(refResult.AnchorPoint);
                UpdateMainStatus($"安装点已确定: 偏距={_assemblyInstallationOffsetDistanceInMeters:F3}m, 可继续取起点");
                LogManager.Info(
                    $"[直线装配] 选安装面完成: 安装点=({anchorPt.X:F3}, {anchorPt.Y:F3}, {anchorPt.Z:F3}), " +
                    $"偏距={_assemblyInstallationOffsetDistanceInMeters:F3}m, " +
                    $"法向=({refResult.PlaneNormal.X:F4}, {refResult.PlaneNormal.Y:F4}, {refResult.PlaneNormal.Z:F4})");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 安装面分析失败: {ex.Message}", ex);
                CleanupAssemblyInstallationSelection();
                DialogHelper.ShowStatusAndDialog(
                    ex.Message,
                    "选安装面失败",
                    ex.Message,
                    UpdateMainStatus,
                    System.Windows.MessageBoxImage.Warning,
                    5000);
            }
        }


        private void ApplyAssemblyStartPointForCurrentWorkflow(Point3D projectedStartPoint)
        {
            if (IsRailEditingWorkflowActive)
            {
                UpdateSelectedRailRouteStartPoint(projectedStartPoint);
                ClearAssemblyReferenceLineVisuals();
                UpdateMainStatus("已根据辅助线更新当前 Rail 路径起点");
                return;
            }

            CreateAssemblyLinearRoute(projectedStartPoint);
            UpdateMainStatus("已根据辅助线起点生成终端安装路径");
        }

        private void ApplyAssemblyInstallationReferenceForCurrentWorkflow()
        {
            if (IsRailEditingWorkflowActive)
            {
                var selectedRailRoute = RequireSelectedRailRouteForAssemblyEdit("当前没有可更新安装点的 Rail 路径。");
                PersistAssemblyInstallationReferenceToRailRoute(
                    selectedRailRoute,
                    "已重选安装点并同步更新 Rail 路径安装参数");
                return;
            }

            LogManager.Info("[直线装配] 安装点已确定,请继续选择起点以生成新路径");
        }

        private void CreateAssemblyLinearRoute(Point3D startPoint)
        {
            Point3D endPoint = AssemblyReferencePathManager.Instance.ReferenceLineEnd;
            string routeName = $"人工_{DateTime.Now:MMdd_HHmmss}";

            var route = new PathRoute(routeName)
            {
                Description = $"直线装配路径 - {AssemblyTerminalObjectName}",
                PathType = PathType.Rail,
                RailMountMode = AssemblyMountMode,
                RailPathDefinitionMode = RailPathDefinitionMode.RailCenterLine,
                RailNormalOffset = UnitsConverter.ConvertFromMeters(AssemblyAnchorVerticalOffsetInMeters)
            };

            if (_hasAssemblyInstallationReference)
            {
                route.RailPreferredNormal = CreatePersistedAssemblyPreferredNormal();
            }

            route.AddPoint(new PathPoint(startPoint, "起点", PathPointType.StartPoint));
            route.AddPoint(new PathPoint(endPoint, "装配终点", PathPointType.EndPoint));

            if (!_pathPlanningManager.AddRoute(route))
            {
                throw new InvalidOperationException("装配路径添加失败");
            }

            _pathPlanningManager.SetCurrentRoute(route);
            if (!_pathPlanningManager.GeneratePath(route))
            {
                throw new InvalidOperationException("装配路径生成失败");
            }

            if (!_pathPlanningManager.FinishEditing())
            {
                throw new InvalidOperationException("装配路径完成编辑失败");
            }

            var generatedRouteViewModel = PathRoutes.FirstOrDefault(p => p.Name == route.Name);
            if (generatedRouteViewModel != null)
            {
                SelectedPathRoute = generatedRouteViewModel;
                UpdatePassageSpaceVisualizationForPathType(route.PathType);
            }

            HideAssemblyReferenceVisuals(
                resetStartPointText: false,
                statusMessage: null,
                logMessage: "[直线装配] 路径生成完成后已隐藏辅助线可视化");

            AssemblyTerminalObjectInfo = string.Format(
                "对接终点=({0:F2}, {1:F2}, {2:F2}),装配起点={3},安装方式={4},对接基准={5}",
                endPoint.X,
                endPoint.Y,
                endPoint.Z,
                AssemblyStartPointText,
                AssemblyMountMode == RailMountMode.OverRail ? "轨上安装" : "轨下安装",
                GetAssemblyAnchorText());

            OnPropertyChanged(nameof(PathRoutes));
            LogManager.Info(
                $"[直线装配] 已生成并完成路径: {route.Name},起点=({startPoint.X:F2}, {startPoint.Y:F2}, {startPoint.Z:F2}),终点=({endPoint.X:F2}, {endPoint.Y:F2}, {endPoint.Z:F2})" +
                $"{(route.RailPreferredNormal != null ? $",安装法向=({route.RailPreferredNormal.X:F3}, {route.RailPreferredNormal.Y:F3}, {route.RailPreferredNormal.Z:F3})" : string.Empty)}");
        }

        private void UpdateSelectedRailRouteStartPoint(Point3D startPoint)
        {
            var route = GetSelectedCoreRoute();
            if (route == null || route.PathType != PathType.Rail)
            {
                throw new InvalidOperationException("当前没有可更新起点的 Rail 路径。");
            }

            int startPointIndex = GetRailRouteStartPointIndex(route);
            if (startPointIndex < 0)
            {
                throw new InvalidOperationException("当前 Rail 路径没有可更新的起点。");
            }

            if (!_pathPlanningManager.UpdatePathPointWithConstraints(route, startPointIndex, startPoint))
            {
                throw new InvalidOperationException("更新 Rail 路径起点失败。");
            }

            route.LastModified = DateTime.Now;
            _pathPlanningManager.SavePathToDatabase(route);
            _pathPlanningManager.DrawRouteVisualization(route, isAutoPath: false);
            _pathPlanningManager.RaiseVisualizationStateChanged();

            if (SelectedPathRoute != null && SelectedPathRoute.Id == route.Id)
            {
                SyncPathViewModelFromCoreRoute(SelectedPathRoute, route, preserveSelection: true);
                RefreshSelectedRailReferenceLineVisuals();
            }

            LogManager.Info($"[Rail构型] {route.Name}: 已重选起点为 ({startPoint.X:F3}, {startPoint.Y:F3}, {startPoint.Z:F3})");
        }

        private void HideAssemblyReferenceVisuals(bool resetStartPointText, string statusMessage, string logMessage)
        {
            CleanupAssemblyReferenceSelection();
            CleanupAssemblyEndFaceSelection(clearVisuals: false);
            ClearAssemblyReferenceLineVisuals();
            ClearAssemblyEndFaceAnalysisVisuals();
            ClearAssemblyInstallationReferenceVisuals();
            if (resetStartPointText)
            {
                AssemblyStartPointText = "未选择";
            }
            NotifyRailAssemblyCommandStateChanged();
            if (!string.IsNullOrWhiteSpace(statusMessage))
            {
                UpdateMainStatus(statusMessage);
            }

            if (!string.IsNullOrWhiteSpace(logMessage))
            {
                LogManager.Info(logMessage);
            }
        }

        private void ResetRailAssemblyWorkflowState(bool announce, string statusMessage = null, string logMessage = null)
        {
            CleanupAssemblyReferenceSelection();
            CleanupAssemblyEndFaceSelection(clearVisuals: true);
            CleanupAssemblyInstallationSelection(clearVisuals: true);
            ClearAssemblyReferenceLineVisuals();
            ClearAssemblyEndFaceAnalysisVisuals();
            ClearAssemblyInstallationReferenceVisuals();
            ResetAssemblyEndFaceAnalysisState();
            ResetAssemblyInstallationReferenceState();
            _railAssemblyContext.ResetSession();
            HasAssemblyTerminalObject = false;
            AssemblyTerminalObjectName = _assemblyTerminalObjectName;
            AssemblyTerminalObjectInfo = _assemblyTerminalObjectInfo;
            AssemblyStartPointText = _assemblyStartPointText;

            SetRailAssemblyWorkflowMode(RailAssemblyWorkflowMode.None);
            NotifyRailAssemblyCommandStateChanged();

            if (announce && !string.IsNullOrWhiteSpace(statusMessage))
            {
                UpdateMainStatus(statusMessage);
            }

            if (!string.IsNullOrWhiteSpace(logMessage))
            {
                LogManager.Info(logMessage);
            }
        }

        private void ExecuteCancelRailAssemblyWorkflow()
        {
            try
            {
                ResetRailAssemblyWorkflowState(
                    announce: true,
                    statusMessage: "已取消 Rail 装配流程",
                    logMessage: "[直线装配] 已取消 Rail 装配流程并清理状态");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 取消 Rail 装配流程失败: {ex.Message}", ex);
                UpdateMainStatus($"取消 Rail 装配流程失败: {ex.Message}");
            }
        }

        private Point3D GetAssemblyTerminalAnchorPoint()
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                throw new InvalidOperationException("终点箱体未设置或已失效,无法计算对接点");
            }

            if (_hasAssemblyInstallationReference && _assemblyInstallationAnchorPoint != null)
            {
                return _assemblyInstallationAnchorPoint;
            }

            HostCoordinateAdapter adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
            ProjectReferenceFrame projectFrame = CreateAssemblyProjectReferenceFrame(adapter);

            var bounds = _assemblyTerminalObject.BoundingBox();
            Point3D canonicalCenter = adapter.ToCanonicalPoint(bounds.Center);
            Vector3D canonicalUp = adapter.ToCanonicalVector(
                ModelItemTransformHelper.GetDirectionFromTransform(
                    _assemblyTerminalObject.Transform,
                    projectFrame.DefaultModelAxisConvention.UpAxis));
            double direction = GetAssemblyAnchorDirection();
            double verticalOffset = UnitsConverter.ConvertFromMeters(AssemblyAnchorVerticalOffsetInMeters);

            Point3D canonicalAnchorPoint = new Point3D(
                canonicalCenter.X + canonicalUp.X * verticalOffset * direction,
                canonicalCenter.Y + canonicalUp.Y * verticalOffset * direction,
                canonicalCenter.Z + canonicalUp.Z * verticalOffset * direction);

            return adapter.FromCanonicalPoint(canonicalAnchorPoint);
        }

        /// <summary>
        /// 根据 Rail 路径终点和路径长度计算起点位置。
        /// 起点位于从终点沿光轴方向(远离球心方向)延伸路径长度的位置。
        /// </summary>
        private Point3D CalculateRailStartPointFromEndPoint(Point3D endPoint, double pathLength)
        {
            HostCoordinateAdapter adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
            ProjectReferenceFrame projectFrame = CreateAssemblyProjectReferenceFrame(adapter);

            Point3D opticalAxisReferencePoint = GetAssemblyOpticalAxisReferencePoint();
            Point3D canonicalEndPoint = adapter.ToCanonicalPoint(endPoint);
            Point3D canonicalOpticalAxisRef = adapter.ToCanonicalPoint(opticalAxisReferencePoint);

            // 计算从球心到光轴参考点的方向(作为参考线方向)
            Vector3D direction = new Vector3D(
                canonicalOpticalAxisRef.X - projectFrame.SphereCenterInCanonical.X,
                canonicalOpticalAxisRef.Y - projectFrame.SphereCenterInCanonical.Y,
                canonicalOpticalAxisRef.Z - projectFrame.SphereCenterInCanonical.Z);

            direction = direction.Normalize();

            // 起点 = 终点 + 方向 * 路径长度
            Point3D canonicalStartPoint = new Point3D(
                canonicalEndPoint.X + direction.X * pathLength,
                canonicalEndPoint.Y + direction.Y * pathLength,
                canonicalEndPoint.Z + direction.Z * pathLength);

            return adapter.FromCanonicalPoint(canonicalStartPoint);
        }

        private void UpdateAssemblyInstallationAnchorFromVerticalOffset()
        {
            if (!_hasAssemblyInstallationReference ||
                _assemblyInstallationBaseAnchorPoint == null)
            {
                return;
            }

            double offset = UnitsConverter.ConvertFromMeters(_assemblyAnchorVerticalOffsetInMeters);
            _assemblyInstallationAnchorPoint = new Point3D(
                _assemblyInstallationBaseAnchorPoint.X + _assemblyInstallationPlaneNormal.X * (float)offset,
                _assemblyInstallationBaseAnchorPoint.Y + _assemblyInstallationPlaneNormal.Y * (float)offset,
                _assemblyInstallationBaseAnchorPoint.Z + _assemblyInstallationPlaneNormal.Z * (float)offset);

            if (_hasAssemblyInstallationReference)
            {
                RenderAssemblyInstallationPickPoints(_assemblyInstallationSeedPoints);
                RenderAssemblyInstallationAnchorPoint(_assemblyInstallationAnchorPoint);
                RenderAssemblyInstallationCenterLine(_assemblyInstallationPickPoint, GetCurrentAssemblyOpticalAxisDirection());
                RenderAssemblyInstallationPlane(_assemblyInstallationAnchorPoint, GetCurrentAssemblyOpticalAxisDirection(), _assemblyInstallationPlaneSpanDirection);
            }
            else
            {
                ClearAssemblyInstallationReferenceVisuals();
            }
        }

        private Point3D CreatePersistedAssemblyPreferredNormal()
        {
            HostCoordinateAdapter adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
            Vector3 normalizedPreferredNormal = RailPathPoseHelper.NormalizePreferredNormalToHostUpHemisphere(
                _assemblyInstallationPlaneNormal,
                adapter.HostUpVector3);

            return new Point3D(
                normalizedPreferredNormal.X,
                normalizedPreferredNormal.Y,
                normalizedPreferredNormal.Z);
        }

        private Vector3 GetCurrentAssemblyOpticalAxisDirection()
        {
            Point3D opticalAxisReferencePoint = GetAssemblyOpticalAxisReferencePoint();
            Point3D sphereCenterPoint = new Point3D(
                AssemblySphereCenterX,
                AssemblySphereCenterY,
                AssemblySphereCenterZ);

            Vector3 opticalAxisDirection = new Vector3(
                (float)(opticalAxisReferencePoint.X - sphereCenterPoint.X),
                (float)(opticalAxisReferencePoint.Y - sphereCenterPoint.Y),
                (float)(opticalAxisReferencePoint.Z - sphereCenterPoint.Z));
            return Vector3.Normalize(opticalAxisDirection);
        }

        private Point3D GetAssemblyOpticalAxisReferencePoint()
        {
            if (_hasAssemblyEndFaceAnalysis && _assemblyEndFaceCenterPoint != null)
            {
                return _assemblyEndFaceCenterPoint;
            }

            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                throw new InvalidOperationException("终点箱体未设置或已失效,无法计算光轴参考点");
            }

            return _assemblyTerminalObject.BoundingBox().Center;
        }

        private AssemblyReferenceLine BuildAssemblyReferenceLine()
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                throw new InvalidOperationException("终点箱体未设置或已失效,无法生成装配参考线");
            }

            HostCoordinateAdapter adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
            ProjectReferenceFrame projectFrame = CreateAssemblyProjectReferenceFrame(adapter);

            Point3D opticalAxisReferencePoint = GetAssemblyOpticalAxisReferencePoint();
            Point3D endPoint = GetAssemblyTerminalAnchorPoint();

            Point3D canonicalAxisReferencePoint = adapter.ToCanonicalPoint(opticalAxisReferencePoint);
            Point3D canonicalEndPoint = adapter.ToCanonicalPoint(endPoint);
            Vector3D direction = new Vector3D(
                canonicalAxisReferencePoint.X - projectFrame.SphereCenterInCanonical.X,
                canonicalAxisReferencePoint.Y - projectFrame.SphereCenterInCanonical.Y,
                canonicalAxisReferencePoint.Z - projectFrame.SphereCenterInCanonical.Z);
            double directionLengthSquared = direction.X * direction.X + direction.Y * direction.Y + direction.Z * direction.Z;
            if (directionLengthSquared < 1e-9)
            {
                throw new InvalidOperationException("光轴参考点与项目球心重合,无法生成装配参考线方向");
            }

            direction = direction.Normalize();
            double rodLength = UnitsConverter.ConvertFromMeters(AssemblyReferenceRodLengthInMeters);
            Point3D canonicalStartPoint = new Point3D(
                canonicalEndPoint.X + direction.X * rodLength,
                canonicalEndPoint.Y + direction.Y * rodLength,
                canonicalEndPoint.Z + direction.Z * rodLength);
            Point3D startPoint = adapter.FromCanonicalPoint(canonicalStartPoint);

            LogManager.Info(
                $"[直线装配] 参考线已计算,终点锚点=({endPoint.X:F2}, {endPoint.Y:F2}, {endPoint.Z:F2}), " +
                $"光轴参考点=({opticalAxisReferencePoint.X:F2}, {opticalAxisReferencePoint.Y:F2}, {opticalAxisReferencePoint.Z:F2}), " +
                $"参考线外端=({startPoint.X:F2}, {startPoint.Y:F2}, {startPoint.Z:F2}), " +
                $"球心到光轴参考点方向(内部坐标)=({direction.X:F3}, {direction.Y:F3}, {direction.Z:F3})");

            return new AssemblyReferenceLine(startPoint, endPoint, direction);
        }

        private void RefreshAssemblyTerminalObjectInfo(Point3D referenceStartPoint = null, Point3D referenceEndPoint = null)
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                return;
            }

            var bounds = _assemblyTerminalObject.BoundingBox();
            string anchorText = GetAssemblyAnchorText();
            string mountText = AssemblyMountMode == RailMountMode.OverRail ? "轨上安装" : "轨下安装";
            Point3D opticalAxisReferencePoint = GetAssemblyOpticalAxisReferencePoint();
            string opticalAxisText = _hasAssemblyEndFaceAnalysis
                ? string.Format("端面中心=({0:F2}, {1:F2}, {2:F2})", opticalAxisReferencePoint.X, opticalAxisReferencePoint.Y, opticalAxisReferencePoint.Z)
                : string.Format("箱体中心=({0:F2}, {1:F2}, {2:F2})", opticalAxisReferencePoint.X, opticalAxisReferencePoint.Y, opticalAxisReferencePoint.Z);
            string anchorPointText = _hasAssemblyInstallationReference
                ? string.Format("{0}点=({1:F2}, {2:F2}, {3:F2})",
                    anchorText,
                    _assemblyInstallationAnchorPoint.X,
                    _assemblyInstallationAnchorPoint.Y,
                    _assemblyInstallationAnchorPoint.Z)
                : string.Format("{0}点=未选择", anchorText);
            string installationText = _hasAssemblyInstallationReference
                ? string.Format(
                    "安装面点中点=({0:F2}, {1:F2}, {2:F2}),安装点=({3:F2}, {4:F2}, {5:F2}),偏距={6:F3}m",
                    _assemblyInstallationPickPoint.X,
                    _assemblyInstallationPickPoint.Y,
                    _assemblyInstallationPickPoint.Z,
                    _assemblyInstallationAnchorPoint.X,
                    _assemblyInstallationAnchorPoint.Y,
                    _assemblyInstallationAnchorPoint.Z,
                    _assemblyInstallationOffsetDistanceInMeters)
                : "安装点=未选择";

            if (referenceStartPoint != null && referenceEndPoint != null)
            {
                AssemblyTerminalObjectInfo = string.Format(
                    "中心=({0:F2}, {1:F2}, {2:F2}),尺寸=({3:F2}, {4:F2}, {5:F2}),{6},{7},{8},{9},垂直偏移={10:F3}m,辅助线外端=({11:F2}, {12:F2}, {13:F2})",
                    bounds.Center.X,
                    bounds.Center.Y,
                    bounds.Center.Z,
                    bounds.Max.X - bounds.Min.X,
                    bounds.Max.Y - bounds.Min.Y,
                    bounds.Max.Z - bounds.Min.Z,
                    mountText,
                    anchorPointText,
                    opticalAxisText,
                    installationText,
                    AssemblyAnchorVerticalOffsetInMeters,
                    referenceStartPoint.X,
                    referenceStartPoint.Y,
                    referenceStartPoint.Z);
                return;
            }

            AssemblyTerminalObjectInfo = string.Format(
                "中心=({0:F2}, {1:F2}, {2:F2}),尺寸=({3:F2}, {4:F2}, {5:F2}),{6},{7},{8},{9},垂直偏移={10:F3}m",
                bounds.Center.X,
                bounds.Center.Y,
                bounds.Center.Z,
                bounds.Max.X - bounds.Min.X,
                bounds.Max.Y - bounds.Min.Y,
                bounds.Max.Z - bounds.Min.Z,
                mountText,
                anchorPointText,
                opticalAxisText,
                installationText,
                AssemblyAnchorVerticalOffsetInMeters);
        }

        private void RefreshAssemblyReferenceRodIfNeeded()
        {
            if (!ShouldShowAssemblyReferenceLineVisuals())
            {
                ClearAssemblyReferenceLineVisuals();
                return;
            }

            if (_assemblyTerminalObject == null)
            {
                return;
            }

            try
            {
                AssemblyReferenceLine referenceLine = BuildAssemblyReferenceLine();

                AssemblyReferencePathManager.Instance.CreateOrUpdateReferenceRod(
                    referenceLine.StartPoint,
                    referenceLine.EndPoint,
                    AssemblyReferenceRodDiameterInMeters);

                RefreshAssemblyTerminalObjectInfo(referenceLine.StartPoint, referenceLine.EndPoint);
                RenderAssemblyAnchorMarker();
                RenderAssemblyCenterGuideLine();
                RenderAssemblyReferenceLine(referenceLine);
                NotifyRailAssemblyCommandStateChanged();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 刷新参考杆失败: {ex.Message}", ex);
            }
        }

        private void InitializeAssemblyAnchorVerticalOffsetFromTerminalObject()
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                return;
            }

            HostCoordinateAdapter adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
            ProjectReferenceFrame projectFrame = CreateAssemblyProjectReferenceFrame(adapter);
            var bounds = _assemblyTerminalObject.BoundingBox();
            double suggestedOffset = UnitsConverter.ConvertToMeters(
                Math.Max(0.0, projectFrame.DefaultModelAxisConvention.GetUpSize(bounds) / 2.0));
            _assemblyAnchorVerticalOffsetInMeters = suggestedOffset;
            OnPropertyChanged(nameof(AssemblyAnchorVerticalOffsetInMeters));
        }

        private double GetAssemblyAnchorDirection()
        {
            return PathRoute.IsTopReferenceFaceForMountMode(AssemblyMountMode)
                ? 1.0
                : -1.0;
        }

        private string GetAssemblyAnchorText()
        {
            return PathRoute.IsTopReferenceFaceForMountMode(AssemblyMountMode)
                ? "顶面参考点"
                : "底面参考点";
        }

        private sealed class AssemblyReferenceLine
        {
            public AssemblyReferenceLine(Point3D startPoint, Point3D endPoint, Vector3D direction)
            {
                StartPoint = startPoint;
                EndPoint = endPoint;
                Direction = direction;
            }

            public Point3D StartPoint { get; }
            public Point3D EndPoint { get; }
            public Vector3D Direction { get; }
        }

        private static double CalculateDefaultAssemblyReferenceRodDiameterInMeters()
        {
            double standardRadiusInMeters = ConfigManager.Instance.Current.PathEditing.CellSizeMeters;
            standardRadiusInMeters = Math.Max(0.1, Math.Min(0.5, standardRadiusInMeters));
            return standardRadiusInMeters * 0.8;
        }

        private void RenderAssemblyAnchorMarker()
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                return;
            }

            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            Point3D anchorPoint = GetAssemblyTerminalAnchorPoint();
            LogManager.Info(
                $"[直线装配] 已渲染终点锚点标记: ({anchorPoint.X:F2}, {anchorPoint.Y:F2}, {anchorPoint.Z:F2})");
            var markerRoute = new PathRoute("装配对接点")
            {
                Id = AssemblyAnchorMarkerPathId,
                Description = "直线装配终点对接标记"
            };
            AddVisualizationPoint(markerRoute, anchorPoint, "对接点", PathPointType.EndPoint);
            renderPlugin.RenderPointOnly(markerRoute);
        }

        private void RenderAssemblyReferenceLine(AssemblyReferenceLine referenceLine)
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null || referenceLine == null)
            {
                return;
            }

            renderPlugin.RenderRailBaseline(
                AssemblyReferenceLinePathId,
                new List<Point3D> { referenceLine.EndPoint, referenceLine.StartPoint });

            LogManager.Info(
                $"[直线装配] 已渲染参考线: 终点锚点=({referenceLine.EndPoint.X:F2}, {referenceLine.EndPoint.Y:F2}, {referenceLine.EndPoint.Z:F2}), " +
                $"参考线外端=({referenceLine.StartPoint.X:F2}, {referenceLine.StartPoint.Y:F2}, {referenceLine.StartPoint.Z:F2})");
        }

        private void RenderAssemblyCenterGuideLine()
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                return;
            }

            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            HostCoordinateAdapter adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
            ProjectReferenceFrame projectFrame = CreateAssemblyProjectReferenceFrame(adapter);

            Point3D centerPoint = GetAssemblyOpticalAxisReferencePoint();
            Point3D sphereCenterPoint = adapter.FromCanonicalPoint(projectFrame.SphereCenterInCanonical);
            renderPlugin.RenderRailBaseline(
                AssemblyCenterGuideLinePathId,
                new List<Point3D> { sphereCenterPoint, centerPoint },
                RenderStyleName.AssemblyGuideLine);

            LogManager.Info(
                $"[直线装配] 已渲染球心到光轴参考点基准线: 球心=({sphereCenterPoint.X:F2}, {sphereCenterPoint.Y:F2}, {sphereCenterPoint.Z:F2}), " +
                $"光轴参考点=({centerPoint.X:F2}, {centerPoint.Y:F2}, {centerPoint.Z:F2})");
        }

        private void RenderAssemblyEndFaceSeedPoints()
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.RemovePath(AssemblyEndFaceSeedPathId);

            if (_assemblyEndFaceSeedPoints.Count == 0)
            {
                return;
            }

            var markerRoute = new PathRoute("端面三点")
            {
                Id = AssemblyEndFaceSeedPathId,
                Description = "终端安装端面三点"
            };

            for (int i = 0; i < _assemblyEndFaceSeedPoints.Count; i++)
            {
                AddVisualizationPoint(
                    markerRoute,
                    _assemblyEndFaceSeedPoints[i],
                    $"端面点{i + 1}",
                    PathPointType.WayPoint,
                    UnitsConverter.ConvertFromMeters(AssemblyVisualizationPointDiameterInMeters));
            }

            renderPlugin.RenderPointOnly(markerRoute);
        }

        private void RenderAssemblyEndFaceCenter(Point3D centerPoint)
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.RemovePath(AssemblyEndFaceCenterPathId);

            var markerRoute = new PathRoute("端面中心")
            {
                Id = AssemblyEndFaceCenterPathId,
                Description = "终端安装端面中心"
            };
            AddVisualizationPoint(
                markerRoute,
                centerPoint,
                "端面中心",
                PathPointType.WayPoint,
                UnitsConverter.ConvertFromMeters(AssemblyVisualizationPointDiameterInMeters));
            renderPlugin.RenderPointOnly(markerRoute);
        }

        private static void AddVisualizationPoint(
            PathRoute route,
            Point3D position,
            string name,
            PathPointType type,
            double? visualizationDiameter = null)
        {
            if (route == null)
            {
                throw new ArgumentNullException(nameof(route));
            }

            route.Points.Add(new PathPoint(position, name, type)
            {
                Index = route.Points.Count,
                VisualizationDiameter = visualizationDiameter
            });
        }

        private void RenderAssemblyEndFaceNormal(Point3D centerPoint, Vector3 normal)
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.ClearRailBaseline(AssemblyEndFaceNormalPathId);

            double lineLength = UnitsConverter.ConvertFromMeters(Math.Max(0.5, AssemblyReferenceRodDiameterInMeters * 4.0));
            Point3D normalEndPoint = new Point3D(
                centerPoint.X + normal.X * (float)lineLength,
                centerPoint.Y + normal.Y * (float)lineLength,
                centerPoint.Z + normal.Z * (float)lineLength);
            renderPlugin.RenderRailBaseline(
                AssemblyEndFaceNormalPathId,
                new List<Point3D> { centerPoint, normalEndPoint },
                RenderStyleName.AssemblyGuideLine);
        }


        private void RenderAssemblyInstallationPickPoints(IReadOnlyList<Point3D> pickPoints)
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.RemovePath(AssemblyInstallationPickPointPathId);
            var markerRoute = new PathRoute("安装点")
            {
                Id = AssemblyInstallationPickPointPathId,
                Description = "终端安装点"
            };
            for (int i = 0; i < pickPoints.Count; i++)
            {
                AddVisualizationPoint(
                    markerRoute,
                    pickPoints[i],
                    $"安装面点{i + 1}",
                    PathPointType.WayPoint,
                    UnitsConverter.ConvertFromMeters(AssemblyVisualizationPointDiameterInMeters));
            }
            renderPlugin.RenderPointOnly(markerRoute);
        }

        private void RenderAssemblyInstallationAnchorPoint(Point3D anchorPoint)
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.RemovePath(AssemblyInstallationAnchorPointPathId);
            var markerRoute = new PathRoute("安装点")
            {
                Id = AssemblyInstallationAnchorPointPathId,
                Description = "终端安装点"
            };
            AddVisualizationPoint(
                markerRoute,
                anchorPoint,
                "安装点",
                PathPointType.WayPoint,
                UnitsConverter.ConvertFromMeters(AssemblyVisualizationPointDiameterInMeters));
            renderPlugin.RenderPointOnly(markerRoute);
        }

        private void RenderAssemblyInstallationCenterLine(Point3D lineBasePoint, Vector3 axisDirection)
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.ClearRailBaseline(AssemblyInstallationCenterLinePathId);
            double halfLength = GetAssemblyInstallationPlaneSideLength() * AssemblyInstallationLineLengthScale / 2.0;
            Point3D startPoint = new Point3D(
                lineBasePoint.X - axisDirection.X * (float)halfLength,
                lineBasePoint.Y - axisDirection.Y * (float)halfLength,
                lineBasePoint.Z - axisDirection.Z * (float)halfLength);
            Point3D endPoint = new Point3D(
                lineBasePoint.X + axisDirection.X * (float)halfLength,
                lineBasePoint.Y + axisDirection.Y * (float)halfLength,
                lineBasePoint.Z + axisDirection.Z * (float)halfLength);
            renderPlugin.RenderRailBaseline(
                AssemblyInstallationCenterLinePathId,
                new List<Point3D> { startPoint, endPoint },
                RenderStyleName.AssemblyGuideLine);
        }

        private void RenderAssemblyInstallationPlane(Point3D planeCenter, Vector3 axisDirection, Vector3 planeSpanDirection)
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            double sideLength = GetAssemblyInstallationPlaneSideLength();
            double halfLength = sideLength / 2.0;
            double thickness = UnitsConverter.ConvertFromMeters(0.01);

            Vector3D xVector = new Vector3D(
                axisDirection.X * (float)sideLength,
                axisDirection.Y * (float)sideLength,
                axisDirection.Z * (float)sideLength);
            Vector3D yVector = new Vector3D(
                planeSpanDirection.X * (float)sideLength,
                planeSpanDirection.Y * (float)sideLength,
                planeSpanDirection.Z * (float)sideLength);
            Point3D origin = new Point3D(
                planeCenter.X - axisDirection.X * (float)halfLength - planeSpanDirection.X * (float)halfLength + _assemblyInstallationPlaneNormal.X * thickness,
                planeCenter.Y - axisDirection.Y * (float)halfLength - planeSpanDirection.Y * (float)halfLength + _assemblyInstallationPlaneNormal.Y * thickness,
                planeCenter.Z - axisDirection.Z * (float)halfLength - planeSpanDirection.Z * (float)halfLength + _assemblyInstallationPlaneNormal.Z * thickness);

            renderPlugin.RemovePath(AssemblyInstallationPlanePathId);
            renderPlugin.RenderRectanglePlane(
                AssemblyInstallationPlanePathId,
                origin,
                xVector,
                yVector,
                RenderStyleName.AssemblyInstallationPlane,
                filled: true);
        }

        private double GetAssemblyInstallationPlaneSideLength()
        {
            if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject))
            {
                return UnitsConverter.ConvertFromMeters(1.0);
            }

            BoundingBox3D bounds = _assemblyTerminalObject.BoundingBox();
            double maxSize = Math.Max(
                bounds.Max.X - bounds.Min.X,
                Math.Max(bounds.Max.Y - bounds.Min.Y, bounds.Max.Z - bounds.Min.Z));
            return maxSize + UnitsConverter.ConvertFromMeters(AssemblyInstallationPlanePaddingInMeters) * 2.0;
        }

        private ProjectReferenceFrame CreateAssemblyProjectReferenceFrame(HostCoordinateAdapter adapter)
        {
            if (adapter == null)
            {
                throw new ArgumentNullException(nameof(adapter));
            }

            Point3D hostSphereCenter = new Point3D(
                AssemblySphereCenterX,
                AssemblySphereCenterY,
                AssemblySphereCenterZ);

            Point3D canonicalSphereCenter = adapter.ToCanonicalPoint(hostSphereCenter);
            return new ProjectReferenceFrame(
                canonicalSphereCenter,
                HostCoordinateAdapter.CanonicalUp,
                ModelAxisConvention.CreateDefaultForHost(adapter.HostType));
        }

        private void ClearAssemblyAnchorMarker()
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.RemovePath(AssemblyAnchorMarkerPathId);
        }

        private void ClearAssemblyReferenceLine()
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.ClearRailBaseline(AssemblyReferenceLinePathId);
        }

        private void ClearAssemblyCenterGuideLine()
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.ClearRailBaseline(AssemblyCenterGuideLinePathId);
        }

        private void ClearAssemblyReferenceLineVisuals()
        {
            AssemblyReferencePathManager.Instance.HideReferenceRod();
            ClearAssemblyAnchorMarker();
            ClearAssemblyCenterGuideLine();
            ClearAssemblyReferenceLine();
            NotifyRailAssemblyCommandStateChanged();
            OnPropertyChanged(nameof(CanRepositionRailStartPoint));
        }

        private void ClearAssemblyEndFaceAnalysisVisuals()
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.RemovePath(AssemblyEndFaceSeedPathId);
            renderPlugin.RemovePath(AssemblyEndFaceCenterPathId);
            renderPlugin.ClearRailBaseline(AssemblyEndFaceNormalPathId);
        }

        private void ResetAssemblyEndFaceAnalysisState()
        {
            _railAssemblyContext.ResetEndFaceAnalysis();
        }

        private void ClearAssemblyInstallationReferenceVisuals()
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin == null)
            {
                return;
            }

            renderPlugin.RemovePath(AssemblyInstallationPickPointPathId);
            renderPlugin.RemovePath(AssemblyInstallationAnchorPointPathId);
            renderPlugin.ClearRailBaseline(AssemblyInstallationCenterLinePathId);
            renderPlugin.ClearRailBaseline(AssemblyInstallationOffsetLinePathId);
            renderPlugin.RemovePath(AssemblyInstallationPlanePathId);
        }

        private void ResetAssemblyInstallationReferenceState()
        {
            _railAssemblyContext.ResetInstallationReference();
            OnPropertyChanged(nameof(AssemblyAnchorVerticalOffsetInMeters));
            NotifyRailAssemblyCommandStateChanged();
        }

        private void CleanupAssemblyReferenceSelection()
        {
            try
            {
                PathClickToolPlugin.MouseClicked -= OnAssemblyReferenceMouseClicked;
                IsSelectingAssemblyStartPoint = false;
                _pathPlanningManager?.EnableMouseHandling();
                _pathPlanningManager?.StopClickTool();
                NotifyRailAssemblyCommandStateChanged();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 清理起点拾取状态失败: {ex.Message}", ex);
            }
        }

        private void CleanupAssemblyInstallationSelection(bool clearVisuals = true)
        {
            try
            {
                _isSelectingAssemblyInstallationPoint = false;
                _pathPlanningManager?.EnableMouseHandling();
                _pathPlanningManager?.StopClickTool();
                if (clearVisuals)
                {
                    ClearAssemblyInstallationReferenceVisuals();
                }
                NotifyRailAssemblyCommandStateChanged();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 清理参考安装点拾取状态失败: {ex.Message}", ex);
            }
        }

        private void CleanupAssemblyEndFaceSelection(bool clearVisuals)
        {
            try
            {
                _isSelectingAssemblyEndFacePoints = false;
                _pathPlanningManager?.EnableMouseHandling();
                _pathPlanningManager?.StopClickTool();
                if (clearVisuals)
                {
                    _assemblyEndFaceSeedPoints.Clear();
                    ClearAssemblyEndFaceAnalysisVisuals();
                    ResetAssemblyEndFaceAnalysisState();
                }
                NotifyRailAssemblyCommandStateChanged();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[直线装配] 清理端面三点拾取状态失败: {ex.Message}", ex);
            }
        }

        private bool IsPickOnAssemblyTerminalObject(PickItemResult pickResult)
        {
            if (pickResult?.ModelItem == null || _assemblyTerminalObject == null)
            {
                return false;
            }

            if (ModelItemAnalysisHelper.ModelItemEquals(pickResult.ModelItem, _assemblyTerminalObject))
            {
                return true;
            }

            return pickResult.ModelItem.AncestorsAndSelf.Any(ancestor => ModelItemAnalysisHelper.ModelItemEquals(ancestor, _assemblyTerminalObject));
        }

        private async Task ExecuteNewPathAsync()
        {
            await SafeExecuteAsync(() =>
            {
                UpdateMainStatus("正在创建新路径...");

                // 清除所有现有路径的可视化显示
                if (PathPointRenderPlugin.Instance != null)
                {
                    try
                    {
                        PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                        LogManager.Info("新建路径:已清除现有路径可视化显示(保留网格可视化)");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"新建路径:清除现有路径可视化失败: {ex.Message}", ex);
                        throw; // 重新抛出异常,让上层处理
                    }
                }

                if (_pathPlanningManager != null)
                {
                    var newRoute = _pathPlanningManager.StartCreatingNewRoute();

                    if (newRoute != null)
                    {
                        // 创建对应的 WPF ViewModel
                        var newPathViewModel = new PathRouteViewModel
                        {
                            Route = newRoute,
                            IsActive = true
                        };

                        // 使用统一的辅助方法创建路径点
                        var pathPoints = CreatePathPointViewModelsFromCoreRoute(newRoute);
                        foreach (var point in pathPoints)
                        {
                            newPathViewModel.Points.Add(point);
                        }

                        // 添加到 UI 列表并选中
                        PathRoutes.Add(newPathViewModel);
                        SelectedPathRoute = newPathViewModel;

                        // 强制重新初始化ToolPlugin以确保获得鼠标焦点,新建路径需要订阅事件
                        if (!ForceReinitializeToolPlugin(subscribeToEvents: true))
                        {
                            UpdateMainStatus("ToolPlugin初始化失败,请重试");
                            LogManager.Error("新建路径:ToolPlugin初始化失败");
                            return;
                        }

                        UpdateMainStatus($"已进入新建路径模式: {newRoute.Name} - 请在3D视图中点击设置路径点");
                        LogManager.Info($"开始新建路径: {newRoute.Name},已强制重新初始化ToolPlugin获取鼠标焦点");

                        // 不再显示对话框,状态文本已提供足够的反馈
                    }
                    else
                    {
                        UpdateMainStatus("创建新路径失败:没有可通行的物流模型");
                        LogManager.Error("创建新路径失败:没有可通行的物流模型");
                        MessageBox.Show("创建新路径失败:没有找到任何可通行的物流模型。\n请先为模型设置可通行的物流属性,然后再尝试创建路径。", "错误",
                            MessageBoxButton.OK, MessageBoxImage.Warning);
                    }
                }
                else
                {
                    UpdateMainStatus("路径规划管理器未初始化");
                    LogManager.Error("路径规划管理器未初始化");
                }
            }, "新建路径");
        }

        private async Task ExecuteNewRailPathAsync()
        {
            await SafeExecuteAsync(() =>
            {
                UpdateMainStatus("正在创建传统空轨路径...");

                // 检查是否有空轨基准路径
                if (PathPointRenderPlugin.Instance != null)
                {
                    try
                    {
                        // 清除所有现有路径的可视化显示
                        PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                        LogManager.Info("新建传统空轨路径:已清除现有路径可视化显示(保留网格可视化)");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"新建传统空轨路径:清除现有路径可视化失败: {ex.Message}", ex);
                        throw;
                    }
                }

                // 自动提取并显示所有空轨模型的基准线
                ExtractAndRenderRailBaselinePaths();

                if (_pathPlanningManager != null)
                {
                        // 创建传统空轨路径
                    var newRoute = _pathPlanningManager.StartCreatingNewRoute(
                        isRailPath: true,
                        pathType: PathType.Rail);

                    if (newRoute != null)
                    {
                        // 创建对应的 WPF ViewModel
                        var newPathViewModel = new PathRouteViewModel
                        {
                            Route = newRoute,
                            IsActive = true,
                            PathType = PathType.Rail
                        };

                        // 使用统一的辅助方法创建路径点
                        var pathPoints = CreatePathPointViewModelsFromCoreRoute(newRoute);
                        foreach (var point in pathPoints)
                        {
                            newPathViewModel.Points.Add(point);
                        }

                        // 添加到 UI 列表并选中
                        PathRoutes.Add(newPathViewModel);
                        SelectedPathRoute = newPathViewModel;

                        // 强制重新初始化ToolPlugin以确保获得鼠标焦点
                        if (!ForceReinitializeToolPlugin(subscribeToEvents: true))
                        {
                            UpdateMainStatus("ToolPlugin初始化失败,请重试");
                            LogManager.Error("新建传统空轨路径:ToolPlugin初始化失败");
                            return;
                        }

                        // 启动点击工具,设置空轨吸附模式
                        _pathPlanningManager.StartClickTool(PathPointType.WayPoint, enableRailSnapping: true);
                        LogManager.Info($"已启动传统空轨路径点击工具(吸附模式): {newRoute.Name}");

                        UpdateMainStatus($"已进入传统空轨路径模式: {newRoute.Name} - 请在3D视图中点击空轨模型设置路径点(将自动吸附到基准路径)");
                        LogManager.Info($"开始新建传统空轨路径: {newRoute.Name},已强制重新初始化ToolPlugin获取鼠标焦点");
                    }
                    else
                    {
                        UpdateMainStatus("创建传统空轨路径失败:没有可通行的物流模型");
                        LogManager.Error("创建传统空轨路径失败:没有可通行的物流模型");
                        MessageBox.Show("创建传统空轨路径失败:没有找到任何可通行的物流模型。\n请先为模型设置可通行的物流属性,然后再尝试创建路径。", "错误",
                            MessageBoxButton.OK, MessageBoxImage.Warning);
                    }
                }
                else
                {
                    UpdateMainStatus("路径规划管理器未初始化");
                    LogManager.Error("路径规划管理器未初始化");
                }
                        }, "新建传统空轨路径");
                        }

                        /// <summary>
                                /// 执行新建自由路径命令
                                /// </summary>
                                private async Task ExecuteNewFreePathAsync()
                                {
                                    await SafeExecuteAsync(() =>
                                    {
                                        UpdateMainStatus("正在创建自由路径...");

                                        // 清除所有现有路径的可视化显示
                                        if (PathPointRenderPlugin.Instance != null)
                                        {
                                            try
                                            {
                                                PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                                                LogManager.Info("新建自由路径:已清除现有路径可视化显示(保留网格可视化)");
                                            }
                                            catch (Exception ex)
                                            {
                                                LogManager.Error($"新建自由路径:清除现有路径可视化失败: {ex.Message}", ex);
                                                throw;
                                            }
                                        }

                                        if (_pathPlanningManager != null)
                                        {
                                            var newRoute = _pathPlanningManager.StartCreatingNewRoute(
                                                pathType: PathType.Free);

                                            if (newRoute != null)
                                            {
                                                var newPathViewModel = new PathRouteViewModel
                                                {
                                                    Route = newRoute,
                                                    IsActive = true,
                                                    PathType = PathType.Free
                                                };

                                                var pathPoints = CreatePathPointViewModelsFromCoreRoute(newRoute);
                                                foreach (var point in pathPoints)
                                                {
                                                    newPathViewModel.Points.Add(point);
                                                }

                                                PathRoutes.Add(newPathViewModel);
                                                SelectedPathRoute = newPathViewModel;

                                                if (!ForceReinitializeToolPlugin(subscribeToEvents: true))
                                                {
                                                    UpdateMainStatus("ToolPlugin初始化失败,请重试");
                                                    LogManager.Error("新建自由路径:ToolPlugin初始化失败");
                                                    return;
                                                }

                                                // 与地面路径一致：不调用 StartClickTool（会设成 AddingPoints 走预览点分支），
                                                // 保持 Creating 状态，点击走 AddPathPointIn3D 正常保存路径点并渲染连线
                                                LogManager.Info($"已进入自由路径点击模式: {newRoute.Name}");

                                                UpdateMainStatus($"已进入自由路径模式: {newRoute.Name} - 请在3D视图中连续点击设置物体中心轨迹点，最后设为终点完成");
                                                LogManager.Info($"开始新建自由路径: {newRoute.Name}");
                                            }
                                            else
                                            {
                                                UpdateMainStatus("创建自由路径失败");
                                                LogManager.Error("创建自由路径失败");
                                            }
                                        }
                                        else
                                        {
                                            UpdateMainStatus("路径规划管理器未初始化");
                                            LogManager.Error("路径规划管理器未初始化");
                                        }
                                    }, "新建自由路径");
                                }

                                /// <summary>
                                /// 执行新建吊装路径命令
                                /// </summary>
                                private async Task ExecuteNewHoistingPathAsync()
                                {
                                    await SafeExecuteAsync(() =>
                                    {
                                        UpdateMainStatus("正在创建新吊装路径...");

                                        // 清除所有现有路径的可视化显示
                                        if (PathPointRenderPlugin.Instance != null)
                                        {
                                            try
                                            {
                                                PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                                                LogManager.Info("新建吊装路径:已清除现有路径可视化显示(保留网格可视化)");
                                            }
                                            catch (Exception ex)
                                            {
                                                LogManager.Error($"新建吊装路径:清除现有路径可视化失败: {ex.Message}", ex);
                                                throw;
                                            }
                                        }

                                        if (_pathPlanningManager != null)
                                        {
                                            // 创建吊装路径
                                            var newRoute = _pathPlanningManager.StartCreatingNewRoute(
                                                isRailPath: false,
                                                pathType: PathType.Hoisting);

                                            if (newRoute != null)
                                            {
                                                // 创建对应的 WPF ViewModel
                                                var newPathViewModel = new PathRouteViewModel
                                                {
                                                    Route = newRoute,
                                                    IsActive = true,
                                                    PathType = PathType.Hoisting
                                                };

                                                // 使用统一的辅助方法创建路径点
                                                var pathPoints = CreatePathPointViewModelsFromCoreRoute(newRoute);
                                                foreach (var point in pathPoints)
                                                {
                                                    newPathViewModel.Points.Add(point);
                                                }

                                                // 添加到 UI 列表并选中
                                                PathRoutes.Add(newPathViewModel);
                                                SelectedPathRoute = newPathViewModel;

                                                // 强制重新初始化ToolPlugin以确保获得鼠标焦点
                                                if (!ForceReinitializeToolPlugin(subscribeToEvents: true))
                                                {
                                                    UpdateMainStatus("ToolPlugin初始化失败,请重试");
                                                    LogManager.Error("新建吊装路径:ToolPlugin初始化失败");
                                                    return;
                                                }

                                                // 启动点击工具,启用吊装模式
                                                _pathPlanningManager.StartClickTool(PathPointType.WayPoint, enableRailSnapping: false, enableHoistingMode: true);
                                                LogManager.Info($"已启动吊装路径点击工具: {newRoute.Name}");

                                                UpdateMainStatus($"已进入新建吊装路径模式: {newRoute.Name} - 请在3D视图中点击吊装起点(地面位置)");
                                                LogManager.Info($"开始新建吊装路径: {newRoute.Name},已强制重新初始化ToolPlugin获取鼠标焦点");
                                            }
                                            else
                                            {
                                                UpdateMainStatus("创建新吊装路径失败:没有可通行的物流模型");
                                                LogManager.Error("创建新吊装路径失败:没有可通行的物流模型");
                                                MessageBox.Show("创建新吊装路径失败:没有找到任何可通行的物流模型。\n请先为模型设置可通行的物流属性,然后再尝试创建路径。", "错误",
                                                    MessageBoxButton.OK, MessageBoxImage.Warning);
                                            }
                                        }
                                        else
                                        {
                                            UpdateMainStatus("路径规划管理器未初始化");
                                            LogManager.Error("路径规划管理器未初始化");
                                        }
                                    }, "新建吊装路径");
                                }

                                #region 多层吊装页签模式实现

                                /// <summary>
                                /// 执行新建多层阶梯式吊装路径命令 - 启用页签模式
                                /// </summary>
                                private async Task ExecuteNewMultiLevelHoistingPathAsync()
                                {
                                    await SafeExecuteAsync(() =>
                                    {
                                        UpdateMainStatus("正在创建多层阶梯式吊装路径...");

                                        // 清除所有现有路径的可视化显示
                                        if (PathPointRenderPlugin.Instance != null)
                                        {
                                            try
                                            {
                                                PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                                                LogManager.Info("新建多层吊装路径:已清除现有路径可视化显示(保留网格可视化)");
                                            }
                                            catch (Exception ex)
                                            {
                                                LogManager.Error($"新建多层吊装路径:清除现有路径可视化失败: {ex.Message}", ex);
                                                throw;
                                            }
                                        }

                                        if (_pathPlanningManager == null)
                                        {
                                            UpdateMainStatus("路径规划管理器未初始化");
                                            LogManager.Error("路径规划管理器未初始化");
                                            return;
                                        }

                                        // 启用多层吊装页签模式
                                        IsMultiLevelHoistingMode = true;

                                        // 清空集合和重置状态
                                        MultiLevelItems.Clear();
                                        _multiLevelStartPoint = null;
                                        _multiLevelEndPoint = null;
                                        _hasMultiLevelStartPoint = false;
                                        _hasMultiLevelEndPoint = false;
                                        MultiLevelStartPointText = "未选择";
                                        MultiLevelEndPointText = "未选择";
                                        UpdateMultiLevelStats();

                                        // 重置选择状态
                                        _isSelectingMultiLevelStartPoint = false;
                                        _isSelectingMultiLevelEndPoint = false;
                                        _currentSelectingLevelTarget = null;

                                        // 清理之前的点击事件订阅
                                        PathClickToolPlugin.MouseClicked -= OnMultiLevelHoistingMouseClicked;

                                        UpdateMainStatus("多层吊装模式已启用 - 请设置起点、终点并添加层级");
                                        LogManager.Info("[多层吊装] 页签模式已启用");

                                    }, "新建多层吊装路径");
                                }

                                /// <summary>
                                /// 执行选择多层吊装起点命令
                                /// </summary>
                                private async Task ExecuteSelectMultiLevelStartPointAsync()
                                {
                                    await SafeExecuteAsync(() =>
                                    {
                                        if (_pathPlanningManager == null) return;

                                        // 清除之前的起点标记
                                        if (_hasMultiLevelStartPoint && PathPointRenderPlugin.Instance != null)
                                        {
                                            var existingRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == "MultiLevelStartPoint");
                                            if (existingRoute != null)
                                            {
                                                PathPointRenderPlugin.Instance.RemovePath(existingRoute.Route.Id);
                                            }
                                        }

                                        // 使用自动路径规划相同的模式
                                        _pathPlanningManager.DisableMouseHandling();

                                        // 设置状态
                                        _isSelectingMultiLevelStartPoint = true;
                                        _isSelectingMultiLevelEndPoint = false;
                                        _currentSelectingLevelTarget = null;

                                        // 订阅点击事件
                                        PathClickToolPlugin.MouseClicked -= OnMultiLevelHoistingMouseClicked;
                                        PathClickToolPlugin.MouseClicked += OnMultiLevelHoistingMouseClicked;

                                        // 强制重新初始化ToolPlugin以获取鼠标焦点
                                        ForceReinitializeToolPlugin(subscribeToEvents: false);

                                        UpdateMainStatus("请在3D视图中点击选择起点(地面起吊位置)...");
                                        LogManager.Info("[多层吊装] 开始选择起点");
                                    }, "选择多层吊装起点");
                                }

                                /// <summary>
                                /// 执行选择多层吊装终点命令
                                /// </summary>
                                private async Task ExecuteSelectMultiLevelEndPointAsync()
                                {
                                    await SafeExecuteAsync(() =>
                                    {
                                        if (_pathPlanningManager == null) return;

                                        // 清除之前的终点标记
                                        if (_hasMultiLevelEndPoint && PathPointRenderPlugin.Instance != null)
                                        {
                                            var existingRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == "MultiLevelEndPoint");
                                            if (existingRoute != null)
                                            {
                                                PathPointRenderPlugin.Instance.RemovePath(existingRoute.Route.Id);
                                            }
                                        }

                                        // 使用自动路径规划相同的模式
                                        _pathPlanningManager.DisableMouseHandling();

                                        // 设置状态
                                        _isSelectingMultiLevelStartPoint = false;
                                        _isSelectingMultiLevelEndPoint = true;
                                        _currentSelectingLevelTarget = null;

                                        // 订阅点击事件
                                        PathClickToolPlugin.MouseClicked -= OnMultiLevelHoistingMouseClicked;
                                        PathClickToolPlugin.MouseClicked += OnMultiLevelHoistingMouseClicked;

                                        // 强制重新初始化ToolPlugin以获取鼠标焦点
                                        ForceReinitializeToolPlugin(subscribeToEvents: false);

                                        UpdateMainStatus("请在3D视图中点击选择终点(地面落地位置)...");
                                        LogManager.Info("[多层吊装] 开始选择终点");
                                    }, "选择多层吊装终点");
                                }

                                /// <summary>
                                /// 执行添加层级命令
                                /// </summary>
                                private void ExecuteAddMultiLevel()
                                {
                                    var level = new HoistingLevelItem
                                    {
                                        Index = MultiLevelItems.Count,
                                        HeightInMeters = 3.0,
                                        Description = $"层级{MultiLevelItems.Count + 1}"
                                    };
                                    MultiLevelItems.Add(level);
                                    UpdateMultiLevelStats();

                                    LogManager.Info($"[多层吊装] 添加层级{level.Index + 1}, 高度={level.HeightInMeters}m");
                                    UpdateMainStatus($"已添加层级{level.Index + 1},请设置目标位置");
                                }

                                /// <summary>
                                /// 执行删除层级命令
                                /// </summary>
                                private void ExecuteDeleteMultiLevel(HoistingLevelItem item)
                                {
                                    if (item == null) return;

                                    // 清除该层级的可视化标记
                                    if (PathPointRenderPlugin.Instance != null)
                                    {
                                        var existingRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == $"MultiLevelLevel{item.Index}");
                                        if (existingRoute != null)
                                        {
                                            PathPointRenderPlugin.Instance.RemovePath(existingRoute.Route.Id);
                                        }
                                    }

                                    MultiLevelItems.Remove(item);

                                    // 重新编号
                                    for (int i = 0; i < MultiLevelItems.Count; i++)
                                    {
                                        MultiLevelItems[i].Index = i;
                                    }

                                    UpdateMultiLevelStats();
                                    LogManager.Info($"[多层吊装] 删除层级,剩余{MultiLevelItems.Count}个层级");
                                }

                                /// <summary>
                                /// 执行拾取层级目标位置命令
                                /// </summary>
                                private void ExecutePickMultiLevelTarget(HoistingLevelItem item)
                                {
                                    if (item == null || _pathPlanningManager == null) return;

                                    // 清除之前的标记
                                    if (PathPointRenderPlugin.Instance != null)
                                    {
                                        var existingRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == $"MultiLevelLevel{item.Index}");
                                        if (existingRoute != null)
                                        {
                                            PathPointRenderPlugin.Instance.RemovePath(existingRoute.Route.Id);
                                        }
                                    }

                                    // 使用自动路径规划相同的模式
                                    _pathPlanningManager.DisableMouseHandling();

                                    // 设置状态
                                    _isSelectingMultiLevelStartPoint = false;
                                    _isSelectingMultiLevelEndPoint = false;
                                    _currentSelectingLevelTarget = item;

                                    // 订阅点击事件
                                    PathClickToolPlugin.MouseClicked -= OnMultiLevelHoistingMouseClicked;
                                    PathClickToolPlugin.MouseClicked += OnMultiLevelHoistingMouseClicked;

                                    // 强制重新初始化ToolPlugin以获取鼠标焦点
                                    ForceReinitializeToolPlugin(subscribeToEvents: false);

                                    UpdateMainStatus($"请在3D视图中点击层级{item.Index + 1}的目标位置...");
                                    LogManager.Info($"[多层吊装] 开始选择层级{item.Index + 1}的目标位置");
                                }

                                /// <summary>
                                /// 执行创建多层吊装路径命令
                                /// </summary>
                                private async Task ExecuteCreateMultiLevelPathAsync()
                                {
                                    await SafeExecuteAsync(() =>
                                    {
                                        // 验证输入
                                        if (!_hasMultiLevelStartPoint)
                                        {
                                            MessageBox.Show("请先选择起点", "验证失败", MessageBoxButton.OK, MessageBoxImage.Warning);
                                            return;
                                        }

                                        if (!_hasMultiLevelEndPoint)
                                        {
                                            MessageBox.Show("请先选择终点", "验证失败", MessageBoxButton.OK, MessageBoxImage.Warning);
                                            return;
                                        }

                                        if (MultiLevelItems.Count == 0)
                                        {
                                            MessageBox.Show("请至少添加一个层级", "验证失败", MessageBoxButton.OK, MessageBoxImage.Warning);
                                            return;
                                        }

                                        // 验证所有层级
                                        foreach (var level in MultiLevelItems)
                                        {
                                            if (level.HeightInMeters <= 0)
                                            {
                                                MessageBox.Show($"层级{level.Index + 1}的高度必须大于0", "验证失败",
                                                    MessageBoxButton.OK, MessageBoxImage.Warning);
                                                return;
                                            }

                                            if (level.HorizontalTarget == null)
                                            {
                                                MessageBox.Show($"请为层级{level.Index + 1}设置目标位置", "验证失败",
                                                    MessageBoxButton.OK, MessageBoxImage.Warning);
                                                return;
                                            }
                                        }

                                        // 创建层级列表
                                        var levels = new List<HoistingLevel>();
                                        foreach (var item in MultiLevelItems)
                                        {
                                            levels.Add(new HoistingLevel
                                            {
                                                Index = item.Index,
                                                HeightInMeters = item.HeightInMeters,
                                                HorizontalTarget = item.HorizontalTarget,
                                                IsRise = true,
                                                Description = item.Description
                                            });
                                        }

                                        LogManager.Info($"[多层吊装] 创建路径:起点({_multiLevelStartPoint.X:F2},{_multiLevelStartPoint.Y:F2},{_multiLevelStartPoint.Z:F2}), " +
                                                       $"终点({_multiLevelEndPoint.X:F2},{_multiLevelEndPoint.Y:F2},{_multiLevelEndPoint.Z:F2}), 层级数={levels.Count}");

                                        // 使用命令创建路径
                                        var parameters = new AerialPathParameters
                                        {
                                            PathType = PathType.Hoisting,
                                            HoistingMode = HoistingMode.MultiLevel,
                                            StartPoint = _multiLevelStartPoint,
                                            EndPoint = _multiLevelEndPoint,
                                            HoistingLevels = levels
                                        };

                                        var command = new CreateAerialPathCommand(parameters);
                                        var result = command.ExecuteAsync().Result;

                                        if (result.IsSuccess && result is PathPlanningResult<PathRoute> typedResult)
                                        {
                                            var route = typedResult.Data;
                                            LogManager.Info($"[多层吊装] 路径创建成功: {route.Name}, 点数: {route.Points.Count}");

                                            // 创建 ViewModel
                                            var newPathViewModel = new PathRouteViewModel
                                            {
                                                Route = route,
                                                IsActive = true,
                                                PathType = PathType.Hoisting
                                            };

                                            var pathPoints = CreatePathPointViewModelsFromCoreRoute(route);
                                            foreach (var point in pathPoints)
                                            {
                                                newPathViewModel.Points.Add(point);
                                            }

                                            PathRoutes.Add(newPathViewModel);
                                            SelectedPathRoute = newPathViewModel;

                                            UpdateMainStatus($"✓ 多层吊装路径创建成功: {route.Name} - {levels.Count}个层级, {route.Points.Count}个路径点");
                                            OnPropertyChanged(nameof(PathRoutes));

                                            // 退出多层吊装模式
                                            ExecuteCancelMultiLevelHoisting();
                                        }
                                        else
                                        {
                                            UpdateMainStatus($"创建失败: {result.Message}");
                                            MessageBox.Show($"创建多层吊装路径失败: {result.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                                        }
                                    }, "创建多层吊装路径");
                                }

                                /// <summary>
                                /// 执行取消多层吊装命令
                                /// </summary>
                                private void ExecuteCancelMultiLevelHoisting()
                                {
                                    // 清理事件订阅
                                    PathClickToolPlugin.MouseClicked -= OnMultiLevelHoistingMouseClicked;

                                    // 清理可视化标记
                                    if (PathPointRenderPlugin.Instance != null)
                                    {
                                        // 清理起点标记
                                        var startRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == "MultiLevelStartPoint");
                                        if (startRoute != null)
                                        {
                                            PathPointRenderPlugin.Instance.RemovePath(startRoute.Route.Id);
                                        }

                                        // 清理终点标记
                                        var endRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == "MultiLevelEndPoint");
                                        if (endRoute != null)
                                        {
                                            PathPointRenderPlugin.Instance.RemovePath(endRoute.Route.Id);
                                        }

                                        // 清理层级标记
                                        for (int i = 0; i < MultiLevelItems.Count; i++)
                                        {
                                            var levelRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == $"MultiLevelLevel{i}");
                                            if (levelRoute != null)
                                            {
                                                PathPointRenderPlugin.Instance.RemovePath(levelRoute.Route.Id);
                                            }
                                        }
                                    }

                                    // 重置状态
                                    IsMultiLevelHoistingMode = false;
                                    MultiLevelItems.Clear();
                                    _multiLevelStartPoint = null;
                                    _multiLevelEndPoint = null;
                                    _hasMultiLevelStartPoint = false;
                                    _hasMultiLevelEndPoint = false;
                                    MultiLevelStartPointText = "未选择";
                                    MultiLevelEndPointText = "未选择";
                                    _isSelectingMultiLevelStartPoint = false;
                                    _isSelectingMultiLevelEndPoint = false;
                                    _currentSelectingLevelTarget = null;

                                    // 恢复PathPlanningManager鼠标处理
                                    _pathPlanningManager?.EnableMouseHandling();
                                    _pathPlanningManager?.StopClickTool();

                                    UpdateMultiLevelStats();
                                    UpdateMainStatus("多层吊装模式已取消");
                                    LogManager.Info("[多层吊装] 页签模式已取消");
                                }

                                /// <summary>
                                /// 更新多层吊装统计信息
                                /// </summary>
                                private void UpdateMultiLevelStats()
                                {
                                    int levelCount = MultiLevelItems.Count;
                                    int pointCount = levelCount > 0 ? 2 + levelCount * 2 + 2 : 0;
                                    MultiLevelStatsText = $"层级数: {levelCount} | 预估路径点数: {pointCount}";

                                    // 通知CanCreateMultiLevelPath变更
                                    OnPropertyChanged(nameof(CanCreateMultiLevelPath));

                                    // 通知命令可执行状态变更
                                    System.Windows.Input.CommandManager.InvalidateRequerySuggested();
                                }

                                /// <summary>
                                /// 多层吊装路径鼠标点击处理
                                /// </summary>
                                private void OnMultiLevelHoistingMouseClicked(object sender, PickItemResult e)
                                {
                                    if (e?.Point == null) return;

                                    var point = e.Point;

                                    if (_isSelectingMultiLevelStartPoint)
                                    {
                                        // 设置起点
                                        _multiLevelStartPoint = point;
                                        _hasMultiLevelStartPoint = true;
                                        MultiLevelStartPointText = $"({point.X:F2}, {point.Y:F2}, {point.Z:F2})";

                                        // 渲染起点标记
                                        RenderMultiLevelPointMarker(point, isStart: true);

                                        LogManager.Info($"[多层吊装] 起点已设置: ({point.X:F2}, {point.Y:F2}, {point.Z:F2})");
                                        UpdateMainStatus($"起点已设置,请选择终点或添加层级");

                                        // 清理事件订阅并停用ToolPlugin
                                        PathClickToolPlugin.MouseClicked -= OnMultiLevelHoistingMouseClicked;
                                        _pathPlanningManager?.EnableMouseHandling();
                                        _pathPlanningManager?.StopClickTool();
                                        _isSelectingMultiLevelStartPoint = false;

                                        // 更新统计
                                        UpdateMultiLevelStats();
                                    }
                                    else if (_isSelectingMultiLevelEndPoint)
                                    {
                                        // 设置终点
                                        _multiLevelEndPoint = point;
                                        _hasMultiLevelEndPoint = true;
                                        MultiLevelEndPointText = $"({point.X:F2}, {point.Y:F2}, {point.Z:F2})";

                                        // 渲染终点标记
                                        RenderMultiLevelPointMarker(point, isStart: false);

                                        LogManager.Info($"[多层吊装] 终点已设置: ({point.X:F2}, {point.Y:F2}, {point.Z:F2})");
                                        UpdateMainStatus($"终点已设置,可以添加层级创建路径");

                                        // 清理事件订阅并停用ToolPlugin
                                        PathClickToolPlugin.MouseClicked -= OnMultiLevelHoistingMouseClicked;
                                        _pathPlanningManager?.EnableMouseHandling();
                                        _pathPlanningManager?.StopClickTool();
                                        _isSelectingMultiLevelEndPoint = false;

                                        // 更新统计
                                        UpdateMultiLevelStats();
                                    }
                                    else if (_currentSelectingLevelTarget != null)
                                    {
                                        // 设置层级目标位置
                                        var targetPoint = new Point3D(point.X, point.Y, point.Z);
                                        _currentSelectingLevelTarget.HorizontalTarget = targetPoint;

                                        // 渲染层级目标标记
                                        RenderMultiLevelLevelMarker(targetPoint, _currentSelectingLevelTarget.Index);

                                        LogManager.Info($"[多层吊装] 层级{_currentSelectingLevelTarget.Index + 1}目标位置已设置: ({point.X:F2}, {point.Y:F2})");
                                        UpdateMainStatus($"层级{_currentSelectingLevelTarget.Index + 1}目标位置已设置,可以继续添加层级或点击创建路径");

                                        // 清理事件订阅并停用ToolPlugin
                                        PathClickToolPlugin.MouseClicked -= OnMultiLevelHoistingMouseClicked;
                                        _pathPlanningManager?.EnableMouseHandling();
                                        _pathPlanningManager?.StopClickTool();
                                        _currentSelectingLevelTarget = null;
                                    }
                                }

                                /// <summary>
                                /// 渲染层级目标位置标记
                                /// </summary>
                                private void RenderMultiLevelLevelMarker(Point3D point, int levelIndex)
                                {
                                    if (PathPointRenderPlugin.Instance == null) return;

                                    var routeName = $"MultiLevelLevel{levelIndex}";

                                    // 移除之前的标记
                                    var existingRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == routeName);
                                    if (existingRoute != null)
                                    {
                                        PathPointRenderPlugin.Instance.RemovePath(existingRoute.Route.Id);
                                    }

                                    // 创建临时路径
                                    var route = new PathRoute(routeName)
                                    {
                                        Description = $"层级{levelIndex + 1}目标位置"
                                    };
                                    var pathPoint = new PathPoint
                                    {
                                        Name = $"层级{levelIndex + 1}",
                                        Position = point,
                                        Type = PathPointType.WayPoint
                                    };
                                    route.AddPoint(pathPoint);

                                    // 渲染点(使用不同颜色区分层级)
                                    PathPointRenderPlugin.Instance.RenderPointOnly(route);
                                    LogManager.Info($"[多层吊装] 层级{levelIndex + 1}目标标记已渲染");
                                }

                                /// <summary>
                                /// 渲染多层吊装路径的点标记
                                /// </summary>
                                private void RenderMultiLevelPointMarker(Point3D point, bool isStart)
                                {
                                    if (PathPointRenderPlugin.Instance == null) return;

                                    var routeName = isStart ? "MultiLevelStartPoint" : "MultiLevelEndPoint";
                                    var displayName = isStart ? "多层吊装起点" : "多层吊装终点";
                                    var pointType = isStart ? PathPointType.StartPoint : PathPointType.EndPoint;

                                    // 移除之前的标记
                                    var existingRoute = PathRoutes.FirstOrDefault(r => r.Route.Name == routeName);
                                    if (existingRoute != null)
                                    {
                                        PathPointRenderPlugin.Instance.RemovePath(existingRoute.Route.Id);
                                    }

                                    // 创建临时路径
                                    var route = new PathRoute(routeName)
                                    {
                                        Description = displayName
                                    };
                                    var pathPoint = new PathPoint
                                    {
                                        Name = displayName,
                                        Position = point,
                                        Type = pointType
                                    };
                                    route.AddPoint(pathPoint);

                                    // 渲染点
                                    PathPointRenderPlugin.Instance.RenderPointOnly(route);
                                }

                                #endregion

        /// <summary>
        /// 提取并渲染所有空轨模型的基准路径
        /// </summary>
        private void ExtractAndRenderRailBaselinePaths()
        {
            try
            {
                LogManager.Info("[空轨路径] 开始提取所有空轨模型的基准路径");
                int successCount = PathPlanning.RailGeometryHelper.ExtractAndRenderAllRailBaselines();
                LogManager.Info($"[空轨路径] 空轨基准路径提取完成,成功 {successCount} 个");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[空轨路径] 提取空轨基准路径失败: {ex.Message}");
            }
        }

        private async Task ExecuteDeletePathAsync()
        {
            if (SelectedPathRoute == null) return;

            await SafeExecuteAsync(() =>
            {
                var pathName = SelectedPathRoute.Name;
                UpdateMainStatus($"正在删除路径: {pathName}...");

                // 清理当前路径的3D可视化显示(使用新的统一API)
                if (PathPointRenderPlugin.Instance != null)
                {
                    try
                    {
                        // 使用路径名找到对应的Core路径,获取其ID进行精确清理
                        string pathIdToRemove = null;
                        if (_pathPlanningManager != null)
                        {
                            var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Name == pathName);
                            if (coreRoute != null)
                            {
                                pathIdToRemove = coreRoute.Id;
                                LogManager.Info($"删除路径:找到Core路径ID: {pathIdToRemove}");

                                // 使用新的API精确删除该路径
                                PathPointRenderPlugin.Instance.RemovePath(pathIdToRemove);
                                LogManager.Info($"删除路径:已清除路径 {pathName} (ID: {pathIdToRemove}) 的可视化显示");
                            }
                            else
                            {
                                LogManager.Warning($"删除路径:未找到路径 {pathName} 对应的Core路径,无法清理可视化");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"删除路径:清除路径可视化失败: {ex.Message}", ex);
                        throw; // 重新抛出异常,让上层处理
                    }
                }

                // 通知PathPlanningManager删除对应的路径(包括数据库删除)
                if (_pathPlanningManager != null)
                {
                    var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Name == pathName);
                    if (coreRoute != null)
                    {
                        // 使用PathPlanningManager的DeleteRoute方法,确保数据库也被删除
                        bool deleteSuccess = _pathPlanningManager.DeleteRoute(coreRoute);
                        if (deleteSuccess)
                        {
                            LogManager.Info($"删除路径:已从PathPlanningManager和数据库删除路径: {pathName}");
                        }
                        else
                        {
                            LogManager.Warning($"删除路径:PathPlanningManager删除失败: {pathName}");
                        }
                    }
                }

                // 更新UI
                PathRoutes.Remove(SelectedPathRoute);
                SelectedPathRoute = null;
                UpdateMainStatus($"已完全删除路径: {pathName}");
            }, "删除路径");
        }

        private async Task ExecuteDuplicatePathAsync()
        {
            if (SelectedPathRoute == null || _pathPlanningManager == null) return;

            await SafeExecuteAsync(async () =>
            {
                var sourceRoute = SelectedPathRoute.Route ??
                                  _pathPlanningManager.Routes.FirstOrDefault(r => r.Id == SelectedPathRoute.Id);
                if (sourceRoute == null)
                {
                    throw new InvalidOperationException("未找到要复制的路径数据");
                }

                UpdateMainStatus($"正在复制路径: {sourceRoute.Name}...");

                var duplicatedRoute = sourceRoute.Clone();
                duplicatedRoute.Name = PathHelper.BuildDuplicatedPathName(sourceRoute.Name);
                duplicatedRoute.CreatedTime = DateTime.Now;
                duplicatedRoute.LastModified = DateTime.Now;

                if (!_pathPlanningManager.AddRoute(duplicatedRoute))
                {
                    throw new InvalidOperationException($"复制路径失败: {sourceRoute.Name}");
                }

                var duplicatedPathViewModel = new PathRouteViewModel(isFromDatabase: true)
                {
                    Route = duplicatedRoute,
                    IsActive = false
                };
                duplicatedPathViewModel.SetTimeInfo(duplicatedRoute.CreatedTime, duplicatedRoute.LastModified);

                foreach (var point in CreatePathPointViewModelsFromCoreRoute(duplicatedRoute))
                {
                    duplicatedPathViewModel.Points.Add(point);
                }

                PathRoutes.Add(duplicatedPathViewModel);
                SelectedPathRoute = duplicatedPathViewModel;
                UpdateMainStatus($"已复制路径: {sourceRoute.Name} -> {duplicatedPathViewModel.Name}");

                await Task.CompletedTask;
            }, "复制路径");
        }

        #endregion

        #region 坐标编辑命令

        private void ExecuteEditPointCoordinates(PathPointViewModel point)
        {
            if (point == null) return;

            try
            {
                // 创建并显示对话框
                // 注意:在Navisworks插件的ViewModel中,不设置Owner
                // 因为Application.Current.MainWindow在Navisworks环境中不可用
                var dialog = new EditCoordinatesWindow(point.X, point.Y, point.Z, point.Name, point.Type.ToString());

                if (dialog.ShowDialog() == true)
                {
                    // 同步更新到底层数据模型
                    if (_pathPlanningManager != null)
                    {
                        var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Id == SelectedPathRoute.Id);
                        if (coreRoute != null)
                        {
                            // 🔥 通过Id查找路径点索引(而不是使用可能过时的point.Index)
                            int pointIndex = -1;
                            for (int i = 0; i < coreRoute.Points.Count; i++)
                            {
                                if (coreRoute.Points[i].Id == point.Id)
                                {
                                    pointIndex = i;
                                    break;
                                }
                            }

                            // 验证索引是否有效
                            if (pointIndex < 0 || pointIndex >= coreRoute.Points.Count)
                            {
                                LogManager.Error($"[坐标编辑] 索引错误: 通过Id查找失败,point.Id={point.Id}, coreRoute.Points.Count={coreRoute.Points.Count}");
                                System.Windows.MessageBox.Show($"路径点索引错误:无法找到对应的路径点,请刷新路径列表后重试", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                                return;
                            }

                            LogManager.Info($"[坐标编辑] 修改点: {point.Name}, 类型: {point.Type}, 索引: {pointIndex}");

                            var corePoint = coreRoute.Points[pointIndex];
                            LogManager.Info($"[坐标编辑] Core路径点: {corePoint.Name}, 索引: {pointIndex}, 位置: ({corePoint.Position.X:F3}, {corePoint.Position.Y:F3}, {corePoint.Position.Z:F3})");

                            // 使用公共方法更新路径点(自动处理吊装路径约束)
                            var newPosition = new Point3D(dialog.X, dialog.Y, dialog.Z);
                            bool success = _pathPlanningManager.UpdatePathPointWithConstraints(coreRoute, pointIndex, newPosition);

                            if (success)
                            {
                                // 更新ViewModel中的坐标(从Core数据同步)
                                corePoint = coreRoute.Points[pointIndex];
                                point.X = corePoint.Position.X;
                                point.Y = corePoint.Position.Y;
                                point.Z = corePoint.Position.Z;

                                // 刷新视图
                                UpdatePathVisualization();

                                LogManager.Info($"已更新路径点 {point.Name} 的坐标为 ({point.X:F3}, {point.Y:F3}, {point.Z:F3})");
                            }
                            else
                            {
                                LogManager.Error($"更新路径点失败: {point.Name}");
                                System.Windows.MessageBox.Show($"更新路径点失败", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"编辑坐标对话框操作失败: {ex.Message}", ex);
                System.Windows.MessageBox.Show($"无法打开编辑对话框: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 从Core路径创建PathPointViewModel列表(统一处理吊装路径属性)
        /// </summary>
        private List<PathPointViewModel> CreatePathPointViewModelsFromCoreRoute(PathRoute coreRoute)
        {
            var points = new List<PathPointViewModel>();

            for (int i = 0; i < coreRoute.Points.Count; i++)
            {
                var corePoint = coreRoute.Points[i];
                var wpfPoint = new PathPointViewModel
                {
                    Id = corePoint.Id,
                    Name = corePoint.Name,
                    X = corePoint.X,
                    Y = corePoint.Y,
                    Z = corePoint.Z,
                    Type = corePoint.Type,
                    Index = i  // 🔥 设置正确的索引
                };
                points.Add(wpfPoint);
            }

            return points;
        }

        private bool SyncPathViewModelFromCoreRoute(PathRouteViewModel pathViewModel, PathRoute coreRoute, bool preserveSelection = true)
        {
            if (pathViewModel == null || coreRoute == null)
            {
                return false;
            }

            bool needsUpdate = !ReferenceEquals(pathViewModel.Route, coreRoute) ||
                               pathViewModel.Points.Count != coreRoute.Points.Count;

            if (!needsUpdate && pathViewModel.Points.Count == coreRoute.Points.Count)
            {
                for (int i = 0; i < pathViewModel.Points.Count; i++)
                {
                    var uiPoint = pathViewModel.Points[i];
                    var corePoint = coreRoute.Points[i];

                    if (uiPoint.Id != corePoint.Id ||
                        uiPoint.Name != corePoint.Name ||
                        uiPoint.Type != corePoint.Type)
                    {
                        needsUpdate = true;
                        break;
                    }

                    const double tolerance = 1e-6;
                    if (Math.Abs(uiPoint.X - corePoint.Position.X) > tolerance ||
                        Math.Abs(uiPoint.Y - corePoint.Position.Y) > tolerance ||
                        Math.Abs(uiPoint.Z - corePoint.Position.Z) > tolerance)
                    {
                        needsUpdate = true;
                        break;
                    }
                }
            }

            pathViewModel.Route = coreRoute;
            pathViewModel.SetTimeInfo(coreRoute.CreatedTime, coreRoute.LastModified);

            if (!needsUpdate)
            {
                pathViewModel.NotifyPropertyChanged(nameof(PathRouteViewModel.TotalLength));
                pathViewModel.NotifyPropertyChanged(nameof(PathRouteViewModel.LastModifiedTime));
                return false;
            }

            string selectedPointId = preserveSelection ? SelectedPathPoint?.Id : null;
            bool hadSelection = !string.IsNullOrEmpty(selectedPointId);
            PathPointViewModel newSelectedPoint = null;

            pathViewModel.Points.Clear();
            foreach (var pointViewModel in CreatePathPointViewModelsFromCoreRoute(coreRoute))
            {
                pathViewModel.Points.Add(pointViewModel);
                if (hadSelection && pointViewModel.Id == selectedPointId)
                {
                    newSelectedPoint = pointViewModel;
                }
            }

            pathViewModel.NotifyPropertyChanged(nameof(PathRouteViewModel.PointCount));
            pathViewModel.NotifyPropertyChanged(nameof(PathRouteViewModel.TotalLength));
            pathViewModel.NotifyPropertyChanged(nameof(PathRouteViewModel.SummaryInfo));
            pathViewModel.NotifyPropertyChanged(nameof(PathRouteViewModel.LastModifiedTime));

            if (hadSelection)
            {
                SelectedPathPoint = newSelectedPoint;
            }

            return true;
        }

        private void RefreshHoistingLayerEditItemsFromSelectedRoute()
        {
            HoistingLayerEditItems.Clear();

            var coreRoute = GetSelectedCoreRoute();
            if (coreRoute == null || coreRoute.PathType != PathType.Hoisting || coreRoute.Points == null || coreRoute.Points.Count < 2)
            {
                HoistingLayerEditHintText = "选择一条吊装路径后,可在这里按层编辑相对起点的绝对高度。";
                OnPropertyChanged(nameof(CanApplyHoistingLayerHeights));
                return;
            }

            HostCoordinateAdapter hostAdapter = CoordinateSystemManager.Instance.CreateHostAdapter();
            PathPoint hostStartPoint = coreRoute.Points.FirstOrDefault(point => point.Type == PathPointType.StartPoint) ?? coreRoute.Points.First();
            double hostStartElevation = HoistingCoordinateHelper.GetElevation(hostStartPoint.Position, hostAdapter);
            const double relativeHeightToleranceInMeters = 0.001;

            var layerItems = new List<HoistingLayerEditItem>();
            foreach (var point in coreRoute.Points)
            {
                if (point == null || point.Type == PathPointType.StartPoint || point.Type == PathPointType.EndPoint)
                {
                    continue;
                }

                double hostPointElevation = HoistingCoordinateHelper.GetElevation(point.Position, hostAdapter);
                double relativeHeightInMeters = UnitsConverter.ConvertToMeters(hostPointElevation - hostStartElevation);
                if (relativeHeightInMeters <= relativeHeightToleranceInMeters)
                {
                    continue;
                }

                HoistingLayerEditItem existingLayer = layerItems.FirstOrDefault(item =>
                    Math.Abs(item.HeightInMeters - relativeHeightInMeters) <= relativeHeightToleranceInMeters);
                if (existingLayer == null)
                {
                    existingLayer = new HoistingLayerEditItem
                    {
                        HeightInMeters = Math.Round(relativeHeightInMeters, 3)
                    };
                    layerItems.Add(existingLayer);
                }

                if (!string.IsNullOrWhiteSpace(point.Id) && !existingLayer.PointIds.Contains(point.Id))
                {
                    existingLayer.PointIds.Add(point.Id);
                }
            }

            List<HoistingLayerEditItem> orderedLayers = layerItems
                .OrderByDescending(item => item.HeightInMeters)
                .ToList();

            for (int i = 0; i < orderedLayers.Count; i++)
            {
                orderedLayers[i].DisplayIndex = i + 1;
                orderedLayers[i].PointSummary = $"关联点 {orderedLayers[i].PointIds.Count} 个";
                HoistingLayerEditItems.Add(orderedLayers[i]);
            }

            HoistingLayerEditHintText = HoistingLayerEditItems.Count > 0
                ? "层高按高到低显示;每层高度相对起吊点,且必须严格低于上一层、高于下一层。"
                : "当前吊装路径未解析出可编辑的空中层。";
            OnPropertyChanged(nameof(CanApplyHoistingLayerHeights));
        }

        private async Task ExecuteApplyHoistingLayerHeightsAsync()
        {
            await SafeExecuteAsync(() =>
            {
                var coreRoute = GetSelectedCoreRoute();
                if (coreRoute == null || coreRoute.PathType != PathType.Hoisting)
                {
                    return;
                }

                if (HoistingLayerEditItems.Count == 0)
                {
                    UpdateMainStatus("当前吊装路径没有可编辑的空中层。");
                    return;
                }

                for (int i = 0; i < HoistingLayerEditItems.Count; i++)
                {
                    HoistingLayerEditItem currentLayer = HoistingLayerEditItems[i];
                    if (currentLayer.HeightInMeters <= 0)
                    {
                        HandleInvalidHoistingLayerHeightInput($"第{currentLayer.DisplayIndex}层高度必须大于0。");
                        return;
                    }

                    if (i > 0 && currentLayer.HeightInMeters >= HoistingLayerEditItems[i - 1].HeightInMeters)
                    {
                        HandleInvalidHoistingLayerHeightInput($"第{currentLayer.DisplayIndex}层高度必须严格低于上一层。");
                        return;
                    }

                    if (i < HoistingLayerEditItems.Count - 1 && currentLayer.HeightInMeters <= HoistingLayerEditItems[i + 1].HeightInMeters)
                    {
                        HandleInvalidHoistingLayerHeightInput($"第{currentLayer.DisplayIndex}层高度必须严格高于下一层。");
                        return;
                    }
                }

                HostCoordinateAdapter hostAdapter = CoordinateSystemManager.Instance.CreateHostAdapter();
                PathPoint hostStartPoint = coreRoute.Points.FirstOrDefault(point => point.Type == PathPointType.StartPoint) ?? coreRoute.Points.First();
                double hostStartElevation = HoistingCoordinateHelper.GetElevation(hostStartPoint.Position, hostAdapter);

                foreach (HoistingLayerEditItem layerItem in HoistingLayerEditItems)
                {
                    double hostTargetElevation = hostStartElevation + UnitsConverter.ConvertFromMeters(layerItem.HeightInMeters);
                    foreach (string pointId in layerItem.PointIds)
                    {
                        PathPoint targetPoint = coreRoute.Points.FirstOrDefault(point => string.Equals(point.Id, pointId, StringComparison.Ordinal));
                        if (targetPoint != null)
                        {
                            targetPoint.Position = HoistingCoordinateHelper.SetElevation(targetPoint.Position, hostTargetElevation, hostAdapter);
                        }
                    }
                }

                PathPoint firstAerialPoint = coreRoute.Points.FirstOrDefault(point =>
                    point != null &&
                    point.Type != PathPointType.StartPoint &&
                    point.Type != PathPointType.EndPoint &&
                    HoistingCoordinateHelper.GetElevation(point.Position, hostAdapter) > hostStartElevation + UnitsConverter.ConvertFromMeters(0.001));
                coreRoute.LiftHeight = firstAerialPoint != null
                    ? HoistingCoordinateHelper.GetElevation(firstAerialPoint.Position, hostAdapter) - hostStartElevation
                    : 0.0;
                coreRoute.LastModified = DateTime.Now;
                coreRoute.RecalculateRoute("更新吊装层高");

                SyncObjectParametersToRenderPlugin();
                _pathPlanningManager.DrawRouteVisualization(coreRoute, isAutoPath: false);
                _pathPlanningManager.SavePathToDatabase(coreRoute);
                _pathPlanningManager.RaiseVisualizationStateChanged();

                if (SelectedPathRoute != null && SelectedPathRoute.Id == coreRoute.Id)
                {
                    SyncPathViewModelFromCoreRoute(SelectedPathRoute, coreRoute, preserveSelection: true);
                }

                RefreshHoistingLayerEditItemsFromSelectedRoute();
                UpdateMainStatus($"已应用 {HoistingLayerEditItems.Count} 个吊装层高。");
                LogManager.Info($"[吊装层高] {coreRoute.Name}: 已应用 {HoistingLayerEditItems.Count} 个层高编辑项");
            }, "应用吊装层高");
        }

        private void HandleInvalidHoistingLayerHeightInput(string message)
        {
            const string validationMessage = "每层高度必须低于上一层、高于下一层,也不能相等。";
            LogManager.Warning($"[吊装层高] 用户输入无效: {message}");
            RefreshHoistingLayerEditItemsFromSelectedRoute();
            UpdateMainStatus(validationMessage);
            MessageBox.Show(validationMessage, "层高输入无效", MessageBoxButton.OK, MessageBoxImage.Warning);
        }

        /// <summary>
        /// 更新吊装路径的关联点(UI层)
        /// </summary>
        /// <param name="pathRoute">路径</param>
        /// <param name="modifiedPointIndex">修改的点的索引</param>
        private void UpdateAerialPathRelatedPoints(PathRouteViewModel pathRoute, int modifiedPointIndex)
        {
            if (pathRoute.PathType != NavisworksTransport.PathType.Hoisting ||
                pathRoute.Points.Count != 4)
            {
                return;
            }

            var points = pathRoute.Points;

            // 修改起点(索引0):更新提升点(索引1)的X,Y坐标
            if (modifiedPointIndex == 0)
            {
                var startPoint = points[0];
                var liftPoint = points[1];
                liftPoint.X = startPoint.X;
                liftPoint.Y = startPoint.Y;
            }
            // 修改终点(索引3):更新平移终点(索引2)的X,Y坐标
            else if (modifiedPointIndex == 3)
            {
                var endPoint = points[3];
                var moveEndPoint = points[2];
                moveEndPoint.X = endPoint.X;
                moveEndPoint.Y = endPoint.Y;
            }
        }

        /// <summary>
        /// 更新吊装路径的关联点(Core层)
        /// </summary>
        /// <param name="coreRoute">Core路径</param>
        /// <param name="modifiedPointIndex">修改的点的索引</param>
        private void UpdateAerialPathRelatedPointsCore(PathRoute coreRoute, int modifiedPointIndex)
        {
            if (coreRoute.PathType != NavisworksTransport.PathType.Hoisting ||
                coreRoute.Points.Count != 4)
            {
                return;
            }

            var points = coreRoute.Points;

            // 修改起点(索引0):更新提升点(索引1)的X,Y坐标
            if (modifiedPointIndex == 0)
            {
                var startPoint = points[0];
                var liftPoint = points[1];
                liftPoint.X = startPoint.X;
                liftPoint.Y = startPoint.Y;
            }
            // 修改终点(索引3):更新平移终点(索引2)的X,Y坐标
            else if (modifiedPointIndex == 3)
            {
                var endPoint = points[3];
                var moveEndPoint = points[2];
                moveEndPoint.X = endPoint.X;
                moveEndPoint.Y = endPoint.Y;
            }
        }

        #endregion

        #region 自动路径规划命令

        private async Task ExecuteSelectStartPointAsync()
        {
            await SafeExecuteAsync(() =>
            {
                LogManager.Info("=== 开始执行选择起点命令 ===");

                if (_pathPlanningManager == null)
                {
                    LogManager.Error("PathPlanningManager为null,无法选择起点");
                    UpdateMainStatus("路径规划管理器未初始化");
                    return;
                }

                // 立即清理现有的起点标记(使用正确的路径ID)
                if (PathPointRenderPlugin.Instance != null && _autoPathStartPointRoute != null)
                {
                    PathPointRenderPlugin.Instance.RemovePath(_autoPathStartPointRoute.Id);
                    _autoPathStartPointRoute = null; // 清除引用
                }

                // 重置状态
                _hasStartPoint = false;
                AutoPathStartPoint = "未选择";

                LogManager.Info("PathPlanningManager已初始化,开始设置自动路径规划状态");
                IsSelectingStartPoint = true;
                IsSelectingEndPoint = false;

                // 通知按钮状态更新,禁用"手动创建"按钮
                OnPropertyChanged(nameof(CanExecuteNewPath));
                OnPropertyChanged(nameof(CanExecuteNewFreePath));

                UpdateMainStatus("请在3D视图中点击选择起点...");

                // 进入自动路径规划模式 - 动态事件订阅
                LogManager.Info("进入自动路径规划模式,启用动态事件订阅");

                // 1. 禁用PathPlanningManager的鼠标处理
                _pathPlanningManager.DisableMouseHandling();

                // 2. 启用PathEditingViewModel的事件订阅
                PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked; // 先取消避免重复
                PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
                LogManager.Info("已启用PathEditingViewModel的鼠标事件订阅");

                // 强制重新初始化ToolPlugin以确保获得鼠标焦点,自动路径不需要PathPlanningManager订阅事件
                if (!ForceReinitializeToolPlugin(subscribeToEvents: false))
                {
                    UpdateMainStatus("ToolPlugin初始化失败,请重试");
                    return;
                }

                // 在STA线程中调用Navisworks API
                _pathPlanningManager.StartClickTool(PathPointType.StartPoint);
                LogManager.Info("=== 选择起点命令设置完成,已启用动态事件订阅,等待用户点击 ===");
            }, "选择起点");
        }

        private async Task ExecuteSelectEndPointAsync()
        {
            await SafeExecuteAsync(() =>
            {
                LogManager.Info("=== 开始执行选择终点命令 ===");

                if (_pathPlanningManager == null)
                {
                    LogManager.Error("PathPlanningManager为null,无法选择终点");
                    UpdateMainStatus("路径规划管理器未初始化");
                    return;
                }

                // 立即清理现有的终点标记(使用正确的路径ID)
                if (PathPointRenderPlugin.Instance != null && _autoPathEndPointRoute != null)
                {
                    PathPointRenderPlugin.Instance.RemovePath(_autoPathEndPointRoute.Id);
                    LogManager.Debug($"[选择终点] 已清除之前的终点标记,ID: {_autoPathEndPointRoute.Id}");
                    _autoPathEndPointRoute = null; // 清除引用
                }

                // 重置状态
                _hasEndPoint = false;
                AutoPathEndPoint = "未选择";

                LogManager.Info("PathPlanningManager已初始化,开始设置自动路径规划状态");
                IsSelectingStartPoint = false;
                IsSelectingEndPoint = true;

                // 通知按钮状态更新,禁用"手动创建"按钮
                OnPropertyChanged(nameof(CanExecuteNewPath));
                OnPropertyChanged(nameof(CanExecuteNewFreePath));

                UpdateMainStatus("请在3D视图中点击选择终点...");

                // 进入自动路径规划模式 - 动态事件订阅
                LogManager.Info("进入自动路径规划模式,启用动态事件订阅");

                // 1. 禁用PathPlanningManager的鼠标处理
                _pathPlanningManager.DisableMouseHandling();

                // 2. 启用PathEditingViewModel的事件订阅
                PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked; // 先取消避免重复
                PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
                LogManager.Info("已启用PathEditingViewModel的鼠标事件订阅");

                // 强制重新初始化ToolPlugin以确保获得鼠标焦点,自动路径不需要PathPlanningManager订阅事件
                if (!ForceReinitializeToolPlugin(subscribeToEvents: false))
                {
                    UpdateMainStatus("ToolPlugin初始化失败,请重试");
                    return;
                }

                // 在STA线程中调用Navisworks API
                _pathPlanningManager.StartClickTool(PathPointType.EndPoint);
                LogManager.Info("=== 选择终点命令设置完成,已启用动态事件订阅,等待用户点击 ===");
            }, "选择终点");
        }

        private async Task ExecuteAutoPlanPathAsync()
        {
            await SafeExecuteAsync(async () =>
            {
                // 保存当前光标
                var oldCursor = Mouse.OverrideCursor;

                try
                {
                    if (!_hasStartPoint || !_hasEndPoint)
                    {
                        UpdateMainStatus("请先选择起点和终点");
                        return;
                    }

                    // 设置等待光标
                    Mouse.OverrideCursor = Cursors.Wait;

                    UpdateMainStatus("正在计算最优路径...", -1, true);
                    LogManager.Info("=== 开始执行自动路径规划 ===");

                // 确保在开始自动路径规划前清理任何残留的事件订阅
                CleanupAutoPathEventSubscriptions();
                if (_pathPlanningManager != null)
                {
                    _pathPlanningManager.StopClickTool();
                }

                // 清理所有临时路径,确保干净的起始状态
                ClearTemporaryAutoPathMarkers();
                if (PathPointRenderPlugin.Instance != null)
                {
                    // 检查是否有网格可视化启用,只在启用时保留网格可视化路径
                    if (_pathPlanningManager?.IsAnyGridVisualizationEnabled == true)
                    {
                        PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                    }
                    else
                    {
                        PathPointRenderPlugin.Instance.ClearPathsExcept(); // 清理所有路径,不保留任何内容
                    }
                }

                // 调用PathPlanningManager的自动路径规划功能
                var startPathPoint = new PathPoint
                {
                    Name = "自动起点",
                    Position = _startPoint3D,
                    Type = PathPointType.StartPoint
                };
                var endPathPoint = new PathPoint
                {
                    Name = "自动终点",
                    Position = _endPoint3D,
                    Type = PathPointType.EndPoint
                };

                LogManager.Info($"起点: ({_startPoint3D.X:F2}, {_startPoint3D.Y:F2}, {_startPoint3D.Z:F2})");
                LogManager.Info($"终点: ({_endPoint3D.X:F2}, {_endPoint3D.Y:F2}, {_endPoint3D.Z:F2})");

                // 计算物体半径:基于长度和宽度的较大值的一半,高度暂时不参与半径计算
                var objectRadius = Math.Max(ObjectLength, ObjectWidth) / 2.0;

                LogManager.Info($"物体参数: 长{ObjectLength:F1}m × 宽{ObjectWidth:F1}m × 高{ObjectHeight:F1}m");
                LogManager.Info($"计算得出物体半径: {objectRadius:F2}m (基于长宽较大值的一半)");

                // 确定网格大小:如果启用手动设置则使用用户设置的值,否则使用-1(自动选择)
                var gridSize = IsGridSizeManuallyEnabled ? GridSize : -1;

                // 获取选择的路径策略,如果未选择则默认使用最短路径
                var selectedStrategy = SelectedPathStrategy?.Value ?? PathStrategy.Shortest;

                LogManager.Info($"网格大小设置: {(IsGridSizeManuallyEnabled ? $"手动设置 {GridSize:F1}米" : "自动选择")}");
                LogManager.Info($"路径策略: {SelectedPathStrategy?.DisplayName ?? "最短路径"}");

                // 在STA线程中执行Navisworks API调用
                var pathRoute = await _pathPlanningManager?.AutoPlanPath(startPathPoint, endPathPoint, objectRadius, SafetyMargin, gridSize, ObjectHeight, selectedStrategy);

                if (pathRoute != null && pathRoute.Points.Count > 0)
                {
                    LogManager.Info($"路径规划成功,共 {pathRoute.Points.Count} 个点");

                    // 自动路径规划完成后,执行完整的事件订阅清理
                    CleanupAutoPathEventSubscriptions();
                    if (_pathPlanningManager != null)
                    {
                        _pathPlanningManager.StopClickTool();
                    }

                    // 清理临时的起点和终点标记
                    ClearTemporaryAutoPathMarkers();

                    // 不在这里直接操作UI,让RouteGenerated事件处理UI更新
                    // 这避免了重复的路径添加和UI更新冲突

                    // 不在这里设置状态,让RouteGenerated事件处理UI更新
                    LogManager.Info($"✅ 自动路径规划完成,RouteGenerated事件将处理UI更新");
                }
                else
                {
                    // 这里的逻辑已经在上方处理过了

                    // 失败情况下也要清理事件订阅和临时标记
                    CleanupAutoPathEventSubscriptions();
                    if (_pathPlanningManager != null)
                    {
                        _pathPlanningManager.StopClickTool();
                    }

                    // 清理临时的起点和终点标记
                    ClearTemporaryAutoPathMarkers();

                    // 确保失败后也清理所有可能的残留路径对象
                    if (PathPointRenderPlugin.Instance != null)
                    {
                        // 检查是否有网格可视化启用,只在启用时保留网格可视化路径
                        if (_pathPlanningManager?.IsAnyGridVisualizationEnabled == true)
                        {
                            PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                        }
                        else
                        {
                            PathPointRenderPlugin.Instance.ClearPathsExcept(); // 清理所有路径,不保留任何内容
                        }
                    }
                }
                }
                finally
                {
                    // 恢复光标
                    Mouse.OverrideCursor = oldCursor;
                }
            }, "自动路径规划");
        }

        private async Task ExecuteClearAutoPathAsync()
        {
            // 使用基类的SafeExecuteAsync方法,确保在STA线程上执行
            await SafeExecuteAsync(() =>
            {
                LogManager.Info("=== 开始重置自动路径规划状态 ===");

                // 停止任何正在进行的点选择
                if (_pathPlanningManager != null)
                {
                    _pathPlanningManager.StopClickTool();
                    PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
                }

                // 清除所有路径的可视化显示(与新建路径按钮保持一致)
                if (PathPointRenderPlugin.Instance != null)
                {
                    try
                    {
                        // 清除路径可视化,但保留网格可视化
                        PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
                        LogManager.Info("重置参数:已清除路径可视化显示(保留网格可视化)");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"重置参数:清除路径可视化失败: {ex.Message}", ex);
                        // 不抛出异常,继续执行状态重置
                    }
                }

                // 强制重新初始化ToolPlugin以重新获得鼠标焦点,重置时不需要订阅事件
                if (_pathPlanningManager != null)
                {
                    ForceReinitializeToolPlugin(subscribeToEvents: false);
                }

                // 重置所有状态
                _hasStartPoint = false;
                _hasEndPoint = false;
                _startPoint3D = new Point3D();
                _endPoint3D = new Point3D();
                AutoPathStartPoint = "未选择";
                AutoPathEndPoint = "未选择";
                UpdateMainStatus("就绪");
                IsSelectingStartPoint = false;
                IsSelectingEndPoint = false;

                // 清除路径引用
                _autoPathStartPointRoute = null;
                _autoPathEndPointRoute = null;

                // 通知Can Execute属性更改
                OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                OnPropertyChanged(nameof(CanExecuteNewPath));
                OnPropertyChanged(nameof(CanExecuteNewFreePath));

                LogManager.Info("自动路径规划参数和起终点标记已完全重置,ToolPlugin已重新初始化");
            }, "重置自动路径规划");
        }

        #endregion

        #region 路径编辑命令 - 待实现

        private async Task ExecuteRenamePathAsync()
        {
            if (SelectedPathRoute == null) return;

            await SafeExecuteAsync(async () =>
            {
                await _uiStateManager.ExecuteUIUpdateAsync(() =>
                {
                    // TODO: 实现重命名对话框
                    var newName = $"路径 {PathRoutes.Count}";
                    var oldName = SelectedPathRoute.Name;
                    SelectedPathRoute.Name = newName;
                    UpdateMainStatus($"路径已重命名: {oldName} -> {newName}");
                });
            }, "重命名路径");
        }

        private async Task ExecuteAddPathPointAsync()
        {
            if (!CanExecuteStartEdit) return;

            await SafeExecuteAsync(async () =>
            {
                await _uiStateManager.ExecuteUIUpdateAsync(() =>
                {
                    IsPathEditMode = true;
                    if (SelectedPathRoute != null)
                    {
                        SelectedPathRoute.IsActive = true;
                        UpdateMainStatus($"正在激活3D路径编辑模式: {SelectedPathRoute.Name}...");

                        // 检查是否是空轨路径
                        bool isRailPath = SelectedPathRoute.PathType == PathType.Rail;

                        // 启动PathPlanningManager的点击工具,这会设置正确的编辑状态
                        if (_pathPlanningManager != null)
                        {
                            try
                            {
                                if (isRailPath)
                                {
                                    _pathPlanningManager.StartClickTool(PathPointType.WayPoint, enableRailSnapping: true);
                                    LogManager.Info($"已启动PathPlanningManager点击工具(空轨吸附模式): {SelectedPathRoute.Name}");
                                }
                                else
                                {
                                    _pathPlanningManager.StartClickTool(PathPointType.WayPoint);
                                    LogManager.Info($"已启动PathPlanningManager点击工具: {SelectedPathRoute.Name}");
                                }
                            }
                            catch (Exception ex)
                            {
                                LogManager.Error($"启动点击工具失败: {ex.Message}");
                                UpdateMainStatus("启动3D编辑工具失败,请重试");
                                IsPathEditMode = false;
                                return;
                            }
                        }
                        else
                        {
                            UpdateMainStatus("路径规划管理器未初始化");
                            LogManager.Error("添加路径点:PathPlanningManager未初始化");
                            IsPathEditMode = false;
                            return;
                        }

                        string modeText = isRailPath ? "(空轨吸附模式)" : "";
                        UpdateMainStatus($"已进入3D路径编辑模式: {SelectedPathRoute.Name} {modeText} - 在3D视图中点击设置路径点");
                        LogManager.Info($"开始添加路径点: {SelectedPathRoute.Name},已启动点击工具");

                        // 手动触发按钮状态更新
                        OnPropertyChanged(nameof(CanExecuteStartEdit));
                        OnPropertyChanged(nameof(CanExecuteEndEdit));
                    }
                });
            }, "添加路径点");
        }

        private async Task ExecuteEndEditAsync()
        {
            if (!CanExecuteEndEdit) return;

            if ((_pathPlanningManager == null || _pathPlanningManager.PathEditState == PathEditState.Viewing) &&
                CanCancelRailAssemblyWorkflow)
            {
                ExecuteCancelRailAssemblyWorkflow();
                return;
            }

            await SafeExecuteAsync(async () =>
            {
                bool success = false;
                string operationMessage = "";
                bool wasInPreviewMode = false;

                if (_pathPlanningManager != null)
                {
                    // 检查是否在修改路径点模式
                    bool isEditingPoint = _pathPlanningManager.PathEditState == PathEditState.EditingPoint;

                    if (isEditingPoint)
                    {
                        // 修改路径点模式 - 尝试确认修改
                        success = _pathPlanningManager.UpdatePointPosition();
                        if (success)
                        {
                            operationMessage = "路径点修改已确认";
                        }
                        else
                        {
                            // 确认失败(可能没有预览点),执行取消操作以安全退出
                            success = _pathPlanningManager.CancelEditPoint();
                            operationMessage = success ? "已取消路径点修改" : "取消路径点修改失败";
                        }
                        LogManager.Info($"[UI-修改路径点] {operationMessage}");
                    }
                    else
                    {
                        // 记录是否在预览模式(因为确认预览点后会退出预览模式)
                        wasInPreviewMode = _pathPlanningManager.IsPreviewMode;

                        if (wasInPreviewMode)
                        {
                            // 预览模式 - 先确认预览点,然后立即完成编辑
                            var confirmedPoint = _pathPlanningManager.ConvertPreviewToPathPoint();
                            if (confirmedPoint != null)
                            {
                                LogManager.Info($"[UI-预览模式] 预览点已确认: {confirmedPoint.Name},现在完成编辑");

                                // 立即完成编辑,不让用户继续添加点
                                success = _pathPlanningManager.FinishEditing();
                                operationMessage = success ? $"预览点已确认并完成编辑: {confirmedPoint.Name}" : "预览点确认后完成编辑失败";
                            }
                            else
                            {
                                LogManager.Error("[UI-预览模式] 预览点确认失败");
                                operationMessage = "预览点确认失败";
                                success = false;
                            }

                            LogManager.Info($"[UI-预览模式] {operationMessage}");
                        }
                        else
                        {
                            // 普通模式 - 直接完成编辑
                            success = _pathPlanningManager.FinishEditing();
                            operationMessage = success ? "路径编辑完成" : "路径编辑完成失败";

                            LogManager.Info($"[UI-编辑模式] {operationMessage}");
                        }
                    }
                }

                await _uiStateManager.ExecuteUIUpdateAsync(() =>
                {
                    if (success)
                    {
                        // 编辑完成成功
                        if (SelectedPathRoute != null)
                        {
                            if (_pathPlanningManager?.PathEditState == PathEditState.EditingPoint || operationMessage.Contains("路径点修改"))
                            {
                                UpdateMainStatus($"✅ 路径点修改完成: {SelectedPathRoute.Name}");
                            }
                            else if (wasInPreviewMode)
                            {
                                UpdateMainStatus($"✅ 预览点已确认,路径编辑完成: {SelectedPathRoute.Name}");
                            }
                            else
                            {
                                UpdateMainStatus($"✅ 路径编辑完成: {SelectedPathRoute.Name} - 最后一个点已自动设置为终点");
                            }
                        }

                        LogManager.Info("[UI状态] 路径编辑完成,等待状态变更事件更新按钮");
                    }
                    else
                    {
                        // 编辑完成失败
                        if (SelectedPathRoute != null)
                        {
                            UpdateMainStatus($"❌ 路径编辑失败: {SelectedPathRoute.Name}");
                        }

                        LogManager.Error("[UI状态] 路径编辑失败");
                    }

                    // 手动触发按钮状态更新 - 确保UI及时响应
                    OnPropertyChanged(nameof(CanExecuteStartEdit));
                    OnPropertyChanged(nameof(CanExecuteEndEdit));
                    OnPropertyChanged(nameof(CanExecuteCancelModifyPoint));
                });
            }, "结束路径编辑");
        }

        private async Task ExecuteClearPathAsync()
        {
            if (!CanExecuteClearPath) return;

            await SafeExecuteAsync(async () =>
            {
                var pointCount = SelectedPathRoute.Points.Count;

                // 清空 Core 层的路径点
                var coreRoute = _pathPlanningManager?.Routes?.FirstOrDefault(r => r.Name == SelectedPathRoute.Name);
                if (coreRoute != null)
                {
                    coreRoute.Points.Clear();
                    coreRoute.RecalculateAndSaveRoute("清空路径");
                    LogManager.Info($"已清空Core路径: {coreRoute.Name}");
                }

                // 清空 UI 层的路径点
                await _uiStateManager.ExecuteUIUpdateAsync(() =>
                {
                    SelectedPathRoute.Points.Clear();
                    UpdateMainStatus($"已清空路径 {SelectedPathRoute.Name} 的 {pointCount} 个点");
                });
            }, "清空路径");
        }

        private async Task ExecuteDeletePointAsync(PathPointViewModel point)
        {
            if (SelectedPathRoute == null || point == null) return;

            await SafeExecuteAsync(async () =>
            {
                // 1. 查找对应的Core数据
                var coreRoute = _pathPlanningManager?.Routes?.FirstOrDefault(r => r.Name == SelectedPathRoute.Name);
                if (coreRoute == null)
                {
                    LogManager.Warning($"未找到对应的Core路径: {SelectedPathRoute.Name}");
                    return;
                }

                // 2. 路径完整性验证:检查删除后是否至少还有2个点
                if (coreRoute.Points.Count <= 2)
                {
                    LogManager.Warning($"路径点不足,无法删除。当前路径只有{coreRoute.Points.Count}个点,至少需要保留2个点(起点和终点)");
                    UpdateMainStatus($"❌ 无法删除路径点:路径至少需要保留2个点(起点和终点),当前只有{coreRoute.Points.Count}个点");
                    return;
                }

                // 3. 在Core路径中查找对应的点(通过位置和名称匹配)
                var corePoint = coreRoute.Points.FirstOrDefault(p =>
                    p.Name == point.Name &&
                    Math.Abs(p.Position.X - point.X) < 0.001 &&
                    Math.Abs(p.Position.Y - point.Y) < 0.001 &&
                    Math.Abs(p.Position.Z - point.Z) < 0.001);

                if (corePoint == null)
                {
                    LogManager.Warning($"未找到对应的Core路径点: {point.Name}");
                    // 即使Core数据不匹配,也要更新UI数据保持一致性
                }

                await _uiStateManager.ExecuteUIUpdateAsync(() =>
                {
                    // 4. 禁止删除起点和终点
                    if (corePoint != null)
                    {
                        int pointIndex = coreRoute.Points.IndexOf(corePoint);

                        if (corePoint.Type == PathPointType.StartPoint)
                        {
                            LogManager.Warning($"不能删除路径的起点");
                            UpdateMainStatus($"❌ 无法删除:{corePoint.Name} 是路径的起点");
                            return;
                        }

                        if (corePoint.Type == PathPointType.EndPoint)
                        {
                            LogManager.Warning($"不能删除路径的终点");
                            UpdateMainStatus($"❌ 无法删除:{corePoint.Name} 是路径的终点");
                            return;
                        }

                        // 吊装路径:禁止删除关键点(提升点、下降点)
                        if (coreRoute.PathType == PathType.Hoisting &&
                            (corePoint.Name == "提升点" || corePoint.Name == "下降点"))
                        {
                            LogManager.Warning($"不能删除吊装路径的关键点: {corePoint.Name}");
                            UpdateMainStatus($"❌ 无法删除:{corePoint.Name} 是吊装路径的关键点");
                            return;
                        }

                        // 删除Core数据
                        coreRoute.Points.Remove(corePoint);
                        LogManager.Info($"已从Core数据删除路径点: {corePoint.Name}");

                        // 吊装路径:正交化路径(处理斜线和清除多余点)
                        if (coreRoute.PathType == PathType.Hoisting)
                        {
                            _pathPlanningManager?.OrthogonalizePath(coreRoute);

                            // 吊装路径:检测并移除矩形环路
                            LogManager.Info($"[吊装路径] 删除路径点后检测矩形环路");
                            _pathPlanningManager?.RemoveRectangularLoops(coreRoute);
                        }

                        // 调用PathPlanningManager的3D删除方法
                        _pathPlanningManager.RemovePathPoint(corePoint);

                        // 触发UI同步更新事件
                        _pathPlanningManager.RaisePathPointsListUpdated(coreRoute, "删除路径点并重新分配类型");
                        LogManager.Info("已触发PathPointsListUpdated事件,UI将自动同步");
                    }

                    // 5. 删除UI数据(事件驱动会自动处理,这里只作为备份)
                    SelectedPathRoute.Points.Remove(point);
                    LogManager.Info($"已从UI删除路径点: {point.Name}");

                    // 🔥 如果被删除的点是当前选中的点,清空选中状态
                    if (SelectedPathPoint != null && SelectedPathPoint.Id == point.Id)
                    {
                        SelectedPathPoint = null;
                        LogManager.Info("已清空选中状态(删除的是当前选中的点)");
                    }

                    // 6. 更新UI状态
                    UpdateMainStatus($"✅ 已删除路径点: {point.Name}");

                    LogManager.Info($"路径点删除完成,当前UI点数: {SelectedPathRoute.Points.Count}, Core点数: {coreRoute?.Points.Count ?? 0}");
                });

                // 7. 刷新3D可视化显示(路径变更会自动更新可视化)
                UpdatePathVisualization();
                LogManager.Info("已触发路径可视化更新");

            }, "删除路径点");
        }

        private async Task ExecuteModifyPointAsync()
        {
            if (!CanExecuteModifyPoint) return;

            await SafeExecuteAsync(async () =>
            {
                await _uiStateManager.ExecuteUIUpdateAsync(() =>
                {
                    if (SelectedPathPoint != null && _pathPlanningManager != null)
                    {
                        // 获取选中路径点的索引
                        var currentRoute = _pathPlanningManager.CurrentRoute;
                        if (currentRoute != null && currentRoute.Points != null)
                        {
                            int pointIndex = -1;

                            // 详细调试信息
                            LogManager.Info($"开始查找路径点索引 - 选中点Id: {SelectedPathPoint.Id}, 选中点名称: {SelectedPathPoint.Name}");
                            LogManager.Info($"当前路径包含 {currentRoute.Points.Count} 个路径点");

                            // 遍历查找匹配的Id
                            for (int i = 0; i < currentRoute.Points.Count; i++)
                            {
                                var currentPoint = currentRoute.Points[i];
                                //LogManager.Info($"检查路径点 [{i}] - Id: {currentPoint.Id}, 名称: {currentPoint.Name}");

                                if (currentPoint.Id == SelectedPathPoint.Id)
                                {
                                    pointIndex = i;
                                    LogManager.Info($"找到匹配的路径点,索引: {pointIndex}");
                                    break;
                                }
                            }

                            if (pointIndex >= 0)
                            {
                                // 调用PathPlanningManager开始修改路径点
                                bool success = _pathPlanningManager.StartEditingPoint(pointIndex);

                                if (success)
                                {
                                    UpdateMainStatus($"正在修改路径点: {SelectedPathPoint.Name} - 请在3D视图中点击新位置");
                                    LogManager.Info($"已开始修改路径点: {SelectedPathPoint.Name}, 索引: {pointIndex}");

                                    // 刷新命令状态
                                    OnPropertyChanged(nameof(CanExecuteStartEdit));
                                    OnPropertyChanged(nameof(CanExecuteEndEdit));
                                    OnPropertyChanged(nameof(CanExecuteModifyPoint));
                                    OnPropertyChanged(nameof(CanExecuteCancelModifyPoint));
                                }
                                else
                                {
                                    UpdateMainStatus("修改路径点失败,请检查路径状态");
                                    LogManager.Error($"开始修改路径点失败: {SelectedPathPoint.Name}, 索引: {pointIndex}");
                                }
                            }
                            else
                            {
                                UpdateMainStatus("找不到选中的路径点");
                                LogManager.Error($"找不到路径点索引 - 选中点Id: {SelectedPathPoint.Id}, 选中点名称: {SelectedPathPoint.Name}");
                                LogManager.Error("可能原因:1)选中的路径点与当前路径不匹配 2)路径点数据不同步 3)Id不匹配");
                            }
                        }
                        else
                        {
                            if (currentRoute == null)
                            {
                                UpdateMainStatus("当前没有活动路径");
                                LogManager.Error("尝试修改路径点时没有当前路径");
                            }
                            else
                            {
                                UpdateMainStatus("当前路径没有路径点数据");
                                LogManager.Error("当前路径的Points集合为空");
                            }
                        }
                    }
                    else
                    {
                        if (SelectedPathPoint == null)
                        {
                            UpdateMainStatus("请先选中要修改的路径点");
                            LogManager.Warning("修改路径点时没有选中路径点");
                        }
                        else
                        {
                            UpdateMainStatus("路径规划管理器未初始化");
                            LogManager.Error("修改路径点时PathPlanningManager为空");
                        }
                    }
                });
            }, "修改路径点");
        }

        /// <summary>
        /// 取消修改路径点
        /// </summary>
        private async Task ExecuteCancelModifyPointAsync()
        {
            if (!CanExecuteCancelModifyPoint) return;

            await SafeExecuteAsync(async () =>
            {
                await _uiStateManager.ExecuteUIUpdateAsync(() =>
                {
                    if (_pathPlanningManager != null)
                    {
                        // 调用PathPlanningManager取消修改路径点
                        bool success = _pathPlanningManager.CancelEditPoint();

                        if (success)
                        {
                            UpdateMainStatus("已取消修改路径点");
                            LogManager.Info("用户取消了修改路径点操作");
                        }
                        else
                        {
                            UpdateMainStatus("取消修改路径点失败");
                            LogManager.Error("取消修改路径点失败");
                        }

                        // 刷新命令状态
                        OnPropertyChanged(nameof(CanExecuteStartEdit));
                        OnPropertyChanged(nameof(CanExecuteEndEdit));
                        OnPropertyChanged(nameof(CanExecuteModifyPoint));
                        OnPropertyChanged(nameof(CanExecuteCancelModifyPoint));
                    }
                });
            }, "取消修改路径点");
        }

        #endregion

        #region 文件管理命令

        private async Task ExecuteImportPathAsync()
        {
            await SafeExecuteAsync(async () =>
            {
                try
                {
                    // 打开文件选择对话框
                    var openFileDialog = new OpenFileDialog
                    {
                        Title = "导入路径文件",
                        Filter = "路径文件 (*.xml;*.json)|*.xml;*.json|XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|所有文件 (*.*)|*.*",
                        FilterIndex = 1,
                        CheckFileExists = true,
                        CheckPathExists = true,
                        Multiselect = true
                    };

                    if (openFileDialog.ShowDialog() == true)
                    {
                        var filePaths = openFileDialog.FileNames;
                        int totalImported = 0;
                        int totalFailed = 0;
                        int totalRenamed = 0;

                        foreach (var filePath in filePaths)
                        {
                            var extension = Path.GetExtension(filePath).ToLower();

                            ExportFormat importFormat;
                            switch (extension)
                            {
                                case ".json":
                                    importFormat = ExportFormat.Json;
                                    break;
                                case ".csv":
                                    importFormat = ExportFormat.Csv;
                                    break;
                                default:
                                    importFormat = ExportFormat.Xml;
                                    break;
                            }

                            var importParameters = new ImportPathParameters
                            {
                                FilePath = filePath,
                                ImportFormat = importFormat,
                                MergeWithExisting = true,
                                CreateBackup = true,
                                DuplicateHandling = DuplicateNameHandling.Rename,
                                ValidateImportedData = true,
                                AutoSelectFirstRoute = false,
                                Description = $"导入路径文件: {Path.GetFileName(filePath)}"
                            };

                            var importCommand = new ImportPathCommand(importParameters, _pathPlanningManager);
                            var result = await importCommand.ExecuteAsync();

                            if (result.IsSuccess)
                            {
                                var importResult = (result as PathPlanningResult<ImportPathResult>)?.Data;
                                if (importResult != null)
                                {
                                    totalImported += importResult.ImportedCount;
                                    totalFailed += importResult.FailedCount;
                                    totalRenamed += importResult.RenamedCount;
                                }
                            }
                            else
                            {
                                totalFailed++;
                                LogManager.Error($"路径导入失败 [{Path.GetFileName(filePath)}]: {result.ErrorMessage}");
                            }
                        }

                        var existingIds = new HashSet<string>(PathRoutes.Select(r => r.Route.Id));
                        foreach (var coreRoute in _pathPlanningManager.Routes)
                        {
                            if (!existingIds.Add(coreRoute.Id)) continue;

                            var pathViewModel = new PathRouteViewModel(isFromDatabase: true)
                            {
                                Route = coreRoute,
                                IsActive = false
                            };
                            pathViewModel.SetTimeInfo(coreRoute.CreatedTime, coreRoute.LastModified);
                            foreach (var pt in CreatePathPointViewModelsFromCoreRoute(coreRoute))
                                pathViewModel.Points.Add(pt);
                            PathRoutes.Add(pathViewModel);
                        }

                        // 自动选择第一个路径
                        if (PathRoutes.Count > 0)
                        {
                            SelectedPathRoute = PathRoutes.FirstOrDefault();
                        }

                        if (totalImported > 0)
                        {
                            var statusMsg = $"✅ 导入成功: {totalImported} 个路径";
                            if (totalFailed > 0)
                                statusMsg += $" (失败 {totalFailed} 个)";
                            UpdateMainStatus(statusMsg);

                            var dialogMsg = new StringBuilder();
                            dialogMsg.AppendLine($"成功导入: {totalImported} 个路径");
                            if (totalFailed > 0)
                                dialogMsg.AppendLine($"导入失败: {totalFailed} 个路径");
                            if (totalRenamed > 0)
                                dialogMsg.AppendLine($"重名自动重命名: {totalRenamed} 个路径");
                            dialogMsg.AppendLine($"来源文件数: {filePaths.Length}");
                            DialogHelper.ShowAutoClosingMessageBox(
                                dialogMsg.ToString(),
                                "导入完成",
                                totalFailed == 0 ? System.Windows.MessageBoxImage.Information : System.Windows.MessageBoxImage.Warning,
                                autoCloseMilliseconds: 5000);
                        }
                        else
                        {
                            UpdateMainStatus($"❌ 导入失败: 所有文件导入失败");
                            DialogHelper.ShowAutoClosingMessageBox(
                                "所有文件导入失败。\n请确认文件格式是否正确。",
                                "导入失败",
                                System.Windows.MessageBoxImage.Error,
                                autoCloseMilliseconds: 5000);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Error($"导入路径异常: {ex.Message}", ex);
                    UpdateMainStatus($"❌ 导入异常: {ex.Message}");
                }
            }, "导入路径");
        }

        private async Task ExecuteExportPathAsync()
        {
            if (!CanExecuteExportPath) return;

            await SafeExecuteAsync(async () =>
            {
                try
                {
                    // 打开文件保存对话框
                    var saveFileDialog = new SaveFileDialog
                    {
                        Title = "导出全部路径",
                        Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|CSV文件 (*.csv)|*.csv|DELMIA Apriso XML (*.aprxml)|*.aprxml|所有文件 (*.*)|*.*",
                        FilterIndex = 1,
                        FileName = $"路径导出_{DateTime.Now:yyyyMMdd_HHmmss}",
                        DefaultExt = "xml",
                        AddExtension = true
                    };

                    if (saveFileDialog.ShowDialog() == true)
                    {
                        var filePath = saveFileDialog.FileName;

                        // 确定导出格式(通过FilterIndex判断,因为DELMIA Apriso和普通XML都是.xml扩展名)
                        ExportFormat exportFormat;
                        switch (saveFileDialog.FilterIndex)
                        {
                            case 2: // JSON文件
                                exportFormat = ExportFormat.Json;
                                break;
                            case 3: // CSV文件
                                exportFormat = ExportFormat.Csv;
                                break;
                            case 4: // DELMIA Apriso XML
                                exportFormat = ExportFormat.DelmiaApriso;
                                break;
                            default: // XML文件或其他
                                exportFormat = ExportFormat.Xml;
                                break;
                        }

                        // 创建导出参数 - 导出所有路径
                        var exportParameters = new ExportPathParameters
                        {
                            ExportAll = true,
                            OutputFilePath = filePath,
                            ExportFormat = exportFormat,
                            OverwriteExisting = true,
                            ValidateExportData = true,
                            GenerateReport = false,
                            Description = $"导出全部路径到: {Path.GetFileName(filePath)}"
                        };

                        // 创建并执行导出命令
                        var exportCommand = new ExportPathCommand(exportParameters, _pathPlanningManager);
                        var result = await exportCommand.ExecuteAsync();

                        if (result.IsSuccess)
                        {
                            var exportResult = (result as PathPlanningResult<ExportPathResult>)?.Data;
                            if (exportResult != null)
                            {
                                var statusMessage = $"✅ 导出全部成功: {exportResult.ExportedCount} 个路径到 {Path.GetFileName(filePath)}";
                                if (exportResult.FailedCount > 0)
                                {
                                    statusMessage += $" (失败 {exportResult.FailedCount} 个)";
                                }
                                UpdateMainStatus(statusMessage);
                                LogManager.Info($"导出完成,文件大小: {exportResult.FileSizeMB:F2} MB");
                            }
                            else
                            {
                                UpdateMainStatus($"✅ 全部路径导出完成: {Path.GetFileName(filePath)}");
                            }
                        }
                        else
                        {
                            UpdateMainStatus($"❌ 导出全部失败: {result.ErrorMessage}");
                            LogManager.Error($"全部路径导出失败: {result.ErrorMessage}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Error($"导出全部路径异常: {ex.Message}", ex);
                    UpdateMainStatus($"❌ 导出全部异常: {ex.Message}");
                }
            }, "导出全部路径");
        }

        private async Task ExecuteSaveAsPathAsync()
        {
            if (!CanExecuteSaveAsPath) return;

            await SafeExecuteAsync(async () =>
            {
                try
                {
                    // 收集选中的路径
                    var selectedRoutes = PathRoutes
                        .Where(r => r.IsSelected && r.Points.Count > 0)
                        .Select(r => _pathPlanningManager.Routes.FirstOrDefault(c => c.Name == r.Name))
                        .Where(c => c != null)
                        .ToList();

                    // 如果没有多选，使用当前选中路径
                    if (selectedRoutes.Count == 0 && SelectedPathRoute != null && SelectedPathRoute.Points.Count > 0)
                    {
                        var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Name == SelectedPathRoute.Name);
                        if (coreRoute != null)
                            selectedRoutes.Add(coreRoute);
                    }

                    if (selectedRoutes.Count == 0)
                    {
                        UpdateMainStatus("没有可导出的路径");
                        return;
                    }

                    // 打开文件保存对话框（确定格式和目录）
                    var firstRoute = selectedRoutes[0];
                    var saveFileDialog = new SaveFileDialog
                    {
                        Title = selectedRoutes.Count == 1
                            ? $"导出路径: {firstRoute.Name}"
                            : $"导出 {selectedRoutes.Count} 个路径",
                        Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|CSV文件 (*.csv)|*.csv|DELMIA Apriso XML (*.aprxml)|*.aprxml|所有文件 (*.*)|*.*",
                        FilterIndex = 1,
                        FileName = selectedRoutes.Count == 1
                            ? firstRoute.Name?.Replace(" ", "_") ?? "路径"
                            : string.Join("; ", selectedRoutes.Select(r => r.Name.Replace(" ", "_"))),
                        DefaultExt = "xml",
                        AddExtension = true
                    };

                    if (saveFileDialog.ShowDialog() == true)
                    {
                        ExportFormat exportFormat;
                        switch (saveFileDialog.FilterIndex)
                        {
                            case 2: exportFormat = ExportFormat.Json; break;
                            case 3: exportFormat = ExportFormat.Csv; break;
                            case 4: exportFormat = ExportFormat.DelmiaApriso; break;
                            default: exportFormat = ExportFormat.Xml; break;
                        }

                        var outputDir = Path.GetDirectoryName(saveFileDialog.FileName);
                        int exportedCount = 0;
                        int failedCount = 0;

                        foreach (var route in selectedRoutes)
                        {
                            var exportFilePath = Path.Combine(outputDir, $"{route.Name.Replace(" ", "_")}{Path.GetExtension(saveFileDialog.FileName)}");

                            var exportParameters = new ExportPathParameters
                            {
                                PathsToExport = new List<PathRoute> { route },
                                OutputFilePath = exportFilePath,
                                ExportFormat = exportFormat,
                                OverwriteExisting = true,
                                ValidateExportData = true,
                                GenerateReport = false,
                                Description = $"导出路径: {route.Name}"
                            };

                            var exportCommand = new ExportPathCommand(exportParameters, _pathPlanningManager);
                            var result = await exportCommand.ExecuteAsync();

                            if (result.IsSuccess)
                                exportedCount++;
                            else
                            {
                                failedCount++;
                                LogManager.Error($"导出路径失败 [{route.Name}]: {result.ErrorMessage}");
                            }
                        }

                        if (exportedCount > 0)
                        {
                            var msg = $"✅ 导出成功: {exportedCount} 个路径";
                            if (failedCount > 0)
                                msg += $" (失败 {failedCount} 个)";
                            UpdateMainStatus(msg);
                            DialogHelper.ShowAutoClosingMessageBox(
                                $"成功导出 {exportedCount} 个路径到: {outputDir}" +
                                (failedCount > 0 ? $"\n失败: {failedCount} 个路径" : ""),
                                "导出完成",
                                failedCount == 0 ? System.Windows.MessageBoxImage.Information : System.Windows.MessageBoxImage.Warning,
                                autoCloseMilliseconds: 4000);
                        }
                        else
                        {
                            UpdateMainStatus("❌ 导出失败");
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Error($"导出路径异常: {ex.Message}", ex);
                    UpdateMainStatus($"❌ 导出异常: {ex.Message}");
                }
                finally
                {
                    // 清除所有选中状态，避免下次导出残留
                    foreach (var r in PathRoutes)
                        r.IsSelected = false;
                }
            }, "导出路径");
        }

        /// <summary>
        /// 生成导航地图的纯业务逻辑方法
        /// </summary>
        /// <param name="renderStyle">渲染样式</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <param name="format">图像格式</param>
        /// <returns>生成的图像数据</returns>
        public Bitmap GenerateNavigationMap(ImageGenerationStyle renderStyle, int width, int height, ImageFormat format)
        {
            try
            {
                LogManager.Info($"开始生成导航地图: 样式={renderStyle}, 尺寸={width}x{height}, 格式={format}");

                // 创建导航地图生成器
                var generator = new NavigationMapGenerator();

                // 生成图像
                var bitmap = generator.GenerateNavigationMapImage(renderStyle, width, height);

                LogManager.Info($"导航地图生成成功: {width}x{height}像素");
                return bitmap;
            }
            catch (Exception ex)
            {
                LogManager.Error($"生成导航地图失败: {ex.Message}", ex);
                throw;
            }
        }

        #endregion

        #endregion

        #region 事件处理

        /// <summary>
        /// 处理自动路径规划的鼠标点击事件
        /// </summary>
        private async void OnAutoPathMouseClicked(object sender, PickItemResult pickResult)
        {
            try
            {
                if (pickResult == null)
                {
                    return;
                }

                var point3D = pickResult.Point;

                if (IsSelectingStartPoint)
                {
                    SetAutoPathStartPoint(point3D);
                    await SafeExecuteAsync(() =>
                    {
                        // 退出自动路径规划模式 - 恢复事件订阅
                        LogManager.Info("起点选择完成,恢复正常事件订阅状态");
                        CleanupAutoPathEventSubscriptions();
                        _pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
                        _pathPlanningManager?.StopClickTool();
                    }, "停止起点选择工具");
                }
                else if (IsSelectingEndPoint)
                {
                    SetAutoPathEndPoint(point3D);
                    await SafeExecuteAsync(() =>
                    {
                        // 退出自动路径规划模式 - 恢复事件订阅
                        LogManager.Info("终点选择完成,恢复正常事件订阅状态");
                        CleanupAutoPathEventSubscriptions();
                        _pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
                        _pathPlanningManager?.StopClickTool();
                    }, "停止终点选择工具");
                }
                else
                {
                    CleanupAutoPathEventSubscriptions();
                    _pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[自动路径事件] 处理点击事件异常: {ex.Message}");
                UpdateMainStatus($"获取点击位置失败: {ex.Message}");

                IsSelectingStartPoint = false;
                IsSelectingEndPoint = false;

                // 异常情况下也要清理事件订阅并恢复状态
                try
                {
                    CleanupAutoPathEventSubscriptions();
                    _pathPlanningManager?.EnableMouseHandling(); // 恢复PathPlanningManager的鼠标处理
                    _pathPlanningManager?.StopClickTool();
                }
                catch (Exception cleanupEx)
                {
                    LogManager.Error($"[自动路径事件] 清理异常: {cleanupEx.Message}");
                }
            }
        }

        /// <summary>
        /// 设置自动路径规划的起点
        /// </summary>
        public async void SetAutoPathStartPoint(Point3D point)
        {
            await SafeExecuteAsync(() =>
            {
                // 直接设置新的起点(清理逻辑已在ExecuteSelectStartPointAsync中处理)
                _startPoint3D = point;
                _hasStartPoint = true;
                AutoPathStartPoint = $"({point.X:F2}, {point.Y:F2}, {point.Z:F2})";
                IsSelectingStartPoint = false;

                // 通知Can Execute属性更改
                OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                OnPropertyChanged(nameof(CanExecuteNewPath));
                OnPropertyChanged(nameof(CanExecuteNewFreePath));

                // 渲染新的起点标记
                if (PathPointRenderPlugin.Instance != null)
                {
                    // 创建临时路径只包含起点
                    _autoPathStartPointRoute = new PathRoute("AutoPathStartPoint")
                    {
                        Description = "自动路径规划起点"
                    };
                    var startPathPoint = new PathPoint
                    {
                        Name = "起点",
                        Position = point,
                        Type = PathPointType.StartPoint
                    };
                    _autoPathStartPointRoute.AddPoint(startPathPoint);

                    // 使用新的只渲染点的API,不绘制连线
                    PathPointRenderPlugin.Instance.RenderPointOnly(_autoPathStartPointRoute);
                    LogManager.Info($"起点路径已创建,ID: {_autoPathStartPointRoute.Id}");
                }

                if (_hasEndPoint)
                {
                    UpdateMainStatus("起点和终点已设置,可以开始路径规划");
                }
                else
                {
                    UpdateMainStatus("起点已设置,请选择终点");
                }

                LogManager.Info($"起点已设置: ({point.X:F2}, {point.Y:F2}, {point.Z:F2})");
            }, "设置起点");
        }

        /// <summary>
        /// 设置自动路径规划的终点
        /// </summary>
        public async void SetAutoPathEndPoint(Point3D point)
        {
            await SafeExecuteAsync(() =>
            {
                // 直接设置新的终点(清理逻辑已在ExecuteSelectEndPointAsync中处理)
                _endPoint3D = point;
                _hasEndPoint = true;
                AutoPathEndPoint = $"({point.X:F2}, {point.Y:F2}, {point.Z:F2})";
                IsSelectingEndPoint = false;

                // 通知Can Execute属性更改
                OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
                OnPropertyChanged(nameof(CanExecuteNewPath));
                OnPropertyChanged(nameof(CanExecuteNewFreePath));

                // 渲染新的终点标记
                if (PathPointRenderPlugin.Instance != null)
                {
                    // 创建临时路径只包含终点
                    _autoPathEndPointRoute = new PathRoute("AutoPathEndPoint")
                    {
                        Description = "自动路径规划终点"
                    };
                    var endPathPoint = new PathPoint
                    {
                        Name = "终点",
                        Position = point,
                        Type = PathPointType.EndPoint
                    };
                    _autoPathEndPointRoute.AddPoint(endPathPoint);

                    // 使用新的只渲染点的API,不绘制连线
                    PathPointRenderPlugin.Instance.RenderPointOnly(_autoPathEndPointRoute);
                    LogManager.Info($"终点路径已创建,ID: {_autoPathEndPointRoute.Id}");
                }

                if (_hasStartPoint)
                {
                    UpdateMainStatus("起点和终点已设置,可以开始路径规划");
                }
                else
                {
                    UpdateMainStatus("终点已设置,请选择起点");
                }

                LogManager.Info($"终点已设置: ({point.X:F2}, {point.Y:F2}, {point.Z:F2})");
            }, "设置终点");
        }

        #endregion

        #region 物体参数同步

        /// <summary>
        /// 同步物体参数到渲染插件
        /// </summary>
        private void SyncObjectParametersToRenderPlugin()
        {
            try
            {
                if (PathPointRenderPlugin.Instance != null)
                {
                    // 检查检测动画页签是否选择了物体或使用了虚拟物体
                    // 如果有,使用动画页签的物体参数来更新通行空间(而不是跳过)
                    var animationVm = AnimationControlViewModel.Instance;
                    if (animationVm != null && animationVm.HasSelectedAnimatedObject)
                    {
                        // 动画页签已选择物体,使用动画页签的物体尺寸和当前路径的类型
                        LogManager.Debug("[物体参数同步] 检测动画页签已选择动画对象,使用动画页签的物体尺寸");
                        SyncAnimationViewObjectParameters(animationVm);
                        return;
                    }

                    // 将米单位转换为模型单位(SetPassageSpaceParameters需要模型单位)
                    var metersToUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
                    double objectLengthModel = ObjectLength * metersToUnits;
                    double objectWidthModel = ObjectWidth * metersToUnits;
                    double objectHeightModel = ObjectHeight * metersToUnits;
                    double safetyMarginModel = SafetyMargin * metersToUnits;

                    // 根据路径类型计算通行空间尺寸
                    double passageAcrossPath, passageNormalToPath, passageAlongPath;
                    PathType pathType = SelectedPathRoute?.PathType ?? PathType.Ground;

                    if (pathType == PathType.Rail)
                    {
                        // 空轨路径:物体水平悬挂,垂直于路径的截面包含物体的宽度和高度
                        passageAcrossPath = objectWidthModel + 2 * safetyMarginModel; // Y方向(宽度)+ 2*间隙(垂直于路径方向)
                        passageNormalToPath = objectHeightModel + 2 * safetyMarginModel; // Z方向(高度)+ 2*间隙(法线方向)
                        passageAlongPath = objectLengthModel; // X方向(长度)(沿路径方向)
                    }
                    else if (pathType == PathType.Hoisting)
                    {
                        // 吊装路径:物体垂直悬挂,垂直于路径的截面包含物体的长度和宽度
                        passageAcrossPath = objectWidthModel + 2 * safetyMarginModel; // Y方向(宽度)+ 2*间隙(垂直于路径方向)
                        passageNormalToPath = objectLengthModel + 2 * safetyMarginModel; // X方向(长度)+ 2*间隙(法线方向)
                        passageAlongPath = objectHeightModel; // Z方向(高度)(沿路径方向)
                    }
                    else // Ground
                    {
                        // 地面路径:高度只有上方加间隙
                        passageAcrossPath = objectWidthModel + 2 * safetyMarginModel; // Y方向(宽度)+ 2*间隙(垂直于路径方向)
                        passageNormalToPath = objectHeightModel + safetyMarginModel; // Z方向(高度)+ 间隙(法线方向,只有上方)
                        passageAlongPath = objectLengthModel; // X方向(长度)(沿路径方向)
                    }

                    // 设置通行空间参数到渲染插件
                    // passageNormalToPathVertical: 垂直段的高度(物体长度 + 2×安全间隙)
                    // passageNormalToPathHorizontal: 水平段的高度(物体高度 + 2×安全间隙)
                    double passageNormalToPathVertical = objectLengthModel + 2 * safetyMarginModel;
                    double passageNormalToPathHorizontal = objectHeightModel + 2 * safetyMarginModel;
                    PathPointRenderPlugin.Instance.SetPassageSpaceParameters(
                        passageAcrossPath,
                        passageNormalToPath,
                        passageAlongPath,
                        passageNormalToPathVertical,
                        passageNormalToPathHorizontal);
                    LogManager.Debug($"[物体参数同步] 已设置通行空间参数: 垂直路径={passageAcrossPath / metersToUnits:F2}m, 法线={passageNormalToPath / metersToUnits:F2}m, 沿路径={passageAlongPath / metersToUnits:F2}m, 间隙={SafetyMargin:F2}m");
                }
                else
                {
                    LogManager.Warning("[物体参数同步] PathPointRenderPlugin实例为空,无法同步物体参数");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[物体参数同步] 同步物体参数失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 使用动画页签的物体参数同步到渲染插件
        /// </summary>
        private void SyncAnimationViewObjectParameters(AnimationControlViewModel animationVm)
        {
            try
            {
                // 获取当前路径类型(使用路径编辑页签的当前选择)
                PathType pathType = SelectedPathRoute?.PathType ?? PathType.Ground;

                // 获取单位转换因子
                var metersToUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
                double safetyMarginModel = SafetyMargin * metersToUnits;

                double objectLengthModel, objectWidthModel, objectHeightModel;

                if (animationVm.UseVirtualObject)
                {
                    // 使用虚拟物体尺寸
                    objectLengthModel = animationVm.VirtualObjectLengthInMeters * metersToUnits;
                    objectWidthModel = animationVm.VirtualObjectWidthInMeters * metersToUnits;
                    objectHeightModel = animationVm.VirtualObjectHeightInMeters * metersToUnits;
                    LogManager.Debug($"[物体参数同步] 使用虚拟物体尺寸: {animationVm.VirtualObjectLengthInMeters:F2}m x {animationVm.VirtualObjectWidthInMeters:F2}m x {animationVm.VirtualObjectHeightInMeters:F2}m");
                }
                else if (animationVm.SelectedAnimatedObject != null)
                {
                    // 优先使用 AnimationControlViewModel 的实测 AABB 缓存
                    // （贴合地面/自动调整后设置），避免 correction 投影失真
                    if (animationVm.TryGetCachedAabbSizes(out double cachedFwd, out double cachedSide, out double cachedUp))
                    {
                        objectLengthModel = cachedFwd;
                        objectWidthModel = cachedSide;
                        objectHeightModel = cachedUp;
                        LogManager.Debug(
                            $"[物体参数同步] 复用贴合地面/自动调整实测AABB: " +
                            $"沿路径={cachedFwd / metersToUnits:F2}m, " +
                            $"垂直路径={cachedSide / metersToUnits:F2}m, " +
                            $"法线={cachedUp / metersToUnits:F2}m");
                    }
                    else
                    {
                        var animationManager = NavisworksTransport.Core.Animation.PathAnimationManager.GetInstance();
                        if ((pathType == PathType.Ground || pathType == PathType.Hoisting) &&
                            animationManager != null &&
                            animationManager.TryGetCurrentRouteRealObjectPlanarProjectedExtents(
                                out double resolvedPlanarForward,
                                out double resolvedPlanarSide,
                                out double resolvedPlanarUp))
                        {
                            objectLengthModel = resolvedPlanarForward;
                            objectWidthModel = resolvedPlanarSide;
                            objectHeightModel = resolvedPlanarUp;
                            LogManager.Debug(
                                $"[物体参数同步] 使用真实物体平面路径最终姿态尺寸: " +
                                $"沿路径={resolvedPlanarForward / metersToUnits:F2}m, " +
                                $"垂直路径={resolvedPlanarSide / metersToUnits:F2}m, " +
                                $"法线={resolvedPlanarUp / metersToUnits:F2}m");
                        }
                        else if (pathType == PathType.Rail &&
                                 animationManager != null &&
                                 animationManager.TryGetCurrentRouteRealObjectRailProjectedExtents(
                                     out double resolvedRailForward,
                                     out double resolvedRailSide,
                                     out double resolvedRailUp))
                        {
                            objectLengthModel = resolvedRailForward;
                            objectWidthModel = resolvedRailSide;
                            objectHeightModel = resolvedRailUp;
                            LogManager.Debug(
                                $"[物体参数同步] 使用真实物体 Rail 最终姿态尺寸: " +
                                $"沿路径={resolvedRailForward / metersToUnits:F2}m, " +
                                $"垂直路径={resolvedRailSide / metersToUnits:F2}m, " +
                                $"法线={resolvedRailUp / metersToUnits:F2}m");
                        }
                        else
                        {
                            // 回退:使用选择物体时保存的原始尺寸(米)
                            objectLengthModel = animationVm.ObjectOriginalLength * metersToUnits;
                            objectWidthModel = animationVm.ObjectOriginalWidth * metersToUnits;
                            objectHeightModel = animationVm.ObjectOriginalHeight * metersToUnits;
                            LogManager.Debug(
                                $"[物体参数同步] 回退使用选择物体保存的原始尺寸: " +
                                $"{animationVm.ObjectOriginalLength:F2}m x {animationVm.ObjectOriginalWidth:F2}m x {animationVm.ObjectOriginalHeight:F2}m");
                        }
                    }
                }
                else
                {
                    // 没有物体,使用默认参数
                    LogManager.Warning("[物体参数同步] 动画页签已选择物体但实际无物体,使用默认参数");
                    objectLengthModel = ObjectLength * metersToUnits;
                    objectWidthModel = ObjectWidth * metersToUnits;
                    objectHeightModel = ObjectHeight * metersToUnits;
                }

                // 根据路径类型计算通行空间尺寸
                double passageAcrossPath, passageNormalToPath, passageAlongPath;

                if (pathType == PathType.Rail)
                {
                    passageAcrossPath = objectWidthModel + 2 * safetyMarginModel;
                    passageNormalToPath = objectHeightModel + 2 * safetyMarginModel;
                    passageAlongPath = objectLengthModel;
                }
                else if (pathType == PathType.Hoisting)
                {
                    passageAcrossPath = objectWidthModel + 2 * safetyMarginModel;
                    passageNormalToPath = objectLengthModel + 2 * safetyMarginModel;
                    passageAlongPath = objectHeightModel;
                }
                else // Ground
                {
                    passageAcrossPath = objectWidthModel + 2 * safetyMarginModel;
                    passageNormalToPath = objectHeightModel + safetyMarginModel;
                    passageAlongPath = objectLengthModel;
                }

                // 设置通行空间参数到渲染插件
                double passageNormalToPathVertical = objectLengthModel + 2 * safetyMarginModel;
                double passageNormalToPathHorizontal = objectHeightModel + 2 * safetyMarginModel;
                PathPointRenderPlugin.Instance.SetPassageSpaceParameters(
                    passageAcrossPath,
                    passageNormalToPath,
                    passageAlongPath,
                    passageNormalToPathVertical,
                    passageNormalToPathHorizontal);
                LogManager.Debug($"[物体参数同步] 已使用动画页签物体参数设置通行空间: 类型={pathType}, 沿路径={passageAlongPath / metersToUnits:F2}m, 垂直路径={passageAcrossPath / metersToUnits:F2}m");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[物体参数同步] 同步动画页签物体参数失败: {ex.Message}", ex);
            }
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 安全执行异步操作
        /// </summary>
        private async Task SafeExecuteAsync(Func<Task> action, string operationName = "未知操作")
        {
            try
            {
                await action();
            }
            catch (Exception ex)
            {
                LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
                UpdateMainStatus($"{operationName}失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 网格可视化设置变更事件处理
        /// </summary>
        private void OnGridVisualizationChanged()
        {
            try
            {
                LogManager.Info($"网格可视化设置已更改: 通行={ShowWalkableGrid}, 障碍物={ShowObstacleGrid}, 未知={ShowUnknownGrid}, 门={ShowDoorGrid}");

                // 通知路径规划管理器更新网格可视化
                if (_pathPlanningManager != null)
                {
                    _pathPlanningManager.UpdateGridVisualizationSettings(
                        showWalkable: ShowWalkableGrid,
                        showObstacle: ShowObstacleGrid,
                        showUnknown: ShowUnknownGrid,
                        showDoor: ShowDoorGrid);

                    UpdateMainStatus("网格可视化设置已更新");
                }
                else
                {
                    LogManager.Warning("无法获取路径规划管理器,网格可视化设置可能不会立即生效");
                    UpdateMainStatus("网格可视化设置已保存");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"应用网格可视化设置失败: {ex.Message}", ex);
                UpdateMainStatus("网格可视化设置应用失败");
            }
        }

        /// <summary>
        /// 网格点类型变更事件处理
        /// </summary>
        private void OnGridPointTypeChanged()
        {
            try
            {
                LogManager.Info($"网格点类型已更改: {GridPointType}");

                // 通知路径点渲染插件更新网格点类型
                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin != null)
                {
                    renderPlugin.GridPointType = GridPointType;
                    UpdateMainStatus("网格点类型已更新");
                }
                else
                {
                    LogManager.Warning("无法获取PathPointRenderPlugin实例,网格点类型可能不会立即生效");
                    UpdateMainStatus("网格点类型已保存");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"应用网格点类型失败: {ex.Message}", ex);
                UpdateMainStatus("网格点类型应用失败");
            }
        }

        /// <summary>
        /// 根据路径类型自动设置可视化模式
        /// - 地面路径:控制点连线 + 路径线
        /// - 吊装和空轨:控制点连线 + 通行空间(不能使用路径线)
        /// </summary>
        private void UpdatePassageSpaceVisualizationForPathType(PathType pathType)
        {
            try
            {
                // 所有路径类型默认都打开控制点连线
                ShowControlVisualization = true;

                switch (pathType)
                {
                    case PathType.Rail:
                    case PathType.Hoisting:
                        // 空中路径:通行空间 + 控制点,不能使用路径线
                        ShowPathLines = false;
                        ShowObjectSpace = true;
                        LogManager.Debug($"[路径编辑] 路径类型={pathType}(空中路径),默认模式:控制点+通行空间");
                        break;

                    case PathType.Ground:
                        // 地面路径:路径线 + 控制点,不使用通行空间
                        ShowPathLines = true;
                        ShowObjectSpace = false;
                        LogManager.Debug($"[路径编辑] 路径类型={pathType}(地面路径),默认模式:控制点+路径线");
                        break;

                    default:
                        LogManager.Warning($"[路径编辑] 未知的路径类型: {pathType}");
                        return;
                }

                LogManager.Info($"[路径编辑] 已根据路径类型自动设置可视化模式:控制点={ShowControlVisualization}, 路径线={ShowPathLines}, 通行空间={ShowObjectSpace}");

                // 🔥 触发可视化状态变更事件,通知状态栏刷新按钮
                _pathPlanningManager?.RaiseVisualizationStateChanged();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[路径编辑] 设置可视化模式失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 路径可视化模式变更事件处理
        /// </summary>
        private void OnPathVisualizationModeChanged()
        {
            try
            {
                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin != null)
                {
                    // 使用新的独立开关设置渲染插件
                    renderPlugin.ShowPathLines = ShowPathLines;
                    renderPlugin.ShowObjectSpace = ShowObjectSpace;

                    string modeName = "";
                    if (ShowPathLines && ShowObjectSpace)
                        modeName = "路径线 + 通行空间";
                    else if (ShowPathLines)
                        modeName = "路径线";
                    else if (ShowObjectSpace)
                        modeName = "通行空间";
                    else
                        modeName = "无路径可视化";

                    // 🔥 触发视图刷新
                    if (NavisApplication.ActiveDocument?.ActiveView != null)
                    {
                        NavisApplication.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render);
                    }

                    LogManager.Info($"路径可视化模式已更改: {modeName}");
                    UpdateMainStatus($"路径可视化: {modeName}");
                }
                else
                {
                    LogManager.Warning("无法获取PathPointRenderPlugin实例");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"应用路径可视化模式失败: {ex.Message}", ex);
                UpdateMainStatus("路径可视化模式更新失败");
            }
        }

        /// <summary>
        /// 控制点可视化变更事件处理
        /// </summary>
        private void OnControlVisualizationChanged()
        {
            try
            {
                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin != null)
                {
                    // 更新所有路径的 ShowControlVisualization 属性
                    lock (typeof(PathPointRenderPlugin))
                    {
                        var allVisualizations = renderPlugin.GetAllPathVisualizations();
                        foreach (var visualization in allVisualizations)
                        {
                            visualization.ShowControlVisualization = ShowControlVisualization;
                        }
                    }

                    // 触发视图刷新
                    if (NavisApplication.ActiveDocument?.ActiveView != null)
                    {
                        NavisApplication.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render);
                    }

                    LogManager.Info($"控制点可视化已更改: {(ShowControlVisualization ? "显示" : "隐藏")}");
                    UpdateMainStatus("控制点可视化已更新");
                }
                else
                {
                    LogManager.Warning("无法获取PathPointRenderPlugin实例");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"应用控制点可视化设置失败: {ex.Message}", ex);
                UpdateMainStatus("控制点可视化设置失败");
            }
        }

        /// <summary>
        /// 清理自动路径相关的事件订阅
        /// </summary>
        private void CleanupAutoPathEventSubscriptions()
        {
            try
            {
                // 简单安全地移除事件订阅
                // 由于C#事件处理机制,多次取消订阅同一个处理程序是安全的
                // 即使处理程序未订阅,取消操作也不会抛出异常
                PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[事件清理] 清理自动路径事件订阅失败: {ex.Message}", ex);
                // 记录异常但不抛出,避免影响主流程
            }
        }

        /// <summary>
        /// 清理临时的自动路径起点和终点标记
        /// </summary>
        private void ClearTemporaryAutoPathMarkers()
        {
            try
            {
                if (PathPointRenderPlugin.Instance != null)
                {
                    // 清除临时的起点标记(使用正确的路径ID)
                    if (_autoPathStartPointRoute != null)
                    {
                        PathPointRenderPlugin.Instance.RemovePath(_autoPathStartPointRoute.Id);
                        _autoPathStartPointRoute = null;
                    }

                    // 清除临时的终点标记(使用正确的路径ID)
                    if (_autoPathEndPointRoute != null)
                    {
                        PathPointRenderPlugin.Instance.RemovePath(_autoPathEndPointRoute.Id);
                        _autoPathEndPointRoute = null;
                    }

                }
                else
                {
                    LogManager.Warning("[临时标记清理] PathPointRenderPlugin实例为null,无法清理标记");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[临时标记清理] 清理临时标记失败: {ex.Message}");
            }
        }

        #endregion

        #region PathPlanningManager事件处理

        /// <summary>
        /// 订阅PathPlanningManager事件
        /// </summary>
        private void SubscribeToPathPlanningManager()
        {
            if (_pathPlanningManager == null)
            {
                LogManager.Debug("PathPlanningManager尚未设置,跳过事件订阅");
                return;
            }

            try
            {
                // 订阅路径点操作事件(用于手工路径编辑)
                _pathPlanningManager.PathPointOperation += OnPathPointOperation;

                // 订阅路径点列表更新事件
                _pathPlanningManager.PathPointsListUpdated += OnPathPointsListUpdated;

                // 订阅当前路径变更事件
                _pathPlanningManager.CurrentRouteChanged += OnCurrentRouteChanged;

                // 订阅编辑状态变更事件
                _pathPlanningManager.EditStateChanged += OnEditStateChanged;

                // 订阅路径生成事件(用于处理自动路径)
                _pathPlanningManager.RouteGenerated += OnRouteGenerated;

                // 订阅路径加载完成事件(用于处理数据库加载的路径)
                _pathPlanningManager.RoutesLoaded += OnRoutesLoaded;

                // 添加错误事件订阅 - 用于处理自动路径规划失败等错误
                _pathPlanningManager.ErrorOccurred += OnPathPlanningError;

                LogManager.Debug("PathEditingViewModel已成功订阅PathPlanningManager事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"*** 订阅PathPlanningManager事件失败: {ex.Message} ***", ex);
            }
        }

        /// <summary>
        /// 取消订阅PathPlanningManager事件
        /// </summary>
        private void UnsubscribeFromPathPlanningManager()
        {
            if (_pathPlanningManager == null) return;

            try
            {
                _pathPlanningManager.PathPointOperation -= OnPathPointOperation;
                _pathPlanningManager.PathPointsListUpdated -= OnPathPointsListUpdated;
                _pathPlanningManager.CurrentRouteChanged -= OnCurrentRouteChanged;
                _pathPlanningManager.EditStateChanged -= OnEditStateChanged;
                _pathPlanningManager.RouteGenerated -= OnRouteGenerated;
                _pathPlanningManager.RoutesLoaded -= OnRoutesLoaded;
                _pathPlanningManager.ErrorOccurred -= OnPathPlanningError;

                LogManager.Info("PathEditingViewModel已取消订阅PathPlanningManager事件,包括ErrorOccurred");
            }
            catch (Exception ex)
            {
                LogManager.Error($"取消订阅PathPlanningManager事件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 处理路径点操作事件(手工路径编辑的核心)
        /// </summary>
        private async void OnPathPointOperation(object sender, PathPointOperationEventArgs e)
        {
            if (e == null || e.PathPoint == null) return;

            try
            {
                await SafeExecuteAsync(() =>
                {
                    LogManager.Info($"PathEditingViewModel收到路径点操作事件: {e.OperationType}, 点: {e.PathPoint.Name}");

                    // 只处理手动编辑的路径点,跳过自动路径点
                    // 自动路径通过RouteGenerated事件处理
                    if (e.PathPoint.Name.Contains("自动"))
                    {
                        LogManager.Info($"跳过自动路径点,将通过RouteGenerated事件处理: {e.PathPoint.Name}");
                        return;
                    }

                    // 注意:不在这里直接添加/移除单个路径点到UI
                    // 因为PathPointsListUpdated事件会处理完整的路径同步
                    // 这里只做状态更新和选择管理

                    if (e.OperationType == PathPointOperationType.Added)
                    {
                        // 确保对应的路径在UI中存在并选中
                        var pathViewModel = PathRoutes.FirstOrDefault(p => p.Name == e.Route.Name);
                        if (pathViewModel != null)
                        {
                            // 设置为选中路径
                            SelectedPathRoute = pathViewModel;
                        }

                        UpdateMainStatus($"已添加路径点: {e.PathPoint.Name} 到 {e.Route.Name}");
                        LogManager.Info($"路径点操作完成: {e.PathPoint.Name} 已添加到路径 {e.Route.Name}");
                    }
                    else if (e.OperationType == PathPointOperationType.Removed)
                    {
                        UpdateMainStatus($"已移除路径点: {e.PathPoint.Name} 从 {e.Route.Name}");
                        LogManager.Info($"路径点操作完成: {e.PathPoint.Name} 已从路径 {e.Route.Name} 移除");
                    }
                }, "处理路径点操作事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"处理路径点操作事件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 处理路径点列表更新事件
        /// </summary>
        private async void OnPathPointsListUpdated(object sender, PathPointsListUpdatedEventArgs e)
        {
            if (e?.Route == null) return;

            try
            {
                await SafeExecuteAsync(() =>
                {
                    LogManager.Info($"路径点列表更新: {e.Route.Name}, 原因: {e.UpdateReason}");

                    // 刷新对应路径的显示
                    var pathViewModel = PathRoutes.FirstOrDefault(p => p.Name == e.Route.Name);
                    if (pathViewModel != null)
                    {
                        bool updated = SyncPathViewModelFromCoreRoute(pathViewModel, e.Route, preserveSelection: true);
                        if (!updated)
                        {
                            LogManager.Info($"路径点数据无变化({pathViewModel.Points.Count}),跳过更新");
                            return;
                        }

                        LogManager.Info($"已更新路径点列表,当前点数: {pathViewModel.Points.Count}");

                        if (SelectedPathRoute == pathViewModel)
                        {
                            RefreshHoistingLayerEditItemsFromSelectedRoute();
                        }

                        // 更新真实路径可视化
                        UpdatePathVisualization();
                    }
                    else
                    {
                        LogManager.Warning($"未找到对应的PathViewModel: {e.Route.Name}");
                    }
                }, "处理路径点列表更新事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"处理路径点列表更新事件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 处理当前路径变更事件
        /// </summary>
        private async void OnCurrentRouteChanged(object sender, CurrentRouteChangedEventArgs e)
        {
            try
            {
                await SafeExecuteAsync(() =>
                {
                    LogManager.Info($"当前路径变更: {e.PreviousRoute?.Name} -> {e.NewRoute?.Name}");

                    if (e.NewRoute != null)
                    {
                        // 查找并选中对应的路径ViewModel
                        var pathViewModel = PathRoutes.FirstOrDefault(p => p.Name == e.NewRoute.Name);
                        if (pathViewModel != null)
                        {
                            bool synced = SyncPathViewModelFromCoreRoute(pathViewModel, e.NewRoute, preserveSelection: true);
                            if (synced)
                            {
                                LogManager.Info($"当前路径切换时已同步路径点列表: {e.NewRoute.Name}, 点数: {pathViewModel.Points.Count}");
                            }

                            ApplyStoredAutoPlanningParameters(e.NewRoute);

                            // 只在真的不同时才设置,避免重复触发
                            if (SelectedPathRoute != pathViewModel)
                            {
                                SelectedPathRoute = pathViewModel;
                                LogManager.Info($"UI已同步选择路径: {e.NewRoute.Name}");
                            }
                        }
                        else
                        {
                            LogManager.Warning($"OnCurrentRouteChanged: UI中未找到路径 {e.NewRoute.Name},可能UI还未刷新");
                        }
                    }
                    else
                    {
                        // 当前路径被设为null,清除UI选择
                        if (SelectedPathRoute != null)
                        {
                            SelectedPathRoute = null;
                            LogManager.Info("UI已清除路径选择");
                        }
                    }
                }, "处理当前路径变更事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"处理当前路径变更事件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 处理编辑状态变更事件
        /// </summary>
        private async void OnEditStateChanged(object sender, PathEditStateChangedEventArgs e)
        {
            try
            {
                await SafeExecuteAsync(() =>
                {
                    LogManager.Info($"路径编辑状态变更: {e.PreviousState} -> {e.NewState}");

                    // 修复:包含 AddingPoints 和 EditingPoint 状态
                    IsPathEditMode = (e.NewState == PathEditState.Creating ||
                                    e.NewState == PathEditState.Editing ||
                                    e.NewState == PathEditState.AddingPoints ||
                                    e.NewState == PathEditState.EditingPoint);

                    LogManager.Info($"[UI状态更新] IsPathEditMode 设为: {IsPathEditMode}");

                    // 更新状态提示
                    switch (e.NewState)
                    {
                        case PathEditState.Creating:
                            UpdateMainStatus($"正在新建路径: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点");
                            break;
                        case PathEditState.Editing:
                            UpdateMainStatus($"正在编辑路径: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点");
                            break;
                        case PathEditState.AddingPoints:
                            UpdateMainStatus($"正在添加路径点到: {e.EditingRoute?.Name} - 请在3D视图中点击设置路径点");
                            break;
                        case PathEditState.EditingPoint:
                            UpdateMainStatus($"正在修改路径点: {e.EditingRoute?.Name} - 请在3D视图中点击新位置,然后点击'结束'确认");
                            break;
                        case PathEditState.Viewing:
                            // 如果当前状态包含路径规划完成信息(包括完成度百分比),则保留不覆盖
                            var currentStatus = _mainViewModel?.StatusText ?? "";
                            if (!currentStatus.Contains("路径规划完成") && !currentStatus.Contains("路径规划部分完成") &&
                                !currentStatus.Contains("✅") && !currentStatus.Contains("🔶"))
                            {
                                UpdateMainStatus("路径编辑已完成");
                            }
                            break;
                        default:
                            UpdateMainStatus("就绪");
                            break;
                    }

                    // 通知命令状态更新
                    OnPropertyChanged(nameof(CanExecuteNewPath));
                OnPropertyChanged(nameof(CanExecuteNewFreePath));
                    OnPropertyChanged(nameof(CanExecuteStartEdit));
                    OnPropertyChanged(nameof(CanExecuteEndEdit));
                    OnPropertyChanged(nameof(CanExecuteModifyPoint));
                    OnPropertyChanged(nameof(CanExecuteCancelModifyPoint));

                    LogManager.Info($"[UI状态更新] 按钮状态已通知更新 - CanExecuteStartEdit: {CanExecuteStartEdit}, CanExecuteEndEdit: {CanExecuteEndEdit}, CanExecuteModifyPoint: {CanExecuteModifyPoint}, CanExecuteCancelModifyPoint: {CanExecuteCancelModifyPoint}");
                }, "处理编辑状态变更事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"处理编辑状态变更事件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 处理路径生成事件(用于自动路径)
        /// </summary>
        private async void OnRouteGenerated(object sender, RouteGeneratedEventArgs e)
        {
            // 添加调试日志确认事件是否被调用
            LogManager.Info($"*** OnRouteGenerated被调用!Sender: {sender?.GetType().Name}, Route: {e?.Route?.Name}, Method: {e?.GenerationMethod}, GridSize: {e?.GridSize} ***");

            if (e?.Route == null)
            {
                LogManager.Warning("*** OnRouteGenerated: RouteGeneratedEventArgs或Route为null,退出处理 ***");
                return;
            }

            try
            {
                await SafeExecuteAsync(() =>
                {
                    LogManager.Info($"PathEditingViewModel收到路径生成事件: {e.Route.Name}, 生成方式: {e.GenerationMethod}");

                    // 处理自动路径生成
                    if (e.GenerationMethod == RouteGenerationMethod.AutoPlanning)
                    {
                        LogManager.Info($"*** 开始处理自动路径生成: {e.Route.Name} ***");

                        // 创建对应的 WPF ViewModel
                        var autoPathViewModel = new PathRouteViewModel(isFromDatabase: true)
                        {
                            Route = e.Route,
                            IsActive = true
                        };

                        // 设置时间信息
                        autoPathViewModel.SetTimeInfo(e.Route.CreatedTime, e.Route.LastModified);

                        // 使用统一的辅助方法创建路径点
                        var pathPoints = CreatePathPointViewModelsFromCoreRoute(e.Route);
                        foreach (var point in pathPoints)
                        {
                            autoPathViewModel.Points.Add(point);
                        }

                        LogManager.Info($"*** 已创建PathRouteViewModel,包含 {autoPathViewModel.Points.Count} 个点 ***");

                        // 检查是否已存在同名路径,避免重复添加
                        var existingPath = PathRoutes.FirstOrDefault(p => p.Name == e.Route.Name);
                        if (existingPath == null)
                        {
                            // 添加到 UI 列表并选中
                            PathRoutes.Add(autoPathViewModel);
                            SelectedPathRoute = autoPathViewModel;

                            LogManager.Info($"*** 自动路径已添加到UI列表: {e.Route.Name},当前PathRoutes.Count = {PathRoutes.Count} ***");
                        }
                        else
                        {
                            // 更新现有路径
                            existingPath.Points.Clear();
                            foreach (var wpfPoint in autoPathViewModel.Points)
                            {
                                existingPath.Points.Add(wpfPoint);
                            }
                            SelectedPathRoute = existingPath;

                            LogManager.Info($"*** 自动路径已更新UI列表: {e.Route.Name} ***");
                        }

                        // 构建包含网格信息和完成度的完整状态消息,使用事件参数中的网格大小信息
                        var gridInfo = e.GridSize > 0 ? $"网格{e.GridSize:F1}m" : "自动网格";
                        string statusMessage;

                        if (e.Route.IsComplete)
                        {
                            // 完全到达终点
                            statusMessage = $"✅ 自动路径规划完成: {e.Route.Name},共 {e.Route.Points.Count} 个路径点,长度 {e.Route.TotalLength:F2}米";
                        }
                        else
                        {
                            // 部分到达终点
                            statusMessage = $"🔶 自动路径规划部分完成: {e.Route.Name},共 {e.Route.Points.Count} 个路径点,长度 {e.Route.TotalLength:F2}米,(完成度: {e.Route.CompletionPercentage:F1}%)";
                        }

                        UpdateMainStatus(statusMessage);
                        LogManager.Info($"*** 状态已更新: {statusMessage} ***");
                    }
                    else if (e.GenerationMethod == RouteGenerationMethod.Manual)
                    {
                        LogManager.Info($"手工路径生成完成: {e.Route.Name},开始刷新路径列表");
                        var existingPath = PathRoutes.FirstOrDefault(p => p.Name == e.Route.Name);
                        if (existingPath == null)
                        {
                            existingPath = new PathRouteViewModel(isFromDatabase: true)
                            {
                                Route = e.Route,
                                IsActive = true
                            };
                            PathRoutes.Add(existingPath);
                            LogManager.Info($"手工路径生成后补建UI路径壳: {e.Route.Name}");
                        }

                        SyncPathViewModelFromCoreRoute(existingPath, e.Route, preserveSelection: true);
                        SelectedPathRoute = existingPath;
                        LogManager.Info($"手工路径已同步并重新选中: {e.Route.Name},点数: {existingPath.Points.Count}");

                        OnPropertyChanged(nameof(PathRoutes));
                        OnPropertyChanged(nameof(CanExecuteStartEdit));
                        OnPropertyChanged(nameof(CanExecuteEndEdit));
                    }
                    else if (e.GenerationMethod == RouteGenerationMethod.DatabaseLoad)
                    {
                        // 注意:DatabaseLoad现在由OnRoutesLoaded事件处理,这里不再处理
                        LogManager.Warning($"*** OnRouteGenerated收到DatabaseLoad方法,这不应该发生!应该由OnRoutesLoaded处理 ***");
                    }
                }, "处理路径生成事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"*** OnRouteGenerated异常: {ex.Message} ***", ex);
            }
        }

        /// <summary>
        /// 处理路径加载完成事件(用于数据库加载)
        /// </summary>
        private async void OnRoutesLoaded(object sender, RoutesLoadedEventArgs e)
        {
            LogManager.Info($"*** OnRoutesLoaded被调用!Sender: {sender?.GetType().Name}, RouteCount: {e?.RouteCount}, LoadSource: {e?.LoadSource} ***");

            if (e?.Routes == null)
            {
                LogManager.Warning("*** OnRoutesLoaded: RoutesLoadedEventArgs或Routes为null,退出处理 ***");
                return;
            }

            try
            {
                await SafeExecuteAsync(() =>
                {
                    LogManager.Info($"PathEditingViewModel收到路径加载完成事件: 加载了 {e.RouteCount} 条路径,来源: {e.LoadSource}");

                    // 处理从数据库加载的历史路径
                    foreach (var coreRoute in e.Routes)
                    {
                        // 创建对应的 WPF ViewModel
                        var dbPathViewModel = new PathRouteViewModel(isFromDatabase: true)
                        {
                            Route = coreRoute,
                            IsActive = false,  // 历史路径默认不激活
                            PathType = coreRoute.PathType
                        };

                        // 设置时间信息
                        dbPathViewModel.SetTimeInfo(coreRoute.CreatedTime, coreRoute.LastModified);

                        // 使用统一的辅助方法创建路径点
                        var pathPoints = CreatePathPointViewModelsFromCoreRoute(coreRoute);
                        foreach (var point in pathPoints)
                        {
                            dbPathViewModel.Points.Add(point);
                        }

                        // 检查是否已存在同名路径,避免重复添加
                        var existingPath = PathRoutes.FirstOrDefault(p => p.Name == coreRoute.Name);
                        if (existingPath == null)
                        {
                            // 添加到 UI 列表
                            PathRoutes.Add(dbPathViewModel);
                        }
                        else
                        {
                            LogManager.Debug($"*** 数据库路径已存在,跳过: {coreRoute.Name} ***");
                        }
                    }

                    var currentRoute = _pathPlanningManager?.CurrentRoute;
                    if (currentRoute != null)
                    {
                        ApplyStoredAutoPlanningParameters(currentRoute);
                        LogManager.Info($"路径加载完成后已按当前路径同步自动规划参数: {currentRoute.Name}");
                    }

                    // 更新状态消息
                    string statusMessage = $"✅ 已从{e.LoadSource}加载 {e.RouteCount} 条历史路径";
                    UpdateMainStatus(statusMessage);

                    // 自动提取并显示所有空轨模型的基准线
                    ExtractAndRenderRailBaselinePaths();
                }, "处理路径加载完成事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"*** OnRoutesLoaded异常: {ex.Message} ***", ex);
            }
        }

        /// <summary>
        /// 处理路径规划错误事件
        /// </summary>
        /// <summary>
        /// 处理路径规划错误事件
        /// </summary>
        /// <summary>
        /// 处理路径规划错误事件
        /// </summary>
        private async void OnPathPlanningError(object sender, PathPlanningErrorOccurredEventArgs e)
        {
            LogManager.Info($"*** OnPathPlanningError被调用!Sender: {sender?.GetType().Name}, Error: {e?.ErrorMessage}, Level: {e?.ErrorLevel} ***");

            try
            {
                await SafeExecuteAsync(async () =>
                {
                    // 根据错误级别决定日志记录方式
                    if (e.ErrorLevel == PathPlanningErrorLevel.Warning)
                    {
                        LogManager.Warning($"自动路径规划失败: {e.ErrorMessage}");
                    }
                    else
                    {
                        LogManager.Error($"自动路径规划失败: {e.ErrorMessage}");
                    }

                    // 使用UIStateManager确保UI更新在主线程执行
                    await _uiStateManager.ExecuteUIUpdateAsync(() =>
                    {
                        // 更新自动路径状态显示错误信息
                        UpdateMainStatus($"❌ 自动路径规划失败: {e.ErrorMessage}");
                        LogManager.Info($"*** 状态已更新为: ❌ 自动路径规划失败: {e.ErrorMessage} ***");
                    });

                }, "处理路径规划错误事件");
            }
            catch (Exception ex)
            {
                LogManager.Error($"*** OnPathPlanningError异常: {ex.Message} ***", ex);
            }
        }

        #endregion


        #region 清理资源

        /// <summary>
        /// 强制重新初始化ToolPlugin以确保获得鼠标焦点
        /// </summary>
        /// <param name="subscribeToEvents">是否订阅鼠标事件,新建路径需要true,自动路径选点需要false</param>
        /// <returns>初始化是否成功</returns>
        private bool ForceReinitializeToolPlugin(bool subscribeToEvents = false)
        {
            try
            {
                LogManager.Info($"开始强制重新初始化ToolPlugin以确保获得鼠标焦点,订阅事件: {subscribeToEvents}");

                // 使用PathPlanningManager的公共方法,避免反射调用
                if (_pathPlanningManager != null)
                {
                    bool result = _pathPlanningManager.ForceReinitializeToolPlugin(subscribeToEvents);
                    LogManager.Info($"ToolPlugin重新初始化结果(事件订阅: {subscribeToEvents}): {result}");

                    if (result)
                    {
                        LogManager.Info("ToolPlugin重新初始化成功,已获得鼠标焦点");
                    }
                    else
                    {
                        LogManager.Error("ToolPlugin初始化失败");
                    }

                    return result;
                }
                else
                {
                    LogManager.Error("PathPlanningManager为null,无法重新初始化ToolPlugin");
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"重新初始化ToolPlugin失败: {ex.Message}", ex);
                return false;
            }
        }

        public void Cleanup()
        {
            try
            {
                LogManager.Info("开始清理PathEditingViewModel资源");

                // 取消配置变更事件订阅
                UnsubscribeFromConfigChanges();

                // 取消事件订阅
                UnsubscribeFromPathPlanningManager();

                // 完整清理自动路径规划相关的事件订阅
                try
                {
                    CleanupAutoPathEventSubscriptions();
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"清理自动路径事件订阅时发生异常: {ex.Message}");
                }

                try
                {
                    CleanupAssemblyReferenceSelection();
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"清理直线装配事件订阅时发生异常: {ex.Message}");
                }

                try
                {
                    CleanupAssemblyEndFaceSelection(clearVisuals: true);
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"清理端面三点分析事件订阅时发生异常: {ex.Message}");
                }

                try
                {
                    ClearAssemblyAnchorMarker();
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"清理直线装配对接点标记时发生异常: {ex.Message}");
                }

                try
                {
                    ClearAssemblyReferenceLine();
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"清理直线装配参考线时发生异常: {ex.Message}");
                }

                // 确保停止任何活动的点击工具
                try
                {
                    if (_pathPlanningManager != null)
                    {
                        _pathPlanningManager.StopClickTool();
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"停止点击工具时发生异常: {ex.Message}");
                }

                LogManager.Info("PathEditingViewModel资源清理完成");
            }
            catch (Exception ex)
            {
                LogManager.Error($"PathEditingViewModel清理失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 释放资源 (IDisposable implementation)
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放托管和非托管资源
        /// </summary>
        /// <param name="disposing">是否释放托管资源</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    try
                    {
                        // 调用现有的清理逻辑
                        Cleanup();
                        LogManager.Info("PathEditingViewModel已正确释放资源 (IDisposable)");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"PathEditingViewModel释放资源时发生异常: {ex.Message}", ex);
                    }
                }
                _disposed = true;
            }
        }

        #endregion
    }

    /// <summary>
    /// 物体参数类 - 用于传递物体尺寸信息给路径规划算法
    /// </summary>
    public class ObjectParameters
    {
        public double Length { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }
        public double SafetyMargin { get; set; }
    }
}
