清理多余的动画检测实时计算代码

This commit is contained in:
tian 2025-12-08 15:04:16 +08:00
parent f8320066c1
commit 12616629b0
4 changed files with 41 additions and 162 deletions

View File

@ -10,7 +10,7 @@
4. [ ] (功能)动画检测时,过滤门和其他可通行构件
5. [ ] BUG只有手动路径时导出路径按钮没激活
6. [ ] BUG重复打开模型有时程序崩溃需要先关闭物流插件窗口
7. [ ] (优化)生成动画时,显示要检测的构件数量,当数量大于阈值时,给于警示,并预估处理时间。
7. [ ] (优化)提高碰撞检测在处理大型模型时的性能
### [2025/12/05]

View File

@ -266,8 +266,13 @@ namespace NavisworksTransport.Core.Animation
// 预计算动画帧和碰撞
PrecomputeAnimationFrames();
// 关键修复:将车辆立即移动到路径起点
// 这样动画就从路径起点开始,而不是从车辆当前位置开始
// 验证预计算结果
if (_animationFrames == null || _animationFrames.Count == 0)
{
throw new InvalidOperationException("动画帧预计算失败,无法创建动画");
}
// 将车辆移动到路径起点
MoveVehicleToPathStart();
// 记录文档单位信息
@ -595,8 +600,8 @@ namespace NavisworksTransport.Core.Animation
LogManager.Info("TimeLiner 不可用,使用基础动画功能");
}
// 设置动态碰撞检测(简化版本
SetupDynamicClashDetection();
// 设置碰撞检测转发用于高亮显示和UI更新
SetupCollisionReportForwarding();
// 初始化动画状态
_animationStartTime = DateTime.Now;
@ -1240,20 +1245,20 @@ namespace NavisworksTransport.Core.Animation
}
/// <summary>
/// 设置动态碰撞检测(实时模式,集成 Clash Detective
/// 设置碰撞报告转发用于高亮显示和UI更新
/// </summary>
private void SetupDynamicClashDetection()
private void SetupCollisionReportForwarding()
{
try
{
// 订阅碰撞检测事件
ClashDetectiveIntegration.Instance.CollisionDetected += OnClashDetectiveCollisionDetected;
LogManager.Info("动态碰撞检测设置完成(实时模式)");
LogManager.Info("碰撞报告转发设置完成");
}
catch (Exception ex)
{
LogManager.Error($"设置动态碰撞检测失败: {ex.Message}");
LogManager.Error($"设置碰撞报告转发失败: {ex.Message}");
}
}
@ -1283,18 +1288,6 @@ namespace NavisworksTransport.Core.Animation
CollisionDetected?.Invoke(this, e);
}
// 已删除CheckAndHighlightCollisions - 使用Clash Detective集成代替
/// <summary>
/// 检查两个包围盒是否相交
/// </summary>
private bool BoundingBoxesIntersect(BoundingBox3D box1, BoundingBox3D box2)
{
return !(box1.Max.X < box2.Min.X || box2.Max.X < box1.Min.X ||
box1.Max.Y < box2.Min.Y || box2.Max.Y < box1.Min.Y ||
box1.Max.Z < box2.Min.Z || box2.Max.Z < box1.Min.Z);
}
/// <summary>
/// 设置动画持续时间
/// </summary>
@ -1690,115 +1683,6 @@ namespace NavisworksTransport.Core.Animation
}
}
/// <summary>
/// 快速测试TimeLiner API的可用性
/// </summary>
public bool TestTimeLinerAPI()
{
try
{
var doc = NavisApplication.ActiveDocument;
// 尝试访问TimeLiner
var timeliner = doc.Timeliner;
if (timeliner != null)
{
LogManager.Info("TimeLiner API基本可用");
return true;
}
else
{
LogManager.Info("TimeLiner API不可用");
return false;
}
}
catch (Exception ex)
{
LogManager.Info($"TimeLiner API测试失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 简化的动画设置方法,支持直接传入部件和路径
/// </summary>
/// <param name="component">部件模型</param>
/// <param name="pathPoints">路径点列表</param>
/// <param name="durationSeconds">动画持续时间(秒)</param>
public bool SetupSimpleAnimation(ModelItem component, List<Point3D> pathPoints, double durationSeconds = 10.0)
{
try
{
if (component == null)
{
LogManager.Error("部件模型不能为空");
return false;
}
if (pathPoints == null || pathPoints.Count < 2)
{
LogManager.Error("路径点数量必须至少为2个");
return false;
}
// 使用现有的SetupAnimation方法
SetupAnimation(component, pathPoints, durationSeconds);
LogManager.Info($"简化动画设置成功:部件={component.DisplayName}, 路径点数={pathPoints.Count}, 时长={durationSeconds}秒");
return true;
}
catch (Exception ex)
{
LogManager.Error($"简化动画设置失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 获取当前选中的部件模型(简化版本)
/// </summary>
/// <returns>选中的部件模型如果没有选中或选中多个则返回null</returns>
public static ModelItem GetSelectedComponent()
{
try
{
var doc = NavisApplication.ActiveDocument;
var selectedItems = doc.CurrentSelection.SelectedItems;
if (selectedItems.Count == 1)
{
var item = selectedItems.First;
if (item.HasGeometry)
{
LogManager.Info($"已获取选中部件: {item.DisplayName}");
return item;
}
else
{
LogManager.Warning("选中的项目没有几何体,可能不适合用于动画");
return null;
}
}
else if (selectedItems.Count == 0)
{
LogManager.Info("没有选中任何项目");
return null;
}
else
{
LogManager.Info($"选中了{selectedItems.Count}个项目,请只选择一个部件");
return null;
}
}
catch (Exception ex)
{
LogManager.Error($"获取选中部件失败: {ex.Message}");
return null;
}
}
/// <summary>
/// 设置动画帧率
/// </summary>

View File

@ -529,7 +529,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 从配置读取动画持续时间
AnimationDuration = config.Animation.DurationSeconds;
// 设置初始状态 - 修改: 默认状态应该是未激活,等待有效动画
// 设置初始状态 - 默认状态未激活,等待有效动画
CanPauseAnimation = false;
CanStopAnimation = false;
@ -540,9 +540,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 从配置读取碰撞检测参数
DetectionGap = config.Animation.DetectionGapMeters;
AnimationFrameRate = config.Animation.FrameRate;
// 注意CollisionDetectionAccuracy(步长)和MovementSpeed(速度)现在是计算属性,不需要设置初始值
// 修改: 使用新的按钮状态更新方法来设置正确的初始状态
// 设置动画按钮的初始状态
UpdateAnimationButtonStates();
LogManager.Info($"动画设置初始化完成 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒, 检测间隙:{DetectionGap}米");
@ -553,7 +552,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// </summary>
private void InitializeCommands()
{
// 原有命令
StartAnimationCommand = new RelayCommand(async () => await ExecuteStartAnimationAsync(), () => CanStartAnimation);
PauseAnimationCommand = new RelayCommand(async () => await ExecutePauseAnimationAsync(), () => CanPauseAnimation);
StopAnimationCommand = new RelayCommand(async () => await ExecuteStopAnimationAsync(), () => CanStopAnimation);
@ -561,8 +559,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SelectAnimatedObjectCommand = new RelayCommand(ExecuteSelectAnimatedObject);
ClearAnimatedObjectCommand = new RelayCommand(ExecuteClearAnimatedObject, () => HasSelectedAnimatedObject);
GenerateAnimationCommand = new RelayCommand(ExecuteGenerateAnimation, () => CanGenerateAnimation);
// 媒体控制命令
PlayForwardCommand = new RelayCommand(ExecutePlayForward, CanExecuteMediaCommands);
PlayReverseCommand = new RelayCommand(ExecutePlayReverse, CanExecuteMediaCommands);
StepForwardCommand = new RelayCommand(ExecuteStepForward, CanExecuteMediaCommands);
@ -970,7 +966,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
OnPropertyChanged(nameof(MovementSpeed));
OnPropertyChanged(nameof(PathLength));
// 使用新的统一按钮状态更新方法
// 按钮状态更新
UpdateAnimationButtonStates();
// 更新碰撞状态
@ -992,11 +988,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// <summary>
/// 处理动画进度变化事件
/// 直接使用Dispatcher更新UI避免UIStateManager的超时机制导致UI积压
/// 使用Dispatcher更新UI
/// </summary>
private void OnAnimationProgressChanged(object sender, double progressPercent)
{
// 直接使用Dispatcher.BeginInvoke进行UI更新避免UIStateManager的5秒超时导致积压
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
// 更新时间轴相关属性
@ -1008,11 +1003,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// <summary>
/// 处理动画状态变化事件
/// 直接使用Dispatcher更新UI避免UIStateManager的超时机制导致UI积压
/// </summary>
private void OnAnimationStateChanged(object sender, NavisworksTransport.Core.Animation.AnimationState state)
{
// 直接使用Dispatcher.BeginInvoke进行UI更新避免UIStateManager的5秒超时导致积压
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
switch (state)
@ -1346,8 +1339,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
UpdateMainStatus("动画对象分析失败,将使用实时计算");
LogManager.Warning("[缓存预计算] 预计算失败,碰撞检测将使用实时计算模式");
UpdateMainStatus("动画对象分析失败,无法生成动画");
LogManager.Error("[缓存预计算] 预计算失败: 无法构建碰撞排除列表");
}
}));
}
@ -1404,15 +1397,19 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (!success)
{
LogManager.Warning("[动画生成] 动画对象分析失败,将使用实时计算模式");
var msg = "[动画生成] 动画对象分析失败,无法继续生成动画";
LogManager.Error(msg);
UpdateMainStatus("生成失败:对象分析错误");
return; // 关键修改:直接返回,不再回退到实时模式
}
}
catch (Exception cacheEx)
{
LogManager.Warning($"[动画生成] 缓存构建失败: {cacheEx.Message},将使用实时计算模式");
LogManager.Error($"[动画生成] 缓存构建失败: {cacheEx.Message}");
UpdateMainStatus($"生成失败:{cacheEx.Message}");
return; // 关键修改:处理异常并返回
}
// 原有的动画生成逻辑
UpdateMainStatus("正在生成路径动画...", -1, true);
// 设置动画参数到PathAnimationManager
@ -1424,13 +1421,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 将PathRouteViewModel的点转换为Point3D列表
var pathPoints = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList();
// 添加调试日志
LogManager.Info($"[ExecuteGenerateAnimation] 准备创建动画: 路径名称='{CurrentPathRoute.Name}', ID='{CurrentPathRoute.Id}', 动画对象='{SelectedAnimatedObject.DisplayName}'");
// 使用PathAnimationManager创建物体动画真正的物体移动动画会设置状态为Ready
// 使用PathAnimationManager创建物体动画
_pathAnimationManager.CreateAnimation(SelectedAnimatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name, CurrentPathRoute.Id);
// 更新状态 - 使用新的按钮状态更新方法
// 更新状态
UpdateAnimationButtonStates();
UpdateMainStatus("动画生成成功");

View File

@ -18,7 +18,7 @@ namespace NavisworksTransport.UI.WPF
// 分层管理视图
private LayerManagementView _layerManagementView;
// 类别设置视图
private ModelSettingsView _modelSettingsView;
@ -37,7 +37,7 @@ namespace NavisworksTransport.UI.WPF
ViewModel = new LogisticsControlViewModel();
SystemManagementViewModel = new SystemManagementViewModel(ViewModel); // 传递主ViewModel引用
DataContext = ViewModel;
// 为SystemManagementView设置独立的DataContext
SystemManagementView.DataContext = SystemManagementViewModel;
@ -59,13 +59,13 @@ namespace NavisworksTransport.UI.WPF
// 创建分层管理视图传入主ViewModel以启用统一状态栏
_layerManagementView = new LayerManagementView(ViewModel);
// 将分层管理视图添加到主界面
LayerManagementContent.Content = _layerManagementView;
// 创建类别设置视图传入主ViewModel引用以启用统一状态栏
_modelSettingsView = new ModelSettingsView(ViewModel);
// 将类别设置视图添加到主界面
ModelSettingsContent.Content = _modelSettingsView;
@ -75,7 +75,7 @@ namespace NavisworksTransport.UI.WPF
// 初始化PathEditingView
InitializePathEditingView();
// 初始化SystemManagementView
InitializeSystemManagementView();
@ -210,7 +210,7 @@ namespace NavisworksTransport.UI.WPF
LogManager.Error($"初始化PathEditingView失败: {ex.Message}");
}
}
/// <summary>
/// 初始化SystemManagementView
/// </summary>
@ -336,13 +336,13 @@ namespace NavisworksTransport.UI.WPF
// 清理PathEditingView
PathEditingView?.Cleanup();
// 🔧 修复清理ModelSettingsView会调用ViewModel的Dispose
_modelSettingsView?.Cleanup();
// 🔧 修复清理LayerManagementView会调用ViewModel的Dispose
_layerManagementView?.Cleanup();
// 清理SystemManagementViewModel
SystemManagementViewModel?.Cleanup();
@ -429,14 +429,13 @@ namespace NavisworksTransport.UI.WPF
{
// 优先从PathEditingView获取选中的路径
PathRouteViewModel selectedPath = null;
if (PathEditingView?.ViewModel?.SelectedPathRoute != null)
{
selectedPath = PathEditingView.ViewModel.SelectedPathRoute;
LogManager.Info($"从PathEditingView同步路径: {selectedPath.Name}");
}
// 主ViewModel不再包含SelectedPathRoute仅从PathEditingView获取路径
if (selectedPath != null)
{
AnimationControlView.ViewModel.SetCurrentPath(selectedPath);
@ -466,7 +465,7 @@ namespace NavisworksTransport.UI.WPF
{
await _layerManagementView.ViewModel.UpdateCurrentSelectionAsync();
}
// 同时更新类别设置视图的ViewModel
if (_modelSettingsView?.DataContext is ModelSettingsViewModel modelSettingsViewModel)
{