NavisworksTransport/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs

3817 lines
152 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using System.Linq;
using System.Threading.Tasks;
using Autodesk.Navisworks.Api;
using NavisApplication = Autodesk.Navisworks.Api.Application;
using NavisworksTransport.Core;
using NavisworksTransport.Commands;
using NavisworksTransport.UI.WPF.Collections;
using NavisworksTransport.UI.WPF.Models;
using NavisworksTransport.Utils;
namespace NavisworksTransport.UI.WPF.ViewModels
{
/// <summary>
/// 物流控制面板主ViewModel
/// </summary>
public class LogisticsControlViewModel : ViewModelBase
{
#region
private string _selectedModelsText;
private string _instructionText;
private string _statusText;
private ObservableCollection<LogisticsModel> _logisticsModels;
private LogisticsModel _selectedLogisticsModel;
private ObservableCollection<PathRouteViewModel> _pathRoutes;
private PathRouteViewModel _selectedPathRoute;
private bool _isPathEditMode;
private string _animationStatus;
private double _animationProgress;
private ObservableCollection<string> _availableCategories;
private string _selectedCategory;
private double _widthLimit;
private string _pathFileStatus;
private PathPlanningManager _pathPlanningManager;
private bool _isLogisticsOnlyMode = false;
// UI状态管理和命令框架
private readonly UIStateManager _uiStateManager;
private readonly NavisworksTransport.Commands.CommandManager _commandManager;
// 动画参数相关字段
private double _animationSpeed = 1.0;
private ObservableCollection<int> _availableFrameRates;
private int _selectedFrameRate = 30;
private double _animationDuration = 10.0;
private bool _isLoopEnabled = false;
private bool _isSmoothTransition = true;
private double _currentAnimationTime = 0.0;
private bool _canStartAnimation = true;
private bool _canPauseAnimation = false;
private bool _canStopAnimation = false;
// 碰撞检测相关字段
private bool _canRunCollisionDetection = true;
private bool _hasCollisionResults = false;
private string _collisionStatus = "就绪";
private string _collisionSummary = "尚未运行碰撞检测";
// 系统管理相关字段
private string _modelSplitterStatus = "就绪";
private ObservableCollection<string> _logLevels;
private string _selectedLogLevel = "Info";
private string _logStatus = "日志系统正常";
private bool _isAutoSaveEnabled = true;
private bool _isDebugModeEnabled = false;
private string _settingsStatus = "设置已加载";
private string _pluginVersion = "v1.0";
private string _navisworksVersion = "2026";
private string _systemStatus = "正常";
private string _systemStatusColor = "Green";
private string _memoryUsage = "0 MB";
private string _runningTime = "00:00:00";
private string _performanceInfo = "性能监控就绪";
// 自动路径规划相关字段
private string _autoPathStartPoint = "未选择";
private string _autoPathEndPoint = "未选择";
private double _autoPathVehicleSize = 1.0;
private double _autoPathSafetyMargin = 0.5;
private string _autoPathStatus = "就绪";
private Point3D _startPoint3D;
private Point3D _endPoint3D;
private bool _hasStartPoint = false;
private bool _hasEndPoint = false;
private bool _isSelectingStartPoint = false;
private bool _isSelectingEndPoint = false;
#endregion
#region
/// <summary>
/// 选中模型文本
/// </summary>
public string SelectedModelsText
{
get => _selectedModelsText;
set => SetProperty(ref _selectedModelsText, value);
}
/// <summary>
/// 指令文本
/// </summary>
public string InstructionText
{
get => _instructionText;
set => SetProperty(ref _instructionText, value);
}
/// <summary>
/// 状态文本
/// </summary>
public string StatusText
{
get => _statusText;
set => SetProperty(ref _statusText, value);
}
/// <summary>
/// 物流模型集合
/// </summary>
public ObservableCollection<LogisticsModel> LogisticsModels
{
get => _logisticsModels;
set => SetProperty(ref _logisticsModels, value);
}
/// <summary>
/// 选中的物流模型
/// </summary>
public LogisticsModel SelectedLogisticsModel
{
get => _selectedLogisticsModel;
set => SetProperty(ref _selectedLogisticsModel, value);
}
/// <summary>
/// 路径集合
/// </summary>
public ObservableCollection<PathRouteViewModel> PathRoutes
{
get => _pathRoutes;
set => SetProperty(ref _pathRoutes, value);
}
/// <summary>
/// 选中的路径
/// </summary>
public PathRouteViewModel SelectedPathRoute
{
get => _selectedPathRoute;
set => SetProperty(ref _selectedPathRoute, value);
}
/// <summary>
/// 是否处于路径编辑模式
/// </summary>
public bool IsPathEditMode
{
get => _isPathEditMode;
set => SetProperty(ref _isPathEditMode, value);
}
/// <summary>
/// 动画状态
/// </summary>
public string AnimationStatus
{
get => _animationStatus;
set => SetProperty(ref _animationStatus, value);
}
/// <summary>
/// 动画进度
/// </summary>
public double AnimationProgress
{
get => _animationProgress;
set => SetProperty(ref _animationProgress, value);
}
/// <summary>
/// 可用类别集合
/// </summary>
public ObservableCollection<string> AvailableCategories
{
get => _availableCategories;
set => SetProperty(ref _availableCategories, value);
}
/// <summary>
/// 选中的类别
/// </summary>
public string SelectedCategory
{
get => _selectedCategory;
set => SetProperty(ref _selectedCategory, value);
}
/// <summary>
/// 宽度限制(米)
/// </summary>
public double WidthLimit
{
get => _widthLimit;
set => SetProperty(ref _widthLimit, value);
}
/// <summary>
/// 路径文件状态
/// </summary>
public string PathFileStatus
{
get => _pathFileStatus;
set => SetProperty(ref _pathFileStatus, value);
}
/// <summary>
/// 是否处于仅显示物流模式
/// </summary>
public bool IsLogisticsOnlyMode
{
get => _isLogisticsOnlyMode;
set
{
if (SetProperty(ref _isLogisticsOnlyMode, value))
{
// 当开关状态改变时,自动应用可见性设置
ApplyVisibilityMode();
}
}
}
#region
/// <summary>
/// 动画速度
/// </summary>
public double AnimationSpeed
{
get => _animationSpeed;
set => SetProperty(ref _animationSpeed, value);
}
/// <summary>
/// 可用帧率集合
/// </summary>
public ObservableCollection<int> AvailableFrameRates
{
get => _availableFrameRates;
set => SetProperty(ref _availableFrameRates, value);
}
/// <summary>
/// 选中的帧率
/// </summary>
public int SelectedFrameRate
{
get => _selectedFrameRate;
set => SetProperty(ref _selectedFrameRate, value);
}
/// <summary>
/// 动画持续时间(秒)
/// </summary>
public double AnimationDuration
{
get => _animationDuration;
set => SetProperty(ref _animationDuration, value);
}
/// <summary>
/// 是否启用循环播放
/// </summary>
public bool IsLoopEnabled
{
get => _isLoopEnabled;
set => SetProperty(ref _isLoopEnabled, value);
}
/// <summary>
/// 是否启用平滑过渡
/// </summary>
public bool IsSmoothTransition
{
get => _isSmoothTransition;
set => SetProperty(ref _isSmoothTransition, value);
}
/// <summary>
/// 当前动画时间
/// </summary>
public double CurrentAnimationTime
{
get => _currentAnimationTime;
set => SetProperty(ref _currentAnimationTime, value);
}
/// <summary>
/// 是否可以开始动画
/// </summary>
public bool CanStartAnimation
{
get => _canStartAnimation;
set => SetProperty(ref _canStartAnimation, value);
}
/// <summary>
/// 是否可以暂停动画
/// </summary>
public bool CanPauseAnimation
{
get => _canPauseAnimation;
set => SetProperty(ref _canPauseAnimation, value);
}
/// <summary>
/// 是否可以停止动画
/// </summary>
public bool CanStopAnimation
{
get => _canStopAnimation;
set => SetProperty(ref _canStopAnimation, value);
}
#endregion
#region
/// <summary>
/// 是否可以运行碰撞检测
/// </summary>
public bool CanRunCollisionDetection
{
get => _canRunCollisionDetection;
set => SetProperty(ref _canRunCollisionDetection, value);
}
/// <summary>
/// 是否有碰撞检测结果
/// </summary>
public bool HasCollisionResults
{
get => _hasCollisionResults;
set => SetProperty(ref _hasCollisionResults, value);
}
/// <summary>
/// 碰撞检测状态
/// </summary>
public string CollisionStatus
{
get => _collisionStatus;
set => SetProperty(ref _collisionStatus, value);
}
/// <summary>
/// 碰撞检测摘要
/// </summary>
public string CollisionSummary
{
get => _collisionSummary;
set => SetProperty(ref _collisionSummary, value);
}
#endregion
#region
/// <summary>
/// 模型分层拆分状态
/// </summary>
public string ModelSplitterStatus
{
get => _modelSplitterStatus;
set => SetProperty(ref _modelSplitterStatus, value);
}
/// <summary>
/// 日志级别集合
/// </summary>
public ObservableCollection<string> LogLevels
{
get => _logLevels;
set => SetProperty(ref _logLevels, value);
}
/// <summary>
/// 选中的日志级别
/// </summary>
public string SelectedLogLevel
{
get => _selectedLogLevel;
set => SetProperty(ref _selectedLogLevel, value);
}
/// <summary>
/// 日志状态
/// </summary>
public string LogStatus
{
get => _logStatus;
set => SetProperty(ref _logStatus, value);
}
/// <summary>
/// 是否启用自动保存
/// </summary>
public bool IsAutoSaveEnabled
{
get => _isAutoSaveEnabled;
set => SetProperty(ref _isAutoSaveEnabled, value);
}
/// <summary>
/// 是否启用调试模式
/// </summary>
public bool IsDebugModeEnabled
{
get => _isDebugModeEnabled;
set => SetProperty(ref _isDebugModeEnabled, value);
}
/// <summary>
/// 设置状态
/// </summary>
public string SettingsStatus
{
get => _settingsStatus;
set => SetProperty(ref _settingsStatus, value);
}
/// <summary>
/// 插件版本
/// </summary>
public string PluginVersion
{
get => _pluginVersion;
set => SetProperty(ref _pluginVersion, value);
}
/// <summary>
/// Navisworks版本
/// </summary>
public string NavisworksVersion
{
get => _navisworksVersion;
set => SetProperty(ref _navisworksVersion, value);
}
/// <summary>
/// 系统状态
/// </summary>
public string SystemStatus
{
get => _systemStatus;
set => SetProperty(ref _systemStatus, value);
}
/// <summary>
/// 系统状态颜色
/// </summary>
public string SystemStatusColor
{
get => _systemStatusColor;
set => SetProperty(ref _systemStatusColor, value);
}
/// <summary>
/// 内存使用情况
/// </summary>
public string MemoryUsage
{
get => _memoryUsage;
set => SetProperty(ref _memoryUsage, value);
}
/// <summary>
/// 运行时间
/// </summary>
public string RunningTime
{
get => _runningTime;
set => SetProperty(ref _runningTime, value);
}
/// <summary>
/// 性能信息
/// </summary>
public string PerformanceInfo
{
get => _performanceInfo;
set => SetProperty(ref _performanceInfo, value);
}
#endregion
#region
/// <summary>
/// 自动路径规划起点文本
/// </summary>
public string AutoPathStartPoint
{
get => _autoPathStartPoint;
set => SetProperty(ref _autoPathStartPoint, value);
}
/// <summary>
/// 自动路径规划终点文本
/// </summary>
public string AutoPathEndPoint
{
get => _autoPathEndPoint;
set => SetProperty(ref _autoPathEndPoint, value);
}
/// <summary>
/// 自动路径规划车辆尺寸
/// </summary>
public double AutoPathVehicleSize
{
get => _autoPathVehicleSize;
set => SetProperty(ref _autoPathVehicleSize, value);
}
/// <summary>
/// 自动路径规划安全间隙(车辆膨胀间隙)
/// </summary>
public double AutoPathSafetyMargin
{
get => _autoPathSafetyMargin;
set => SetProperty(ref _autoPathSafetyMargin, value);
}
/// <summary>
/// 自动路径规划状态
/// </summary>
public string AutoPathStatus
{
get => _autoPathStatus;
set => SetProperty(ref _autoPathStatus, value);
}
/// <summary>
/// 是否正在选择起点
/// </summary>
public bool IsSelectingStartPoint
{
get => _isSelectingStartPoint;
set => SetProperty(ref _isSelectingStartPoint, value);
}
/// <summary>
/// 是否正在选择终点
/// </summary>
public bool IsSelectingEndPoint
{
get => _isSelectingEndPoint;
set => SetProperty(ref _isSelectingEndPoint, value);
}
#endregion
#endregion
#region
public ICommand NewPathCommand { 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 ImportPathCommand { get; private set; }
public ICommand ExportPathCommand { get; private set; }
public ICommand SaveAsPathCommand { get; private set; }
public ICommand StartAnimationCommand { get; private set; }
public ICommand PauseAnimationCommand { get; private set; }
public ICommand StopAnimationCommand { get; private set; }
public ICommand RunCollisionDetectionCommand { get; private set; }
public ICommand ViewCollisionReportCommand { get; private set; }
public ICommand ModelSplitterCommand { get; private set; }
public ICommand SetLogisticsAttributeCommand { get; private set; }
public ICommand ViewLogCommand { get; private set; }
public ICommand ClearLogCommand { get; private set; }
public ICommand ExportLogCommand { get; private set; }
public ICommand OpenSettingsCommand { get; private set; }
public ICommand ResetSettingsCommand { get; private set; }
public ICommand ImportConfigCommand { get; private set; }
public ICommand CheckUpdateCommand { get; private set; }
public ICommand GeneratePerformanceReportCommand { get; private set; }
public ICommand SelectStartPointCommand { get; private set; }
public ICommand SelectEndPointCommand { get; private set; }
public ICommand AutoPlanPathCommand { get; private set; }
public ICommand ClearAutoPathCommand { get; private set; }
#endregion
#region
public LogisticsControlViewModel() : base()
{
try
{
// 获取UI状态管理器和命令管理器实例
_uiStateManager = UIStateManager.Instance;
_commandManager = NavisworksTransport.Commands.CommandManager.Instance;
// 验证关键组件是否正常初始化
if (_uiStateManager == null)
{
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
if (_commandManager == null)
{
LogManager.Error("CommandManager初始化失败");
throw new InvalidOperationException("CommandManager初始化失败");
}
// 初始化线程安全的集合
LogisticsModels = new ThreadSafeObservableCollection<LogisticsModel>();
PathRoutes = new ThreadSafeObservableCollection<PathRouteViewModel>();
AvailableCategories = new ThreadSafeObservableCollection<string>();
AvailableFrameRates = new ThreadSafeObservableCollection<int>();
LogLevels = new ThreadSafeObservableCollection<string>();
// 初始化路径规划管理器
InitializePathPlanningManager();
// 初始化命令使用新的Command Pattern框架
InitializeCommandsAsync();
// 初始化状态
InitializeViewModelAsync();
LogManager.Info("LogisticsControlViewModel构造函数执行完成");
}
catch (Exception ex)
{
LogManager.Error($"LogisticsControlViewModel构造函数异常: {ex.Message}", ex);
// 在构造函数中尽量保证对象处于可用状态
StatusText = "初始化失败,请检查日志";
throw;
}
}
#endregion
#region
private async void InitializeViewModelAsync()
{
await SafeExecuteAsync(async () =>
{
await UpdateInstructionTextAsync();
await UpdateSelectionDisplayAsync();
await InitializeCategoriesAsync();
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "插件已就绪";
AnimationStatus = "动画状态: 就绪";
AnimationProgress = 0;
WidthLimit = 3.0; // 默认宽度限制3米
PathFileStatus = "未保存";
});
// 初始化动画参数
await InitializeAnimationSettingsAsync();
// 初始化系统管理设置
await InitializeSystemManagementSettingsAsync();
LogManager.Info("LogisticsControlViewModel 初始化完成");
}, "初始化ViewModel");
}
/// <summary>
/// 初始化命令使用Command Pattern框架
/// </summary>
private async void InitializeCommandsAsync()
{
await SafeExecuteAsync(() =>
{
// 路径操作命令 - 使用原有的RelayCommand保持向后兼容
NewPathCommand = new RelayCommand(async () => await ExecuteNewPathAsync());
DeletePathCommand = new RelayCommand(async () => await ExecuteDeletePathAsync(), CanExecuteDeletePath);
RenamePathCommand = new RelayCommand(async () => await ExecuteRenamePathAsync(), CanExecuteRenamePath);
StartEditCommand = new RelayCommand(async () => await ExecuteStartEditAsync(), CanExecuteStartEdit);
EndEditCommand = new RelayCommand(async () => await ExecuteEndEditAsync(), CanExecuteEndEdit);
ClearPathCommand = new RelayCommand(async () => await ExecuteClearPathAsync(), CanExecuteClearPath);
DeletePointCommand = new RelayCommand<PathPointViewModel>(async (point) => await ExecuteDeletePointAsync(point));
ImportPathCommand = new RelayCommand(async () => await ExecuteImportPathAsync());
ExportPathCommand = new RelayCommand(async () => await ExecuteExportPathAsync(), CanExecuteExportPath);
SaveAsPathCommand = new RelayCommand(async () => await ExecuteSaveAsPathAsync(), CanExecuteSaveAsPath);
// 动画控制命令
StartAnimationCommand = new RelayCommand(async () => await ExecuteStartAnimationAsync(), () => CanStartAnimation);
PauseAnimationCommand = new RelayCommand(async () => await ExecutePauseAnimationAsync(), () => CanPauseAnimation);
StopAnimationCommand = new RelayCommand(async () => await ExecuteStopAnimationAsync(), () => CanStopAnimation);
// 碰撞检测命令
RunCollisionDetectionCommand = new RelayCommand(async () => await ExecuteRunCollisionDetectionAsync(), () => CanRunCollisionDetection);
ViewCollisionReportCommand = new RelayCommand(async () => await ExecuteViewCollisionReportAsync(), () => HasCollisionResults);
// 系统管理命令
ModelSplitterCommand = new RelayCommand(async () => await ExecuteModelSplitterAsync());
SetLogisticsAttributeCommand = new RelayCommand(async () => await ExecuteSetLogisticsAttributeAsync());
ViewLogCommand = new RelayCommand(async () => await ExecuteViewLogAsync());
ClearLogCommand = new RelayCommand(async () => await ExecuteClearLogAsync());
ExportLogCommand = new RelayCommand(async () => await ExecuteExportLogAsync());
OpenSettingsCommand = new RelayCommand(async () => await ExecuteOpenSettingsAsync());
ResetSettingsCommand = new RelayCommand(async () => await ExecuteResetSettingsAsync());
ImportConfigCommand = new RelayCommand(async () => await ExecuteImportConfigAsync());
CheckUpdateCommand = new RelayCommand(async () => await ExecuteCheckUpdateAsync());
GeneratePerformanceReportCommand = new RelayCommand(async () => await ExecuteGeneratePerformanceReportAsync());
// 自动路径规划命令
SelectStartPointCommand = new RelayCommand(async () => await ExecuteSelectStartPointAsync());
SelectEndPointCommand = new RelayCommand(async () => await ExecuteSelectEndPointAsync());
AutoPlanPathCommand = new RelayCommand(async () => await ExecuteAutoPlanPathAsync(), CanExecuteAutoPlanPath);
ClearAutoPathCommand = new RelayCommand(async () => await ExecuteClearAutoPathAsync());
LogManager.Info("命令初始化完成 - 使用新的异步Command Pattern框架");
}, "初始化命令");
}
/// <summary>
/// 初始化动画设置
/// </summary>
private async Task InitializeAnimationSettingsAsync()
{
await SafeExecuteAsync(async () =>
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 初始化可用帧率
AvailableFrameRates.Clear();
var frameRates = new[] { 15, 24, 30, 60 };
foreach (var rate in frameRates)
{
AvailableFrameRates.Add(rate);
}
SelectedFrameRate = 30; // 默认30fps
// 设置默认动画参数
AnimationSpeed = 1.0;
AnimationDuration = 10.0;
IsLoopEnabled = false;
IsSmoothTransition = true;
CurrentAnimationTime = 0.0;
// 设置初始状态
CanStartAnimation = true;
CanPauseAnimation = false;
CanStopAnimation = false;
CanRunCollisionDetection = true;
HasCollisionResults = false;
CollisionStatus = "就绪";
CollisionSummary = "尚未运行碰撞检测";
});
LogManager.Info("动画设置初始化完成");
}, "初始化动画设置");
}
/// <summary>
/// 初始化系统管理设置
/// </summary>
private async Task InitializeSystemManagementSettingsAsync()
{
await SafeExecuteAsync(async () =>
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 初始化日志级别
LogLevels.Clear();
var logLevels = new[] { "Debug", "Info", "Warning", "Error" };
foreach (var level in logLevels)
{
LogLevels.Add(level);
}
SelectedLogLevel = "Info";
// 初始化系统信息
ModelSplitterStatus = "就绪";
LogStatus = "日志系统正常";
SettingsStatus = "设置已加载";
PluginVersion = "v1.0";
NavisworksVersion = "2026";
SystemStatus = "正常";
SystemStatusColor = "Green";
});
// 启动性能监控
StartPerformanceMonitoring();
LogManager.Info("系统管理设置初始化完成");
}, "初始化系统管理设置");
}
/// <summary>
/// 启动性能监控
/// </summary>
private void StartPerformanceMonitoring()
{
var startTime = DateTime.Now;
// 使用定时器更新性能信息
var timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(5);
timer.Tick += (s, e) =>
{
try
{
// 更新内存使用
var process = System.Diagnostics.Process.GetCurrentProcess();
var memoryMB = process.WorkingSet64 / (1024 * 1024);
MemoryUsage = $"{memoryMB} MB";
// 更新运行时间
var runTime = DateTime.Now - startTime;
RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
// 更新性能信息
PerformanceInfo = $"CPU: 正常, 内存: {memoryMB}MB, 运行时间: {RunningTime}";
}
catch (Exception ex)
{
LogManager.Error($"性能监控更新失败: {ex.Message}");
}
};
timer.Start();
}
#endregion
#region
/// <summary>
/// 应用可见性模式
/// </summary>
private void ApplyVisibilityMode()
{
SafeExecute(() =>
{
if (IsLogisticsOnlyMode)
{
// 仅显示物流模式
ShowLogisticsOnlyInternal();
}
else
{
// 显示全部模式
ShowAllInternal();
}
}, "应用可见性模式");
}
/// <summary>
/// 内部方法:显示所有元素
/// </summary>
private void ShowAllInternal()
{
var result = VisibilityManager.ShowAllItems();
if (result.Success)
{
// 更新物流模型列表中的可见性状态
foreach (var model in LogisticsModels)
{
model.IsVisible = true;
}
StatusText = "显示所有元素";
LogManager.Info("切换到显示全部模式");
}
else
{
StatusText = $"显示全部失败: {result.Message}";
LogManager.Error($"显示全部失败: {result.Message}");
}
}
/// <summary>
/// 内部方法:仅显示物流元素
/// </summary>
private void ShowLogisticsOnlyInternal()
{
var document = NavisApplication.ActiveDocument;
if (document?.Models != null)
{
// 先重置所有隐藏状态
document.Models.ResetAllHidden();
// 获取所有具有物流属性的元素
var logisticsItems = new HashSet<ModelItem>();
var allItems = GetAllModelItems();
foreach (var item in allItems)
{
if (CategoryAttributeManager.HasLogisticsAttributes(item))
{
logisticsItems.Add(item);
}
}
// 获取所有需要保持可见的元素
var itemsToKeepVisible = new HashSet<ModelItem>();
foreach (var logisticsItem in logisticsItems)
{
// 添加物流元素本身
itemsToKeepVisible.Add(logisticsItem);
// 添加所有父元素路径(向上)
var parent = logisticsItem.Parent;
while (parent != null)
{
itemsToKeepVisible.Add(parent);
parent = parent.Parent;
}
// 添加所有子元素(向下)- 物流属性继承给子元素
AddAllChildren(logisticsItem, itemsToKeepVisible);
}
// 找出需要隐藏的元素(不在保持可见列表中的元素)
var itemsToHide = new List<ModelItem>();
foreach (var item in allItems)
{
if (!itemsToKeepVisible.Contains(item))
{
itemsToHide.Add(item);
}
}
// 执行隐藏操作
if (itemsToHide.Count > 0)
{
var collectionToHide = new ModelItemCollection();
collectionToHide.AddRange(itemsToHide);
document.Models.SetHidden(collectionToHide, true);
}
// 更新物流模型列表中的可见性状态
foreach (var model in LogisticsModels)
{
model.IsVisible = true;
}
var totalVisibleItems = itemsToKeepVisible.Count;
StatusText = $"仅显示物流元素 ({logisticsItems.Count} 个物流节点,{totalVisibleItems} 个可见元素)";
LogManager.Info($"切换到仅显示物流模式: 找到 {logisticsItems.Count} 个物流节点,{totalVisibleItems} 个可见元素");
}
}
/// <summary>
/// 递归添加所有子元素到可见列表
/// </summary>
private void AddAllChildren(ModelItem parent, HashSet<ModelItem> visibleItems)
{
if (parent.Children != null)
{
foreach (ModelItem child in parent.Children)
{
visibleItems.Add(child);
// 递归添加子元素的子元素
AddAllChildren(child, visibleItems);
}
}
}
private void ExecuteNewPath()
{
SafeExecute(() =>
{
// 调用 PathPlanningManager 来启动新建路径流程
if (_pathPlanningManager != null)
{
var newRoute = _pathPlanningManager.StartCreatingNewRoute();
if (newRoute != null)
{
// 创建对应的 WPF ViewModel
var newPathViewModel = new PathRouteViewModel
{
Name = newRoute.Name,
Description = newRoute.Description,
IsActive = true // 新建的路径默认是活动的
};
// 将 Core 层的 PathPoint 转换为 WPF 的 PathPointViewModel 并添加到 ViewModel
foreach (var corePoint in newRoute.Points)
{
var wpfPoint = new PathPointViewModel
{
Name = corePoint.Name,
X = corePoint.X,
Y = corePoint.Y,
Z = corePoint.Z
// 注意Type 属性在 corrected_old_string 中不存在,因此不添加
};
newPathViewModel.Points.Add(wpfPoint);
}
// 添加到 UI 列表并选中
PathRoutes.Add(newPathViewModel);
SelectedPathRoute = newPathViewModel;
StatusText = $"已进入新建路径模式: {newRoute.Name} - 请在3D视图中点击设置路径点";
LogManager.Info($"开始新建路径: {newRoute.Name}");
// 显示提示信息,告知用户进入新建路径模式
MessageBox.Show("已进入新建路径模式!\n\n请在3D视图中可通行的物流模型上来设置路径点。",
"新建路径", MessageBoxButton.OK, MessageBoxImage.Information);
}
else
{
// StartCreatingNewRoute 已经通过 OnErrorOccurred 发送了错误信息
// 这里可以添加更具体的提示
StatusText = "创建新路径失败:没有可通行的物流模型";
LogManager.Error("创建新路径失败:没有可通行的物流模型");
MessageBox.Show("创建新路径失败:没有找到任何可通行的物流模型。\n请先为模型设置可通行的物流属性然后再尝试创建路径。", "错误",
MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
else
{
StatusText = "路径规划管理器未初始化";
LogManager.Error("路径规划管理器未初始化");
}
}, "新建路径");
}
/// <summary>
/// 异步新建路径命令使用UIStateManager和Command Pattern
/// </summary>
private async Task ExecuteNewPathAsync()
{
try
{
// 使用CommandManager执行新建路径命令
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "正在创建新路径...";
});
// 在后台线程执行业务逻辑
var result = await Task.Run(() =>
{
if (_pathPlanningManager != null)
{
var newRoute = _pathPlanningManager.StartCreatingNewRoute();
return new { Success = newRoute != null, Route = newRoute };
}
return new { Success = false, Route = (NavisworksTransport.PathRoute)null };
});
// 在UI线程上更新结果
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (result.Success && result.Route != null)
{
// 创建对应的 WPF ViewModel
var newPathViewModel = new PathRouteViewModel
{
Name = result.Route.Name,
Description = result.Route.Description,
IsActive = true
};
// 转换路径点
foreach (var corePoint in result.Route.Points)
{
var wpfPoint = new PathPointViewModel
{
Name = corePoint.Name,
X = corePoint.X,
Y = corePoint.Y,
Z = corePoint.Z
};
newPathViewModel.Points.Add(wpfPoint);
}
// 添加到 UI 列表并选中
PathRoutes.Add(newPathViewModel);
SelectedPathRoute = newPathViewModel;
StatusText = $"已进入新建路径模式: {result.Route.Name} - 请在3D视图中点击设置路径点";
LogManager.Info($"开始新建路径: {result.Route.Name}");
// 显示提示信息
MessageBox.Show("已进入新建路径模式!\n\n请在3D视图中可通行的物流模型上来设置路径点。",
"新建路径", MessageBoxButton.OK, MessageBoxImage.Information);
}
else
{
StatusText = "创建新路径失败:没有可通行的物流模型";
LogManager.Error("创建新路径失败:没有可通行的物流模型");
MessageBox.Show("创建新路径失败:没有找到任何可通行的物流模型。\n请先为模型设置可通行的物流属性然后再尝试创建路径。", "错误",
MessageBoxButton.OK, MessageBoxImage.Warning);
}
});
}
catch (Exception ex)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = $"新建路径出错: {ex.Message}";
LogManager.Error($"新建路径异常: {ex.Message}", ex);
});
}
}
private void ExecuteDeletePath()
{
SafeExecute(() =>
{
if (SelectedPathRoute != null)
{
var pathName = SelectedPathRoute.Name;
// 清理对应的3D可视化标记
if (PathPointRenderPlugin.Instance != null)
{
// 如果是自动生成的路径,清除对应的标记
if (pathName.StartsWith("自动路径_"))
{
// 清除所有自动路径标记(负序号-1000系列
var allMarkers = PathPointRenderPlugin.Instance.GetAllMarkers();
var autoPathMarkers = allMarkers.Where(m => m.SequenceNumber < -999).ToList();
foreach (var marker in autoPathMarkers)
{
PathPointRenderPlugin.Instance.RemoveMarkerAt(marker.Center, 1.0);
}
if (autoPathMarkers.Count > 0)
{
LogManager.Info($"删除路径时清除了 {autoPathMarkers.Count} 个自动路径3D标记");
}
}
else
{
// 对于手动路径,清除对应序号的标记(正序号)
// 这里可以根据路径点来清除具体的标记
if (SelectedPathRoute.Points.Count > 0)
{
int removedMarkers = 0;
foreach (var point in SelectedPathRoute.Points)
{
var pointLocation = new Point3D(point.X, point.Y, point.Z);
bool removed = PathPointRenderPlugin.Instance.RemoveMarkerAt(pointLocation, 2.0);
if (removed) removedMarkers++;
}
if (removedMarkers > 0)
{
LogManager.Info($"删除路径时清除了 {removedMarkers} 个手动路径3D标记");
}
}
}
}
// 通知PathPlanningManager删除对应的路径
if (_pathPlanningManager != null)
{
// 查找PathPlanningManager中对应的路径并删除
var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Name == pathName);
if (coreRoute != null)
{
_pathPlanningManager.ModifiableRoutes.Remove(coreRoute);
LogManager.Info($"已从PathPlanningManager中删除路径: {pathName}");
}
// 如果删除的是当前路径,清除当前路径状态
if (_pathPlanningManager.CurrentRoute?.Name == pathName)
{
_pathPlanningManager.Clear3DPathMarkers();
LogManager.Info("已清除当前路径的3D标记");
}
}
// 从UI列表中删除路径
PathRoutes.Remove(SelectedPathRoute);
SelectedPathRoute = null;
StatusText = $"已完全删除路径: {pathName}包括3D可视化";
LogManager.Info($"完全删除路径: {pathName}包括UI列表和3D可视化");
}
}, "删除路径");
}
private bool CanExecuteDeletePath()
{
return SelectedPathRoute != null;
}
/// <summary>
/// 异步删除路径命令使用UIStateManager和Command Pattern
/// </summary>
private async Task ExecuteDeletePathAsync()
{
if (!CanExecuteDeletePath()) return;
try
{
var pathName = SelectedPathRoute.Name;
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = $"正在删除路径: {pathName}...";
});
// 在后台线程执行删除逻辑
var result = await Task.Run(() =>
{
var deletedMarkers = 0;
// 清理对应的3D可视化标记
if (PathPointRenderPlugin.Instance != null)
{
if (pathName.StartsWith("自动路径_"))
{
// 清除所有自动路径标记
var allMarkers = PathPointRenderPlugin.Instance.GetAllMarkers();
var autoPathMarkers = allMarkers.Where(m => m.SequenceNumber < -999).ToList();
foreach (var marker in autoPathMarkers)
{
PathPointRenderPlugin.Instance.RemoveMarkerAt(marker.Center, 1.0);
deletedMarkers++;
}
}
else
{
// 对于手动路径,清除对应序号的标记
if (SelectedPathRoute.Points.Count > 0)
{
foreach (var point in SelectedPathRoute.Points)
{
var pointLocation = new Point3D(point.X, point.Y, point.Z);
bool removed = PathPointRenderPlugin.Instance.RemoveMarkerAt(pointLocation, 2.0);
if (removed) deletedMarkers++;
}
}
}
}
// 通知PathPlanningManager删除对应的路径
if (_pathPlanningManager != null)
{
var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Name == pathName);
if (coreRoute != null)
{
_pathPlanningManager.ModifiableRoutes.Remove(coreRoute);
}
if (_pathPlanningManager.CurrentRoute?.Name == pathName)
{
_pathPlanningManager.Clear3DPathMarkers();
}
}
return deletedMarkers;
});
// 在UI线程上更新结果
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 从UI列表中删除路径
PathRoutes.Remove(SelectedPathRoute);
SelectedPathRoute = null;
StatusText = $"已完全删除路径: {pathName}包括3D可视化共清除{result}个标记)";
LogManager.Info($"完全删除路径: {pathName}包括UI列表和3D可视化共清除{result}个标记");
});
}
catch (Exception ex)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = $"删除路径出错: {ex.Message}";
LogManager.Error($"删除路径异常: {ex.Message}", ex);
});
}
}
private void ExecuteRenamePath()
{
SafeExecute(() =>
{
if (SelectedPathRoute != null)
{
// TODO: 实现重命名对话框
var newName = $"路径 {PathRoutes.Count}"; // 临时实现
var oldName = SelectedPathRoute.Name;
SelectedPathRoute.Name = newName;
StatusText = $"路径已重命名: {oldName} -> {newName}";
PathFileStatus = "未保存";
LogManager.Info($"路径重命名: {oldName} -> {newName}");
}
}, "重命名路径");
}
private bool CanExecuteRenamePath()
{
return SelectedPathRoute != null;
}
private void ExecuteStartEdit()
{
SafeExecute(() =>
{
if (SelectedPathRoute != null)
{
// 查找或创建与 WPF ViewModel 对应的 Core PathRoute
var coreRoute = _pathPlanningManager?.Routes.FirstOrDefault(r => r.Name == SelectedPathRoute.Name);
if (coreRoute == null)
{
// 如果 Core 层没有,可能需要创建或同步
// 这里假设 Core 层应该已经包含了所有路径,如果没有,可能需要重新加载或同步
// 为简化,我们直接使用 SelectedPathRoute 的信息创建一个临时的 Core PathRoute
coreRoute = new NavisworksTransport.PathRoute(SelectedPathRoute.Name)
{
Description = SelectedPathRoute.Description ?? ""
};
// 注意ViewModel 中的点是 PathPoint 对象Core 中的是 NavisworksTransport.PathPoint 对象
// 这里没有直接转换,因为 StartEditing 通常是对已存在的路径操作
// 如果需要从 ViewModel 创建 Core Route需要进行数据转换
// 为了保持逻辑清晰,这里假设路径已经在 Core 中存在
StatusText = $"路径 '{SelectedPathRoute.Name}' 在核心管理器中未找到,无法开始编辑。";
LogManager.Warning($"路径 '{SelectedPathRoute.Name}' 在核心管理器中未找到");
return;
}
// 通知 PathPlanningManager 开始编辑此路径
_pathPlanningManager?.SwitchToEditingState(coreRoute);
// 更新 WPF ViewModel 状态
IsPathEditMode = true;
SelectedPathRoute.IsActive = true;
StatusText = $"已进入3D路径编辑模式: {SelectedPathRoute.Name}";
LogManager.Info($"开始3D路径编辑: {SelectedPathRoute.Name}");
}
else
{
StatusText = "请先选择一个路径";
}
}, "开始编辑");
}
private bool CanExecuteStartEdit()
{
// 检查是否选择了路径以及 PathPlanningManager 是否处于非编辑状态
return SelectedPathRoute != null &&
(_pathPlanningManager?.PathEditState == PathEditState.Viewing);
}
private void ExecuteEndEdit()
{
SafeExecute(() =>
{
// 通知 PathPlanningManager 结束编辑
bool success = _pathPlanningManager?.FinishEditing() ?? false;
// 更新 WPF ViewModel 状态
IsPathEditMode = false;
if (SelectedPathRoute != null)
{
SelectedPathRoute.IsActive = false;
if (success)
{
StatusText = $"已退出3D路径编辑模式: {SelectedPathRoute.Name} (已保存)";
PathFileStatus = "未保存"; // 或者根据实际情况设置为"已保存"
}
else
{
StatusText = $"退出3D路径编辑模式失败: {SelectedPathRoute.Name}";
}
}
else
{
if (success)
{
StatusText = "已退出3D路径编辑模式 (已保存)";
}
else
{
StatusText = "退出3D路径编辑模式失败";
}
}
LogManager.Info("结束3D路径编辑");
}, "结束编辑");
}
private bool CanExecuteEndEdit()
{
// 检查 PathPlanningManager 是否处于编辑状态 (Creating 或 Editing)
return (_pathPlanningManager?.PathEditState == PathEditState.Creating ||
_pathPlanningManager?.PathEditState == PathEditState.Editing);
}
private void ExecuteClearPath()
{
SafeExecute(() =>
{
if (SelectedPathRoute != null)
{
var pointCount = SelectedPathRoute.Points.Count;
// 通知 PathPlanningManager 清除当前路径点
// 这需要 PathPlanningManager 有对应的方法,或者直接操作 CurrentRoute
var currentRoute = _pathPlanningManager?.CurrentRoute;
if (currentRoute != null && currentRoute.Name == SelectedPathRoute.Name)
{
currentRoute.ClearPoints();
// 通知 PathPlanningManager 重绘/清除3D标记
_pathPlanningManager?.Clear3DPathMarkers(); // 假设有此方法
}
// 更新 WPF ViewModel
SelectedPathRoute.Points.Clear();
StatusText = $"已清空路径 {SelectedPathRoute.Name} 的 {pointCount} 个点";
PathFileStatus = "未保存";
LogManager.Info($"清空路径: {SelectedPathRoute.Name}, 删除了 {pointCount} 个点");
}
}, "清空路径");
}
private bool CanExecuteClearPath()
{
return SelectedPathRoute != null && SelectedPathRoute.Points.Count > 0;
}
private void ExecuteDeletePoint(PathPointViewModel point)
{
SafeExecute(() =>
{
if (SelectedPathRoute != null && point != null)
{
// 通知 PathPlanningManager 删除路径点
// 这需要 PathPlanningManager 有对应的方法,或者直接操作 CurrentRoute
var currentRoute = _pathPlanningManager?.CurrentRoute;
if (currentRoute != null && currentRoute.Name == SelectedPathRoute.Name)
{
var corePoint = currentRoute.Points.FirstOrDefault(p =>
Math.Abs(p.X - point.X) < 0.001 &&
Math.Abs(p.Y - point.Y) < 0.001 &&
Math.Abs(p.Z - point.Z) < 0.001);
if (corePoint != null)
{
// 通知 PathPlanningManager 从3D视图中移除此点
_pathPlanningManager?.RemovePathPointFrom3D(corePoint); // 假设有此方法
}
}
// 更新 WPF ViewModel
SelectedPathRoute.Points.Remove(point);
StatusText = $"已删除路径点: {point.Name}";
PathFileStatus = "未保存";
LogManager.Info($"删除路径点: {point.Name}");
}
}, "删除路径点");
}
private void ExecuteImportPath()
{
SafeExecute(() =>
{
// TODO: 实现文件对话框和路径导入逻辑
StatusText = "路径导入功能待实现";
LogManager.Info("执行路径导入命令");
}, "导入路径");
}
private void ExecuteExportPath()
{
SafeExecute(() =>
{
if (SelectedPathRoute != null)
{
// TODO: 实现文件对话框和路径导出逻辑
StatusText = $"导出路径: {SelectedPathRoute.Name}";
PathFileStatus = "已保存";
LogManager.Info($"导出路径: {SelectedPathRoute.Name}");
}
}, "导出路径");
}
private bool CanExecuteExportPath()
{
return SelectedPathRoute != null && SelectedPathRoute.Points.Count > 0;
}
private void ExecuteSaveAsPath()
{
SafeExecute(() =>
{
if (SelectedPathRoute != null)
{
// TODO: 实现另存为对话框和保存逻辑
StatusText = $"另存为路径: {SelectedPathRoute.Name}";
PathFileStatus = "已保存";
LogManager.Info($"另存为路径: {SelectedPathRoute.Name}");
}
}, "另存为路径");
}
private bool CanExecuteSaveAsPath()
{
return SelectedPathRoute != null && SelectedPathRoute.Points.Count > 0;
}
private void ExecuteStartAnimation()
{
SafeExecute(() =>
{
if (SelectedPathRoute == null || SelectedPathRoute.Points.Count < 2)
{
StatusText = "请先选择包含至少2个点的路径";
return;
}
// 更新动画状态
AnimationStatus = "动画状态: 播放中";
AnimationProgress = 0;
CurrentAnimationTime = 0.0;
// 更新按钮状态
CanStartAnimation = false;
CanPauseAnimation = true;
CanStopAnimation = true;
// TODO: 集成LogisticsAnimationManager开始动画
StatusText = $"动画已开始: {SelectedPathRoute.Name} (速度: {AnimationSpeed}x, 帧率: {SelectedFrameRate}fps)";
LogManager.Info($"开始动画播放: {SelectedPathRoute.Name}, 速度: {AnimationSpeed}x, 帧率: {SelectedFrameRate}fps");
}, "开始动画");
}
private void ExecutePauseAnimation()
{
SafeExecute(() =>
{
AnimationStatus = "动画状态: 已暂停";
// 更新按钮状态
CanStartAnimation = true;
CanPauseAnimation = false;
CanStopAnimation = true;
StatusText = "动画已暂停";
LogManager.Info("暂停动画播放");
}, "暂停动画");
}
private void ExecuteStopAnimation()
{
SafeExecute(() =>
{
AnimationStatus = "动画状态: 已停止";
AnimationProgress = 0;
CurrentAnimationTime = 0.0;
// 更新按钮状态
CanStartAnimation = true;
CanPauseAnimation = false;
CanStopAnimation = false;
StatusText = "动画已停止";
LogManager.Info("停止动画播放");
}, "停止动画");
}
/// <summary>
/// 异步开始动画命令使用UIStateManager和Command Pattern
/// </summary>
private async Task ExecuteStartAnimationAsync()
{
if (!CanStartAnimation || SelectedPathRoute == null || SelectedPathRoute.Points.Count < 2)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "请先选择包含至少2个点的路径";
});
return;
}
try
{
// 在UI线程上更新动画状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AnimationStatus = "动画状态: 播放中";
AnimationProgress = 0;
CurrentAnimationTime = 0.0;
// 更新按钮状态
CanStartAnimation = false;
CanPauseAnimation = true;
CanStopAnimation = true;
StatusText = $"动画已开始: {SelectedPathRoute.Name} (速度: {AnimationSpeed}x, 帧率: {SelectedFrameRate}fps)";
LogManager.Info($"开始动画播放: {SelectedPathRoute.Name}, 速度: {AnimationSpeed}x, 帧率: {SelectedFrameRate}fps");
});
// TODO: 集成LogisticsAnimationManager开始动画
// 这里可以使用CommandManager执行动画命令
// await _commandManager.ExecuteCommandAsync("StartAnimation", new object[] { SelectedPathRoute });
}
catch (Exception ex)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = $"开始动画出错: {ex.Message}";
LogManager.Error($"开始动画异常: {ex.Message}", ex);
// 恢复按钮状态
CanStartAnimation = true;
CanPauseAnimation = false;
CanStopAnimation = false;
});
}
}
/// <summary>
/// 异步暂停动画命令
/// </summary>
private async Task ExecutePauseAnimationAsync()
{
try
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AnimationStatus = "动画状态: 已暂停";
CanStartAnimation = true;
CanPauseAnimation = false;
CanStopAnimation = true;
StatusText = "动画已暂停";
LogManager.Info("暂停动画播放");
});
}
catch (Exception ex)
{
LogManager.Error($"暂停动画异常: {ex.Message}", ex);
}
}
/// <summary>
/// 异步停止动画命令
/// </summary>
private async Task ExecuteStopAnimationAsync()
{
try
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AnimationStatus = "动画状态: 已停止";
AnimationProgress = 0;
CurrentAnimationTime = 0.0;
CanStartAnimation = true;
CanPauseAnimation = false;
CanStopAnimation = false;
StatusText = "动画已停止";
LogManager.Info("停止动画播放");
});
}
catch (Exception ex)
{
LogManager.Error($"停止动画异常: {ex.Message}", ex);
}
}
private void ExecuteRunCollisionDetection()
{
SafeExecute(() =>
{
if (SelectedPathRoute == null || SelectedPathRoute.Points.Count < 2)
{
StatusText = "请先选择包含至少2个点的路径进行碰撞检测";
return;
}
CollisionStatus = "正在运行碰撞检测...";
CanRunCollisionDetection = false;
// TODO: 集成ClashDetectiveIntegration运行碰撞检测
// 模拟碰撞检测结果
System.Threading.Tasks.Task.Run(() =>
{
System.Threading.Thread.Sleep(2000); // 模拟检测时间
// 在UI线程上异步更新结果避免死锁
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
CollisionStatus = "碰撞检测完成";
CollisionSummary = "发现 3 个潜在碰撞点";
HasCollisionResults = true;
CanRunCollisionDetection = true;
StatusText = "碰撞检测已完成,发现 3 个潜在碰撞点";
}
catch (Exception ex)
{
LogManager.Error($"碰撞检测UI更新失败: {ex.Message}");
}
}), System.Windows.Threading.DispatcherPriority.Background);
});
LogManager.Info($"开始碰撞检测: {SelectedPathRoute.Name}");
}, "运行碰撞检测");
}
private void ExecuteViewCollisionReport()
{
SafeExecute(() =>
{
// TODO: 实现碰撞报告查看功能
StatusText = "打开碰撞检测报告";
LogManager.Info("查看碰撞检测报告");
}, "查看碰撞报告");
}
/// <summary>
/// 异步碰撞检测命令使用UIStateManager和Command Pattern
/// </summary>
private async Task ExecuteRunCollisionDetectionAsync()
{
if (!CanRunCollisionDetection || SelectedPathRoute == null || SelectedPathRoute.Points.Count < 2)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "请先选择包含至少2个点的路径进行碰撞检测";
});
return;
}
try
{
// 更新UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CollisionStatus = "正在运行碰撞检测...";
CanRunCollisionDetection = false;
StatusText = "正在进行碰撞检测...";
});
// 在后台线程执行碰撞检测
var result = await Task.Run(() =>
{
// 模拟碰撞检测过程
System.Threading.Thread.Sleep(2000);
// TODO: 集成ClashDetectiveIntegration运行碰撞检测
// 这里可以使用CommandManager执行碰撞检测命令
// return await _commandManager.ExecuteCommandAsync("RunCollisionDetection", new object[] { SelectedPathRoute });
return new {
Success = true,
ConflictCount = 3,
Summary = "发现 3 个潜在碰撞点",
Details = "碰撞点位于路径的 20%, 45%, 78% 处"
};
});
// 更新结果
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (result.Success)
{
CollisionStatus = "碰撞检测完成";
CollisionSummary = result.Summary;
HasCollisionResults = true;
StatusText = $"碰撞检测已完成,{result.Summary}";
LogManager.Info($"碰撞检测完成: {result.Details}");
}
else
{
CollisionStatus = "碰撞检测失败";
CollisionSummary = "碰撞检测过程中发生错误";
StatusText = "碰撞检测失败";
}
CanRunCollisionDetection = true;
});
}
catch (Exception ex)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CollisionStatus = "碰撞检测出错";
CollisionSummary = $"错误: {ex.Message}";
CanRunCollisionDetection = true;
StatusText = $"碰撞检测出错: {ex.Message}";
LogManager.Error($"碰撞检测异常: {ex.Message}", ex);
});
}
}
/// <summary>
/// 异步查看碰撞报告命令
/// </summary>
private async Task ExecuteViewCollisionReportAsync()
{
if (!HasCollisionResults)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "请先运行碰撞检测";
});
return;
}
try
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "打开碰撞检测报告";
LogManager.Info("查看碰撞检测报告");
});
// TODO: 实现碰撞报告查看功能
// 这里可以使用CommandManager打开报告界面
}
catch (Exception ex)
{
LogManager.Error($"查看碰撞报告异常: {ex.Message}", ex);
}
}
private void ExecuteModelSplitter()
{
SafeExecute(() =>
{
ModelSplitterStatus = "正在分析模型结构...";
// TODO: 集成ModelSplitterManager实现模型分层拆分功能
System.Threading.Tasks.Task.Run(() =>
{
System.Threading.Thread.Sleep(3000); // 模拟分析时间
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
ModelSplitterStatus = "模型分析完成,可进行拆分操作";
StatusText = "模型分层拆分分析完成";
}
catch (Exception ex)
{
LogManager.Error($"模型分层状态UI更新失败: {ex.Message}");
}
}), System.Windows.Threading.DispatcherPriority.Background);
});
StatusText = "正在分析模型结构...";
LogManager.Info("执行模型分层拆分命令");
}, "模型分层拆分");
}
private void ExecuteViewLog()
{
SafeExecute(() =>
{
// TODO: 实现日志查看功能
StatusText = "打开日志查看器";
LogManager.Info("查看日志");
}, "查看日志");
}
private void ExecuteClearLog()
{
SafeExecute(() =>
{
// TODO: 实现日志清空功能
LogStatus = "日志已清空";
StatusText = "日志已清空";
LogManager.Info("清空日志");
}, "清空日志");
}
private void ExecuteExportLog()
{
SafeExecute(() =>
{
// TODO: 实现日志导出功能
StatusText = "日志导出完成";
LogManager.Info("导出日志");
}, "导出日志");
}
private void ExecuteOpenSettings()
{
SafeExecute(() =>
{
// TODO: 实现设置对话框
StatusText = "打开插件设置";
LogManager.Info("打开设置");
}, "打开设置");
}
private void ExecuteResetSettings()
{
SafeExecute(() =>
{
// TODO: 实现设置重置功能
SettingsStatus = "设置已重置为默认值";
IsAutoSaveEnabled = true;
IsDebugModeEnabled = false;
StatusText = "设置已重置";
LogManager.Info("重置设置");
}, "重置设置");
}
private void ExecuteImportConfig()
{
SafeExecute(() =>
{
// TODO: 实现配置导入功能
StatusText = "配置导入完成";
LogManager.Info("导入配置");
}, "导入配置");
}
private void ExecuteCheckUpdate()
{
SafeExecute(() =>
{
StatusText = "正在检查更新...";
// 模拟检查更新
System.Threading.Tasks.Task.Run(() =>
{
System.Threading.Thread.Sleep(2000);
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
StatusText = "当前版本已是最新版本";
}
catch (Exception ex)
{
LogManager.Error($"更新检查UI更新失败: {ex.Message}");
}
}), System.Windows.Threading.DispatcherPriority.Background);
});
LogManager.Info("检查更新");
}, "检查更新");
}
private void ExecuteGeneratePerformanceReport()
{
SafeExecute(() =>
{
StatusText = "正在生成性能报告...";
// 模拟生成报告
System.Threading.Tasks.Task.Run(() =>
{
System.Threading.Thread.Sleep(1500);
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
StatusText = "性能报告生成完成";
PerformanceInfo = $"报告已生成 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}";
}
catch (Exception ex)
{
LogManager.Error($"性能报告UI更新失败: {ex.Message}");
}
}), System.Windows.Threading.DispatcherPriority.Background);
});
LogManager.Info("生成性能报告");
}, "生成性能报告");
}
private void ExecuteSetLogisticsAttribute()
{
SafeExecute(() =>
{
if (string.IsNullOrEmpty(SelectedCategory))
{
StatusText = "请先选择物流类别";
return;
}
var selectedItems = NavisApplication.ActiveDocument?.CurrentSelection?.SelectedItems;
if (selectedItems == null || selectedItems.Count == 0)
{
StatusText = "请先选择模型元素";
return;
}
// 解析选中的类别为枚举
if (Enum.TryParse<CategoryAttributeManager.LogisticsElementType>(SelectedCategory, out var elementType))
{
int successCount = CategoryAttributeManager.AddLogisticsAttributes(
selectedItems,
elementType,
isTraversable: true,
priority: 5,
vehicleSize: "标准",
speedLimit: 10.0,
widthLimit: WidthLimit);
StatusText = $"已为 {successCount} 个元素设置物流属性: {SelectedCategory} (宽度限制: {WidthLimit}m)";
LogManager.Info($"设置物流属性: {SelectedCategory}, 宽度限制: {WidthLimit}m, 影响元素: {successCount}");
// 刷新所有物流模型列表,显示所有具有物流属性的模型
_ = RefreshAllLogisticsModelsAsync();
// 如果当前处于仅显示物流模式,重新应用可见性设置
if (IsLogisticsOnlyMode)
{
ApplyVisibilityMode();
}
}
else
{
StatusText = $"无效的物流类别: {SelectedCategory}";
}
}, "设置物流属性");
}
/// <summary>
/// 异步设置物流属性命令使用UIStateManager和Command Pattern
/// </summary>
private async Task ExecuteSetLogisticsAttributeAsync()
{
try
{
// 验证输入
if (string.IsNullOrEmpty(SelectedCategory))
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "请先选择物流类别";
});
return;
}
var selectedItems = NavisApplication.ActiveDocument?.CurrentSelection?.SelectedItems;
if (selectedItems == null || selectedItems.Count == 0)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "请先选择模型元素";
});
return;
}
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = "正在设置物流属性...";
});
// 在后台线程执行属性设置
var result = await Task.Run(() =>
{
if (Enum.TryParse<CategoryAttributeManager.LogisticsElementType>(SelectedCategory, out var elementType))
{
int successCount = CategoryAttributeManager.AddLogisticsAttributes(
selectedItems,
elementType,
isTraversable: true,
priority: 5,
vehicleSize: "标准",
speedLimit: 10.0,
widthLimit: WidthLimit);
return new { Success = true, Count = successCount, Category = SelectedCategory, Width = WidthLimit };
}
return new { Success = false, Count = 0, Category = SelectedCategory, Width = WidthLimit };
});
// 更新UI结果
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (result.Success)
{
StatusText = $"已为 {result.Count} 个元素设置物流属性: {result.Category} (宽度限制: {result.Width}m)";
LogManager.Info($"设置物流属性: {result.Category}, 宽度限制: {result.Width}m, 影响元素: {result.Count}");
}
else
{
StatusText = $"无效的物流类别: {result.Category}";
LogManager.Warning($"无效的物流类别: {result.Category}");
}
});
// 异步刷新物流模型列表
await RefreshAllLogisticsModelsAsync();
// 如果当前处于仅显示物流模式,重新应用可见性设置
if (IsLogisticsOnlyMode)
{
await Task.Run(() =>
{
ApplyVisibilityMode();
});
}
}
catch (Exception ex)
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
StatusText = $"设置物流属性出错: {ex.Message}";
LogManager.Error($"设置物流属性异常: {ex.Message}", ex);
});
}
}
#region
/// <summary>
/// 异步重命名路径命令
/// </summary>
private async Task ExecuteRenamePathAsync()
{
if (!CanExecuteRenamePath()) return;
try
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// TODO: 实现重命名对话框
var newName = $"路径 {PathRoutes.Count}"; // 临时实现
var oldName = SelectedPathRoute.Name;
SelectedPathRoute.Name = newName;
StatusText = $"路径已重命名: {oldName} -> {newName}";
PathFileStatus = "未保存";
LogManager.Info($"路径重命名: {oldName} -> {newName}");
});
}
catch (Exception ex)
{
LogManager.Error($"重命名路径异常: {ex.Message}", ex);
}
}
/// <summary>
/// 异步开始编辑命令
/// </summary>
private async Task ExecuteStartEditAsync()
{
if (!CanExecuteStartEdit()) return;
try
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// TODO: 集成PathPlanningManager开始编辑逻辑
IsPathEditMode = true;
if (SelectedPathRoute != null)
{
SelectedPathRoute.IsActive = true;
StatusText = $"已进入3D路径编辑模式: {SelectedPathRoute.Name}";
LogManager.Info($"开始3D路径编辑: {SelectedPathRoute.Name}");
}
});
}
catch (Exception ex)
{
LogManager.Error($"开始编辑异常: {ex.Message}", ex);
}
}
/// <summary>
/// 异步结束编辑命令
/// </summary>
private async Task ExecuteEndEditAsync()
{
if (!CanExecuteEndEdit()) return;
try
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// TODO: 集成PathPlanningManager结束编辑逻辑
IsPathEditMode = false;
if (SelectedPathRoute != null)
{
SelectedPathRoute.IsActive = false;
StatusText = $"已退出3D路径编辑模式: {SelectedPathRoute.Name}";
PathFileStatus = "未保存";
}
LogManager.Info("结束3D路径编辑");
});
}
catch (Exception ex)
{
LogManager.Error($"结束编辑异常: {ex.Message}", ex);
}
}
/// <summary>
/// 异步清空路径命令
/// </summary>
private async Task ExecuteClearPathAsync()
{
if (!CanExecuteClearPath()) return;
try
{
var pointCount = SelectedPathRoute.Points.Count;
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SelectedPathRoute.Points.Clear();
StatusText = $"已清空路径 {SelectedPathRoute.Name} 的 {pointCount} 个点";
PathFileStatus = "未保存";
LogManager.Info($"清空路径: {SelectedPathRoute.Name}, 删除了 {pointCount} 个点");
});
}
catch (Exception ex)
{
LogManager.Error($"清空路径异常: {ex.Message}", ex);
}
}
/// <summary>
/// 异步删除路径点命令
/// </summary>
private async Task ExecuteDeletePointAsync(PathPointViewModel point)
{
if (SelectedPathRoute == null || point == null) return;
try
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SelectedPathRoute.Points.Remove(point);
StatusText = $"已删除路径点: {point.Name}";
PathFileStatus = "未保存";
LogManager.Info($"删除路径点: {point.Name}");
});
}
catch (Exception ex)
{
LogManager.Error($"删除路径点异常: {ex.Message}", ex);
}
}
// 其他简单的异步命令实现...
private async Task ExecuteImportPathAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteExportPathAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteSaveAsPathAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteModelSplitterAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteViewLogAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteClearLogAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteExportLogAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteOpenSettingsAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteResetSettingsAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteImportConfigAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteCheckUpdateAsync() { await Task.CompletedTask; /* TODO */ }
private async Task ExecuteGeneratePerformanceReportAsync() { await Task.CompletedTask; /* TODO */ }
/// <summary>
/// 强制重新初始化ToolPlugin以确保获得鼠标焦点
/// </summary>
/// <returns>初始化是否成功</returns>
private bool ForceReinitializeToolPlugin()
{
LogManager.Info("开始强制重新初始化ToolPlugin以确保获得鼠标焦点");
try
{
// 使用反射调用私有方法强制重新激活ToolPlugin
var deactivateMethod = _pathPlanningManager.GetType().GetMethod("DeactivateToolPlugin",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (deactivateMethod != null)
{
deactivateMethod.Invoke(_pathPlanningManager, null);
LogManager.Info("已停用ToolPlugin");
}
// 重置激活状态标志
var isActiveField = _pathPlanningManager.GetType().GetField("_isToolPluginActive",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (isActiveField != null)
{
isActiveField.SetValue(_pathPlanningManager, false);
LogManager.Info("已重置ToolPlugin激活状态标志");
}
// 重新激活ToolPlugin
var activateMethod = _pathPlanningManager.GetType().GetMethod("ActivateToolPlugin",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (activateMethod != null)
{
var result = activateMethod.Invoke(_pathPlanningManager, null);
LogManager.Info($"ToolPlugin重新激活结果: {result}");
if (!(bool)result)
{
LogManager.Error("ToolPlugin激活失败");
return false;
}
}
LogManager.Info("ToolPlugin重新初始化成功已获得鼠标焦点");
return true;
}
catch (Exception ex)
{
LogManager.Error($"重新初始化ToolPlugin失败: {ex.Message}");
return false;
}
}
private async Task ExecuteSelectStartPointAsync()
{
await SafeExecuteAsync(() =>
{
LogManager.Info("=== 开始执行选择起点命令 ===");
if (_pathPlanningManager == null)
{
LogManager.Error("PathPlanningManager为null无法选择起点");
AutoPathStatus = "路径规划管理器未初始化";
return;
}
LogManager.Info("PathPlanningManager已初始化开始设置选择状态");
IsSelectingStartPoint = true;
IsSelectingEndPoint = false;
AutoPathStatus = "请在3D视图中点击选择起点...";
// 强制重新初始化ToolPlugin以确保获得鼠标焦点
if (!ForceReinitializeToolPlugin())
{
AutoPathStatus = "ToolPlugin初始化失败请重试";
return;
}
// 订阅PathClickToolPlugin的鼠标点击事件来获取自动路径规划的起点
LogManager.Info("订阅PathClickToolPlugin.MouseClicked事件");
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
LogManager.Info("=== 选择起点命令设置完成ToolPlugin已重新激活并获得鼠标焦点等待用户点击 ===");
}, "选择起点");
}
private async Task ExecuteSelectEndPointAsync()
{
await SafeExecuteAsync(() =>
{
LogManager.Info("=== 开始执行选择终点命令 ===");
if (_pathPlanningManager == null)
{
LogManager.Error("PathPlanningManager为null无法选择终点");
AutoPathStatus = "路径规划管理器未初始化";
return;
}
LogManager.Info("PathPlanningManager已初始化开始设置选择状态");
IsSelectingStartPoint = false;
IsSelectingEndPoint = true;
AutoPathStatus = "请在3D视图中点击选择终点...";
// 强制重新初始化ToolPlugin以确保获得鼠标焦点
if (!ForceReinitializeToolPlugin())
{
AutoPathStatus = "ToolPlugin初始化失败请重试";
return;
}
// 订阅PathClickToolPlugin的鼠标点击事件来获取自动路径规划的终点
LogManager.Info("订阅PathClickToolPlugin.MouseClicked事件");
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
LogManager.Info("=== 选择终点命令设置完成ToolPlugin已重新激活并获得鼠标焦点等待用户点击 ===");
}, "选择终点");
}
private async Task ExecuteAutoPlanPathAsync()
{
await SafeExecuteAsync(async () =>
{
if (!_hasStartPoint || !_hasEndPoint)
{
AutoPathStatus = "请先选择起点和终点";
return;
}
AutoPathStatus = "正在计算最优路径...";
LogManager.Info("=== 开始执行自动路径规划 ===");
try
{
// 调用PathPlanningManager的自动路径规划功能
// 将Point3D转换为PathPoint
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 pathRoute = await _pathPlanningManager?.AutoPlanPath(startPathPoint, endPathPoint);
if (pathRoute != null && pathRoute.Points.Count > 0)
{
LogManager.Info($"路径规划成功,共 {pathRoute.Points.Count} 个点");
// 创建新的路径视图模型
var autoPathViewModel = new PathRouteViewModel
{
Name = $"自动路径_{DateTime.Now:HHmmss}",
Description = "自动生成的最优路径",
IsActive = true
};
// 转换路径点
foreach (var point in pathRoute.Points)
{
var pointViewModel = new PathPointViewModel
{
Name = point.Name,
X = point.X,
Y = point.Y,
Z = point.Z,
Type = point.Type
};
autoPathViewModel.Points.Add(pointViewModel);
}
// 更新UI
PathRoutes.Add(autoPathViewModel);
SelectedPathRoute = autoPathViewModel;
AutoPathStatus = $"路径规划完成!共 {pathRoute.Points.Count} 个路径点";
StatusText = $"自动路径规划成功: {pathRoute.Points.Count} 个点";
LogManager.Info($"✅ 自动路径规划完成: {autoPathViewModel.Name}");
}
else
{
AutoPathStatus = "路径规划失败,未找到可行路径";
StatusText = "自动路径规划失败:未找到可行路径";
LogManager.Warning("自动路径规划失败:未找到可行路径");
}
}
catch (Exception ex)
{
LogManager.Error($"自动路径规划出错: {ex.Message}");
AutoPathStatus = $"路径规划出错: {ex.Message}";
StatusText = $"自动路径规划出错: {ex.Message}";
}
}, "自动路径规划");
}
private async Task ExecuteClearAutoPathAsync()
{
await SafeExecuteAsync(() =>
{
LogManager.Info("=== 开始重置自动路径规划状态 ===");
// 停止任何正在进行的点选择
if (_pathPlanningManager != null)
{
_pathPlanningManager.StopClickTool();
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
LogManager.Info("已停止点选择工具");
}
// 清除所有3D路径标记 - 使用PathPlanningManager的完整清除方法
if (_pathPlanningManager != null)
{
// 调用PathPlanningManager的完整清除方法这个方法会清除所有标记
try
{
// 使用反射调用私有方法Clear3DPathMarkers
var clearMethod = _pathPlanningManager.GetType().GetMethod("Clear3DPathMarkers",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (clearMethod != null)
{
clearMethod.Invoke(_pathPlanningManager, null);
LogManager.Info("已调用PathPlanningManager.Clear3DPathMarkers清除所有路径标记");
}
else
{
LogManager.Warning("未找到Clear3DPathMarkers方法使用备用清除方式");
// 备用方式直接清除RenderPlugin中的所有标记
if (PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.ClearAllMarkers();
LogManager.Info("已直接清除PathPointRenderPlugin中的所有标记");
}
}
}
catch (Exception ex)
{
LogManager.Error($"调用Clear3DPathMarkers失败: {ex.Message},使用备用清除方式");
// 备用方式
if (PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.ClearAllMarkers();
LogManager.Info("已使用备用方式清除所有标记");
}
}
// 强制重新初始化ToolPlugin以重新获得鼠标焦点
ForceReinitializeToolPlugin();
}
// 重置自动路径规划的输入状态,让用户可以重新设置起点终点
_hasStartPoint = false;
_hasEndPoint = false;
_startPoint3D = new Point3D();
_endPoint3D = new Point3D();
AutoPathStartPoint = "未选择";
AutoPathEndPoint = "未选择";
AutoPathStatus = "就绪";
IsSelectingStartPoint = false;
IsSelectingEndPoint = false;
StatusText = "已重置自动路径规划状态,可重新选择起点终点,已重新初始化鼠标工具";
LogManager.Info("重置自动路径规划已清除起点终点选择已清除所有路径点标记已重新初始化ToolPlugin");
}, "重置自动路径规划");
}
#endregion
#region
/// <summary>
/// 执行选择起点命令
/// </summary>
private void ExecuteSelectStartPoint()
{
SafeExecute(() =>
{
LogManager.Info("=== 开始执行选择起点命令 ===");
if (_pathPlanningManager == null)
{
LogManager.Error("PathPlanningManager为null无法选择起点");
AutoPathStatus = "路径规划管理器未初始化";
return;
}
LogManager.Info("PathPlanningManager已初始化开始设置选择状态");
IsSelectingStartPoint = true;
IsSelectingEndPoint = false;
AutoPathStatus = "请在3D视图中点击选择起点...";
// 直接订阅PathClickToolPlugin的鼠标点击事件来获取自动路径规划的起点
LogManager.Info("订阅PathClickToolPlugin.MouseClicked事件");
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
// 启动3D点击工具选择起点
LogManager.Info("调用PathPlanningManager.StartClickTool");
_pathPlanningManager.StartClickTool(PathPointType.StartPoint);
LogManager.Info("=== 选择起点命令设置完成,等待用户点击 ===");
}, "选择起点");
}
/// <summary>
/// 执行选择终点命令
/// </summary>
private void ExecuteSelectEndPoint()
{
SafeExecute(() =>
{
if (_pathPlanningManager == null)
{
AutoPathStatus = "路径规划管理器未初始化";
return;
}
IsSelectingEndPoint = true;
IsSelectingStartPoint = false;
AutoPathStatus = "请在3D视图中点击选择终点...";
// 直接订阅PathClickToolPlugin的鼠标点击事件来获取自动路径规划的终点
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
PathClickToolPlugin.MouseClicked += OnAutoPathMouseClicked;
// 启动3D点击工具选择终点
_pathPlanningManager.StartClickTool(PathPointType.EndPoint);
LogManager.Info("开始选择自动路径规划终点,已激活点击工具");
}, "选择终点");
}
/// <summary>
/// 执行自动路径规划命令
/// </summary>
private void ExecuteAutoPlanPath()
{
SafeExecute(() =>
{
if (!_hasStartPoint || !_hasEndPoint)
{
AutoPathStatus = "请先选择起点和终点";
return;
}
AutoPathStatus = "正在计算最优路径...";
// 在后台线程中执行路径规划
System.Threading.Tasks.Task.Run(() =>
{
try
{
// 调用PathPlanningManager的自动路径规划功能
// 将Point3D转换为PathPoint
var startPathPoint = new PathPoint
{
Name = "自动起点",
Position = _startPoint3D,
Type = PathPointType.StartPoint
};
var endPathPoint = new PathPoint
{
Name = "自动终点",
Position = _endPoint3D,
Type = PathPointType.EndPoint
};
var pathRoute = _pathPlanningManager?.AutoPlanPath(startPathPoint, endPathPoint).Result;
// 在UI线程上异步更新结果避免死锁
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(() =>
{
try
{
if (pathRoute != null && pathRoute.Points.Count > 0)
{
// 🔥 关键修复原子性UI更新避免竞态条件
try
{
// 创建新的路径视图模型
var autoPathViewModel = new PathRouteViewModel
{
Name = $"自动路径_{DateTime.Now:HHmmss}",
Description = "自动生成的最优路径",
IsActive = true
};
// 转换路径点
foreach (var point in pathRoute.Points)
{
var pointViewModel = new PathPointViewModel
{
Name = point.Name,
X = point.X,
Y = point.Y,
Z = point.Z,
Type = point.Type
};
autoPathViewModel.Points.Add(pointViewModel);
}
// 🔥 原子性操作:先添加到集合,再设置选中项,避免中间状态
PathRoutes.Add(autoPathViewModel);
// 稍微延迟选中项设置,确保集合更新完成
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(() =>
{
try
{
SelectedPathRoute = autoPathViewModel;
LogManager.Info($"✅ UI路径选择已更新: {autoPathViewModel.Name}");
}
catch (Exception ex)
{
LogManager.Error($"设置选中路径失败: {ex.Message}");
}
}),
System.Windows.Threading.DispatcherPriority.Background
);
AutoPathStatus = $"路径规划完成!共 {pathRoute.Points.Count} 个路径点";
StatusText = $"自动路径规划成功: {pathRoute.Points.Count} 个点";
LogManager.Info($"✅ UI路径更新完成: {autoPathViewModel.Name}");
}
catch (Exception uiEx)
{
LogManager.Error($"UI路径更新失败: {uiEx.Message}");
AutoPathStatus = $"路径规划完成但UI更新失败: {uiEx.Message}";
StatusText = $"自动路径规划成功,但显示更新失败";
}
}
else
{
AutoPathStatus = "路径规划失败,未找到可行路径";
StatusText = "自动路径规划失败:未找到可行路径";
LogManager.Warning("自动路径规划失败:未找到可行路径");
}
}
catch (Exception innerEx)
{
LogManager.Error($"UI线程路径规划结果更新失败: {innerEx.Message}");
AutoPathStatus = $"UI更新失败: {innerEx.Message}";
StatusText = $"路径规划UI更新失败: {innerEx.Message}";
}
}),
System.Windows.Threading.DispatcherPriority.Background
);
}
catch (Exception ex)
{
// 使用BeginInvoke异步更新异常信息避免死锁
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(() =>
{
try
{
AutoPathStatus = $"路径规划出错: {ex.Message}";
StatusText = $"自动路径规划出错: {ex.Message}";
// 详细记录异常信息
LogManager.Error($"自动路径规划出错: {ex.Message}");
LogManager.Error($"异常类型: {ex.GetType().FullName}");
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
if (ex.InnerException != null)
{
LogManager.Error($"内部异常: {ex.InnerException.Message}");
LogManager.Error($"内部异常堆栈: {ex.InnerException.StackTrace}");
}
}
catch (Exception innerEx)
{
LogManager.Error($"UI线程异常处理失败: {innerEx.Message}");
}
}),
System.Windows.Threading.DispatcherPriority.Background
);
}
});
}, "自动路径规划");
}
/// <summary>
/// 检查是否可以执行自动路径规划
/// </summary>
private bool CanExecuteAutoPlanPath()
{
return _hasStartPoint && _hasEndPoint && AutoPathVehicleSize > 0 && AutoPathSafetyMargin >= 0;
}
/// <summary>
/// 执行重置自动路径规划命令(只重置起点终点状态,不删除已生成的路径)
/// </summary>
private void ExecuteClearAutoPath()
{
SafeExecute(() =>
{
// 停止任何正在进行的点选择
if (_pathPlanningManager != null)
{
_pathPlanningManager.StopClickTool();
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
// 只清除临时的点选择标记,不清除已完成的路径
LogManager.Info("已停止点选择工具");
}
// 只清除起点、终点球体,保留已生成的路径
if (PathPointRenderPlugin.Instance != null)
{
// 只清除起点和终点球体(用于重新选择)
if (_hasStartPoint)
{
PathPointRenderPlugin.Instance.RemoveMarkerAt(_startPoint3D, 2.0);
LogManager.Info("已清除起点标记球体");
}
if (_hasEndPoint)
{
PathPointRenderPlugin.Instance.RemoveMarkerAt(_endPoint3D, 2.0);
LogManager.Info("已清除终点标记球体");
}
// 🔥 关键修改:不删除自动路径连线和标记,保留已生成的路径可视化
// 已生成的路径应该通过路径列表的删除功能来管理
}
// 🔥 关键修改不删除PathRoutes中的自动路径保留在列表中供用户管理
// 路径的删除应该通过每行的删除按钮或统一的删除功能来处理
// 如果当前选中的是自动生成的路径,也不清除选择,让用户继续查看
// 用户可以通过路径列表来管理选择状态
// 只重置自动路径规划的输入状态,让用户可以重新设置起点终点
_hasStartPoint = false;
_hasEndPoint = false;
_startPoint3D = new Point3D();
_endPoint3D = new Point3D();
AutoPathStartPoint = "未选择";
AutoPathEndPoint = "未选择";
// 保持其他设置不变,用户可能希望使用相同的车辆尺寸和安全间隙
// AutoPathVehicleSize = 1.0; // 保持用户设置
// AutoPathSafetyMargin = 0.5; // 保持用户设置
AutoPathStatus = "就绪";
IsSelectingStartPoint = false;
IsSelectingEndPoint = false;
StatusText = "已重置自动路径规划状态,可重新选择起点终点";
LogManager.Info("重置自动路径规划:已清除起点终点选择,保留已生成的路径");
}, "重置自动路径规划");
}
/// <summary>
/// 设置自动路径规划的起点(供外部调用)
/// </summary>
public void SetAutoPathStartPoint(Point3D point)
{
// 清除之前的起点标记(如果有的话)
if (_hasStartPoint && PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.RemoveMarkerAt(_startPoint3D, 2.0);
LogManager.Info("已清除之前的起点标记");
}
_startPoint3D = point;
_hasStartPoint = true;
AutoPathStartPoint = $"({point.X:F2}, {point.Y:F2}, {point.Z:F2})";
IsSelectingStartPoint = false;
// 可视化新的起点 - 使用绿色球体
if (PathPointRenderPlugin.Instance != null)
{
// 添加新的起点标记(使用负序号避免与手动路径连线)
PathPointRenderPlugin.Instance.AddCircleMarker(point, PathPointType.StartPoint, -100);
LogManager.Info("已可视化自动路径规划起点(绿色球体)");
}
if (_hasEndPoint)
{
AutoPathStatus = "起点和终点已设置,可以开始路径规划";
}
else
{
AutoPathStatus = "起点已设置,请选择终点";
}
LogManager.Info($"设置自动路径规划起点: {AutoPathStartPoint}");
}
/// <summary>
/// 设置自动路径规划的终点(供外部调用)
/// </summary>
public void SetAutoPathEndPoint(Point3D point)
{
// 清除之前的终点标记(如果有的话)
if (_hasEndPoint && PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.RemoveMarkerAt(_endPoint3D, 2.0);
LogManager.Info("已清除之前的终点标记");
}
_endPoint3D = point;
_hasEndPoint = true;
AutoPathEndPoint = $"({point.X:F2}, {point.Y:F2}, {point.Z:F2})";
IsSelectingEndPoint = false;
// 可视化新的终点 - 使用红色球体
if (PathPointRenderPlugin.Instance != null)
{
// 添加新的终点标记(使用负序号避免与手动路径连线)
PathPointRenderPlugin.Instance.AddCircleMarker(point, PathPointType.EndPoint, -200);
LogManager.Info("已可视化自动路径规划终点(红色球体)");
}
if (_hasStartPoint)
{
AutoPathStatus = "起点和终点已设置,可以开始路径规划";
}
else
{
AutoPathStatus = "终点已设置,请选择起点";
}
LogManager.Info($"设置自动路径规划终点: {AutoPathEndPoint}");
}
/// <summary>
/// 处理自动路径规划的鼠标点击事件直接从PathClickToolPlugin获取
/// </summary>
private void OnAutoPathMouseClicked(object sender, PickItemResult pickResult)
{
try
{
if (pickResult == null)
{
LogManager.Warning("收到空的点击结果事件");
return;
}
var point3D = pickResult.Point;
LogManager.Info($"收到自动路径规划点击事件: ({point3D.X:F2}, {point3D.Y:F2}, {point3D.Z:F2})");
LogManager.Info($"点击对象: {pickResult.ModelItem?.DisplayName ?? "NULL"}");
if (IsSelectingStartPoint)
{
// 设置起点
SetAutoPathStartPoint(point3D);
// 停止3D点击工具并取消事件订阅
_pathPlanningManager.StopClickTool();
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
LogManager.Info("已设置自动路径规划起点");
}
else if (IsSelectingEndPoint)
{
// 设置终点
SetAutoPathEndPoint(point3D);
// 停止3D点击工具并取消事件订阅
_pathPlanningManager.StopClickTool();
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
LogManager.Info("已设置自动路径规划终点");
}
else
{
// 如果不在选择模式中,取消事件订阅
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
LogManager.Warning("收到点击事件但未在选择模式中");
}
}
catch (Exception ex)
{
LogManager.Error($"处理自动路径规划点击事件时发生错误: {ex.Message}");
AutoPathStatus = $"获取点击位置失败: {ex.Message}";
// 确保清理状态
IsSelectingStartPoint = false;
IsSelectingEndPoint = false;
if (_pathPlanningManager != null)
{
_pathPlanningManager.StopClickTool();
PathClickToolPlugin.MouseClicked -= OnAutoPathMouseClicked;
}
}
}
#endregion
#endregion
#region PathPlanningManager
/// <summary>
/// 初始化路径规划管理器
/// </summary>
private void InitializePathPlanningManager()
{
SafeExecute(() =>
{
// 获取或创建PathPlanningManager实例
_pathPlanningManager = PathPlanningManager.GetActivePathManager() ?? new PathPlanningManager();
// 订阅 PathPlanningManager 的事件
if (_pathPlanningManager != null)
{
// 订阅路径编辑状态变更事件
_pathPlanningManager.EditStateChanged += OnEditStateChanged;
// 订阅路径点操作事件
_pathPlanningManager.PathPointOperation += OnPathPointOperation;
// 订阅路径点列表更新事件
_pathPlanningManager.PathPointsListUpdated += OnPathPointsListUpdated;
// 订阅当前路径变更事件
_pathPlanningManager.CurrentRouteChanged += OnCurrentRouteChanged;
// 订阅状态和错误事件
_pathPlanningManager.StatusChanged += OnPathManagerStatusChanged;
_pathPlanningManager.ErrorOccurred += OnPathManagerErrorOccurred;
LogManager.Info("PathPlanningManager事件订阅完成");
}
LogManager.Info("PathPlanningManager已初始化并集成到ViewModel");
}, "初始化PathPlanningManager");
}
#region PathPlanningManager
/// <summary>
/// 处理 EditStateChanged 事件
/// </summary>
private void OnEditStateChanged(object sender, PathEditStateChangedEventArgs e)
{
try
{
// 安全地在UI线程上更新使用BeginInvoke避免死锁
if (System.Windows.Application.Current?.Dispatcher != null)
{
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
{
// 已在UI线程上
UpdatePathEditState(e.NewState);
}
else
{
// 需要切换到UI线程使用BeginInvoke异步调用
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(() =>
{
try
{
UpdatePathEditState(e.NewState);
}
catch (Exception innerEx)
{
LogManager.Error($"UI线程路径编辑状态更新内部错误: {innerEx.Message}");
}
}),
System.Windows.Threading.DispatcherPriority.Background
);
}
}
else
{
// Dispatcher不可用直接更新
UpdatePathEditState(e.NewState);
}
}
catch (Exception ex)
{
LogManager.Error($"处理路径编辑状态变更失败: {ex.Message}");
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
}
}
private void UpdatePathEditState(PathEditState newState)
{
SafeExecute(() =>
{
// 更新 ViewModel 的 IsPathEditMode 状态
// Creating 或 Editing 状态都视为编辑模式
IsPathEditMode = (newState == PathEditState.Creating || newState == PathEditState.Editing);
// 如果有选中的路径,也更新其 IsActive 状态
if (SelectedPathRoute != null)
{
SelectedPathRoute.IsActive = IsPathEditMode;
}
LogManager.Info($"UI已更新 - 路径编辑状态已变更为: {newState}, IsPathEditMode: {IsPathEditMode}");
}, "处理路径编辑状态变更事件");
}
/// <summary>
/// 处理 PathPointOperation 事件
/// </summary>
private void OnPathPointOperation(object sender, PathPointOperationEventArgs e)
{
try
{
// 使用UIStateManager进行线程安全的UI更新
_uiStateManager.QueueUIUpdate(() =>
{
try
{
if (e.OperationType == PathPointOperationType.Added)
{
AddPathPointToUI(e.PathPoint);
}
else if (e.OperationType == PathPointOperationType.Removed)
{
RemovePathPointFromUI(e.PathPoint);
}
}
catch (Exception ex)
{
LogManager.Error($"UI线程路径点操作失败: {ex.Message}");
}
}, UIUpdatePriority.Normal);
}
catch (Exception ex)
{
LogManager.Error($"处理路径点操作事件失败: {ex.Message}");
}
}
private void AddPathPointToUI(NavisworksTransport.PathPoint pathPoint)
{
if (pathPoint != null && SelectedPathRoute != null)
{
// 创建 WPF ViewModel 对应的 PathPoint
var newWpfPoint = new PathPointViewModel
{
Name = pathPoint.Name,
X = pathPoint.X,
Y = pathPoint.Y,
Z = pathPoint.Z,
Type = pathPoint.Type // 同步 Type 属性
};
SelectedPathRoute.Points.Add(newWpfPoint);
LogManager.Info($"UI已更新 - 添加路径点: {pathPoint.Name}");
}
}
private void RemovePathPointFromUI(NavisworksTransport.PathPoint pathPoint)
{
if (pathPoint != null && SelectedPathRoute != null)
{
// 在 WPF ViewModel 中找到并移除对应的 PathPoint
var pointToRemove = SelectedPathRoute.Points.FirstOrDefault(p => p.Name == pathPoint.Name);
if (pointToRemove != null)
{
SelectedPathRoute.Points.Remove(pointToRemove);
LogManager.Info($"UI已更新 - 移除路径点: {pathPoint.Name}");
}
}
}
/// <summary>
/// 处理 PathPointsListUpdated 事件
/// </summary>
private void OnPathPointsListUpdated(object sender, PathPointsListUpdatedEventArgs e)
{
try
{
// 使用BeginInvoke确保在UI线程上更新避免死锁
if (System.Windows.Application.Current?.Dispatcher != null)
{
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
{
// 已在UI线程上
UpdatePathPointsList(e.Route);
}
else
{
// 使用BeginInvoke异步更新
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(() =>
{
try
{
UpdatePathPointsList(e.Route);
}
catch (Exception innerEx)
{
LogManager.Error($"UI线程路径点列表更新内部错误: {innerEx.Message}");
}
}),
System.Windows.Threading.DispatcherPriority.Background
);
}
}
else
{
UpdatePathPointsList(e.Route);
}
}
catch (Exception ex)
{
LogManager.Error($"处理路径点列表更新事件失败: {ex.Message}");
}
}
private void UpdatePathPointsList(NavisworksTransport.PathRoute updatedRoute)
{
SafeExecute(() =>
{
// 查找或创建对应的 WPF ViewModel
var routeViewModel = PathRoutes.FirstOrDefault(r => r.Name == updatedRoute?.Name);
if (routeViewModel == null && updatedRoute != null)
{
// 如果UI列表中没有则创建一个新的
routeViewModel = new PathRouteViewModel
{
Name = updatedRoute.Name,
Description = updatedRoute.Description,
IsActive = true // 或根据实际情况设置
};
PathRoutes.Add(routeViewModel);
}
// 更新 ViewModel 的点列表
if (routeViewModel != null && updatedRoute != null)
{
routeViewModel.Points.Clear();
foreach (var corePoint in updatedRoute.Points)
{
var wpfPoint = new PathPointViewModel
{
Name = corePoint.Name,
X = corePoint.X,
Y = corePoint.Y,
Z = corePoint.Z,
Type = corePoint.Type // 同步 Type 属性
};
routeViewModel.Points.Add(wpfPoint);
}
LogManager.Info($"UI已更新 - 路径点列表已同步: {updatedRoute.Name}");
}
}, "处理路径点列表更新事件");
}
/// <summary>
/// 处理 CurrentRouteChanged 事件
/// </summary>
private void OnCurrentRouteChanged(object sender, CurrentRouteChangedEventArgs e)
{
try
{
// 安全地在UI线程上更新使用BeginInvoke避免死锁
if (System.Windows.Application.Current?.Dispatcher != null)
{
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
{
// 已在UI线程上
UpdateCurrentRoute(e.NewRoute);
}
else
{
// 需要切换到UI线程使用BeginInvoke异步调用
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(() =>
{
try
{
UpdateCurrentRoute(e.NewRoute);
}
catch (Exception innerEx)
{
LogManager.Error($"UI线程当前路径更新内部错误: {innerEx.Message}");
}
}),
System.Windows.Threading.DispatcherPriority.Background
);
}
}
else
{
// Dispatcher不可用直接更新
UpdateCurrentRoute(e.NewRoute);
}
}
catch (Exception ex)
{
LogManager.Error($"处理当前路径变更失败: {ex.Message}");
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
}
}
private void UpdateCurrentRoute(NavisworksTransport.PathRoute newRoute)
{
SafeExecute(() =>
{
if (newRoute != null)
{
// 更新 SelectedPathRoute 为新的当前路径
SelectedPathRoute = PathRoutes.FirstOrDefault(r => r.Name == newRoute.Name) ?? SelectedPathRoute;
StatusText = $"当前活动路径: {newRoute.Name}";
LogManager.Info($"[UI同步] 当前路径已变更: {newRoute.Name}");
}
}, "处理当前路径变更事件");
}
/// <summary>
/// 处理 PathManager 的 StatusChanged 事件
/// </summary>
private void OnPathManagerStatusChanged(object sender, PathPlanningStatusChangedEventArgs e)
{
try
{
// 🔥 关键修复简化状态更新逻辑ViewModelBase已处理线程安全
StatusText = e.StatusMessage;
LogManager.Info($"PathManager状态更新: {e.StatusMessage}");
}
catch (Exception ex)
{
LogManager.Error($"PathManager状态更新失败: {ex.Message}");
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
}
}
/// <summary>
/// 处理 PathManager 的 ErrorOccurred 事件
/// </summary>
private void OnPathManagerErrorOccurred(object sender, PathPlanningErrorOccurredEventArgs e)
{
// 使用 Dispatcher 异步确保在 UI 线程上更新(避免死锁)
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
StatusText = $"错误: {e.ErrorMessage}";
LogManager.Error($"PathManager错误: {e.ErrorMessage}");
// 可以考虑显示一个错误对话框
// MessageBox.Show(e.ErrorMessage, "PathManager 错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (Exception ex)
{
LogManager.Error($"PathManager错误处理UI更新失败: {ex.Message}");
}
}), System.Windows.Threading.DispatcherPriority.Background);
}
#endregion
/// <summary>
/// 开始3D路径编辑
/// </summary>
private void Start3DPathEditing()
{
SafeExecute(() =>
{
if (SelectedPathRoute != null && _pathPlanningManager != null)
{
// 将WPF模型转换为PathPlanningManager的路径模型
var planningRoute = ConvertToPathPlanningRoute(SelectedPathRoute);
// 开始编辑模式
_pathPlanningManager.SwitchToEditingState(planningRoute);
StatusText = $"已开始3D编辑模式: {SelectedPathRoute.Name}";
LogManager.Info($"开始3D路径编辑: {SelectedPathRoute.Name}");
}
}, "开始3D路径编辑");
}
/// <summary>
/// 结束3D路径编辑
/// </summary>
private void End3DPathEditing()
{
SafeExecute(() =>
{
if (_pathPlanningManager != null)
{
// 完成编辑并保存
bool success = _pathPlanningManager.FinishEditing();
if (success)
{
// 更新WPF模型
UpdatePathRouteFromPlanning();
StatusText = "3D路径编辑已完成";
PathFileStatus = "未保存";
}
else
{
StatusText = "3D路径编辑完成失败";
}
LogManager.Info("结束3D路径编辑");
}
}, "结束3D路径编辑");
}
/// <summary>
/// 将WPF路径视图模型转换为Core层路径模型
/// </summary>
private NavisworksTransport.PathRoute ConvertToPathPlanningRoute(PathRouteViewModel wpfRoute)
{
if (wpfRoute == null) return null;
var planningRoute = new NavisworksTransport.PathRoute
{
Name = wpfRoute.Name,
Description = wpfRoute.Description ?? "",
Points = new List<NavisworksTransport.PathPoint>()
};
// 转换路径点
foreach (var wpfPoint in wpfRoute.Points)
{
var planningPoint = new NavisworksTransport.PathPoint
{
Name = wpfPoint.Name,
X = wpfPoint.X,
Y = wpfPoint.Y,
Z = wpfPoint.Z,
Type = NavisworksTransport.PathPointType.WayPoint // 默认类型
};
planningRoute.Points.Add(planningPoint);
}
return planningRoute;
}
/// <summary>
/// 从PathPlanningManager更新WPF路径模型
/// </summary>
private void UpdatePathRouteFromPlanning()
{
SafeExecute(() =>
{
if (_pathPlanningManager?.CurrentRoute != null && SelectedPathRoute != null)
{
var planningRoute = _pathPlanningManager.CurrentRoute;
// 更新路径基本信息
SelectedPathRoute.Name = planningRoute.Name;
SelectedPathRoute.Description = planningRoute.Description;
// 清空并重新添加路径点
SelectedPathRoute.Points.Clear();
foreach (var planningPoint in planningRoute.Points)
{
var wpfPoint = new PathPointViewModel
{
Name = planningPoint.Name,
X = planningPoint.X,
Y = planningPoint.Y,
Z = planningPoint.Z,
Type = planningPoint.Type
};
SelectedPathRoute.Points.Add(wpfPoint);
}
// 触发UI更新
OnPropertyChanged(nameof(SelectedPathRoute));
StatusText = $"已更新路径: {SelectedPathRoute.Name} ({SelectedPathRoute.Points.Count} 个点)";
}
}, "更新路径模型");
}
#endregion
#region
/// <summary>
/// 更新指令文本
/// </summary>
public async Task UpdateInstructionTextAsync()
{
await SafeExecuteAsync(async () =>
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (NavisApplication.ActiveDocument?.Models?.Count > 0)
{
InstructionText = "请在主界面中点击选择模型";
}
else
{
InstructionText = "请先打开一个Navisworks模型文件";
}
});
}, "更新指令文本");
}
/// <summary>
/// 更新选择显示
/// </summary>
public async Task UpdateSelectionDisplayAsync()
{
await SafeExecuteAsync(async () =>
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (NavisApplication.ActiveDocument?.CurrentSelection?.SelectedItems?.Count > 0)
{
var selectedCount = NavisApplication.ActiveDocument.CurrentSelection.SelectedItems.Count;
SelectedModelsText = $"选中模型: {selectedCount} 个";
}
else
{
SelectedModelsText = "选中模型: 0 个";
}
});
}, "更新选择显示");
}
/// <summary>
/// 初始化物流类别
/// </summary>
private async Task InitializeCategoriesAsync()
{
await SafeExecuteAsync(async () =>
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AvailableCategories.Clear();
// 添加所有物流元素类型
foreach (var elementType in Enum.GetValues(typeof(CategoryAttributeManager.LogisticsElementType)))
{
AvailableCategories.Add(elementType.ToString());
}
// 设置默认选择
if (AvailableCategories.Count > 0)
{
SelectedCategory = AvailableCategories[0];
}
});
LogManager.Info($"已初始化 {AvailableCategories.Count} 个物流类别");
}, "初始化物流类别");
}
/// <summary>
/// 更新物流模型列表(显示所有具有物流属性的模型)
/// </summary>
private void UpdateLogisticsModels()
{
// 直接调用刷新所有物流模型的方法
_ = RefreshAllLogisticsModelsAsync();
}
/// <summary>
/// 从模型项获取物流类型
/// </summary>
private string GetLogisticsTypeFromItem(ModelItem item)
{
try
{
// 查找物流属性类别
foreach (var category in item.PropertyCategories)
{
if (category.DisplayName == CategoryAttributeManager.LogisticsCategories.LOGISTICS)
{
foreach (var property in category.Properties)
{
if (property.DisplayName == CategoryAttributeManager.LogisticsProperties.TYPE)
{
return property.Value.ToDisplayString();
}
}
}
}
}
catch (Exception ex)
{
LogManager.Error($"获取物流类型失败: {ex.Message}");
}
return null;
}
/// <summary>
/// 从模型项获取物流属性描述
/// </summary>
private string GetLogisticsAttributesFromItem(ModelItem item)
{
try
{
var attributes = new System.Text.StringBuilder();
// 查找物流属性类别
foreach (var category in item.PropertyCategories)
{
if (category.DisplayName == CategoryAttributeManager.LogisticsCategories.LOGISTICS)
{
foreach (var property in category.Properties)
{
if (property.DisplayName != CategoryAttributeManager.LogisticsProperties.TYPE)
{
if (attributes.Length > 0) attributes.Append(", ");
attributes.Append($"{property.DisplayName}: {property.Value.ToDisplayString()}");
}
}
break;
}
}
return attributes.Length > 0 ? attributes.ToString() : null;
}
catch (Exception ex)
{
LogManager.Error($"获取物流属性失败: {ex.Message}");
return null;
}
}
/// <summary>
/// 查找所有具有物流属性的模型项
/// </summary>
private ModelItemCollection FindAllLogisticsModels()
{
var logisticsItems = new ModelItemCollection();
try
{
var document = NavisApplication.ActiveDocument;
if (document?.Models != null)
{
// 使用Search API查找所有具有物流属性的模型项
var search = new Search();
search.Selection.SelectAll();
// 查找具有物流属性类别的项目
search.SearchConditions.Add(
SearchCondition.HasCategoryByDisplayName(CategoryAttributeManager.LogisticsCategories.LOGISTICS)
);
logisticsItems = search.FindAll(document, false);
LogManager.Info($"找到 {logisticsItems.Count} 个具有物流属性的模型项");
}
}
catch (Exception ex)
{
LogManager.Error($"查找物流模型失败: {ex.Message}");
}
return logisticsItems;
}
/// <summary>
/// 获取模型中的所有ModelItem
/// </summary>
private List<ModelItem> GetAllModelItems()
{
var allItems = new List<ModelItem>();
try
{
var document = NavisApplication.ActiveDocument;
if (document?.Models != null)
{
foreach (var model in document.Models)
{
// 从根模型的子项开始收集,以避免包含不可见的根节点
foreach (var item in model.RootItem.Children)
{
CollectModelItems(item, allItems);
}
}
}
}
catch (Exception ex)
{
LogManager.Error($"获取所有模型项失败: {ex.Message}");
}
return allItems;
}
/// <summary>
/// 递归收集ModelItem及其所有子项
/// </summary>
private void CollectModelItems(ModelItem item, List<ModelItem> collection)
{
if (item == null) return;
collection.Add(item);
// 递归添加子项目
if (item.Children != null && item.Children.Count() > 0)
{
foreach (ModelItem child in item.Children)
{
CollectModelItems(child, collection);
}
}
}
/// <summary>
/// 检查模型项是否具有物流属性
/// </summary>
private bool HasLogisticsAttributes(ModelItem item)
{
try
{
foreach (var category in item.PropertyCategories)
{
if (category.DisplayName == CategoryAttributeManager.LogisticsCategories.LOGISTICS)
{
return true;
}
}
}
catch (Exception ex)
{
LogManager.Error($"检查物流属性失败: {ex.Message}");
}
return false;
}
#endregion
#region
/// <summary>
/// 向后兼容:同步版本的更新指令文本方法
/// </summary>
[Obsolete("请使用UpdateInstructionTextAsync方法以获得更好的性能", false)]
public void UpdateInstructionText()
{
Task.Run(async () => await UpdateInstructionTextAsync());
}
/// <summary>
/// 向后兼容:同步版本的更新选择显示方法
/// </summary>
[Obsolete("请使用UpdateSelectionDisplayAsync方法以获得更好的性能", false)]
public void UpdateSelectionDisplay()
{
Task.Run(async () => await UpdateSelectionDisplayAsync());
}
/// <summary>
/// 向后兼容:同步版本的刷新物流模型方法
/// </summary>
[Obsolete("请使用RefreshAllLogisticsModelsAsync方法以获得更好的性能", false)]
public void RefreshAllLogisticsModels()
{
Task.Run(async () => await RefreshAllLogisticsModelsAsync());
}
/// <summary>
/// 异步版本的刷新所有物流模型方法
/// </summary>
public async Task RefreshAllLogisticsModelsAsync()
{
await SafeExecuteAsync(async () =>
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
LogisticsModels.Clear();
// 查找所有具有物流属性的模型项
var allLogisticsItems = FindAllLogisticsModels();
foreach (var item in allLogisticsItems)
{
var logisticsType = GetLogisticsTypeFromItem(item);
var attributes = GetLogisticsAttributesFromItem(item);
var model = new LogisticsModel
{
Name = item.DisplayName ?? "未命名模型",
Category = logisticsType ?? "未分类",
Attributes = attributes ?? "无属性",
IsVisible = !item.IsHidden,
NavisworksItem = item
};
LogisticsModels.Add(model);
}
});
LogManager.Info($"已刷新所有物流模型列表,共 {LogisticsModels.Count} 个模型");
}, "刷新所有物流模型列表");
}
/// <summary>
/// 向后兼容提供CommandManager访问接口
/// </summary>
public NavisworksTransport.Commands.CommandManager CommandManager => _commandManager;
/// <summary>
/// 向后兼容提供UIStateManager访问接口
/// </summary>
public UIStateManager UIStateManager => _uiStateManager;
/// <summary>
/// 验证ViewModel状态是否正常
/// </summary>
public bool IsValidState()
{
return _uiStateManager != null &&
_commandManager != null &&
LogisticsModels != null &&
PathRoutes != null &&
AvailableCategories != null;
}
/// <summary>
/// 获取ViewModel状态信息
/// </summary>
public string GetStateInfo()
{
return $"UIStateManager: {(_uiStateManager != null ? "" : "")}, " +
$"CommandManager: {(_commandManager != null ? "" : "")}, " +
$"物流模型数量: {LogisticsModels?.Count ?? 0}, " +
$"路径数量: {PathRoutes?.Count ?? 0}";
}
#endregion
}
}