步进式动画系统完整方案                                                                                        │
     │                                                                                                               │
     │ 核心架构                                                                                                      │
     │                                                                                                               │
     │ - 步进式播放：基于帧索引而非时间                                                                              │
     │ - 预计算碰撞：提前计算所有碰撞点                                                                              │
     │ - 逐帧控制：支持单帧前进/后退                                                                                 │
     │ - 双向导航：可以在任意帧之间跳转                                                                              │
     │                                                                                                               │
     │ 实现方案                                                                                                      │
     │                                                                                                               │
     │ 1. 步进式动画数据结构                                                                                         │
     │                                                                                                               │
     │ // 动画帧数据                                                                                                 │
     │ public class AnimationFrame                                                                                   │
     │ {                                                                                                             │
     │     public int FrameIndex { get; set; }                                                                       │
     │     public double Progress { get; set; }           // 0-1之间的进度                                           │
     │     public Point3D Position { get; set; }          // 该帧的位置                                              │
     │     public List<CollisionInfo> Collisions { get; set; } // 该帧的碰撞信息                                     │
     │     public DateTime Timestamp { get; set; }        // 帧时间戳（用于性能分析）                                │
     │ }                                                                                                             │
     │                                                                                                               │
     │ public class CollisionInfo                                                                                    │
     │ {                                                                                                             │
     │     public ModelItem CollidingObject { get; set; }                                                            │
     │     public Point3D CollidingPosition { get; set; }                                                            │
     │     public double Distance { get; set; }                                                                      │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 在PathAnimationManager中添加                                                                               │
     │ private List<AnimationFrame> _animationFrames;     // 所有动画帧                                              │
     │ private int _currentFrameIndex = 0;                // 当前帧索引                                              │
     │ private int _totalFrames = 0;                      // 总帧数                                                  │
     │ private double _frameStepSize = 0.01;              // 帧步进大小(1%)                                          │
     │ private bool _isSteppingMode = true;               // 是否步进模式                                            │
     │                                                                                                               │
     │ 2. 预计算所有帧（SetupAnimation）                                                                             │
     │                                                                                                               │
     │ public void SetupAnimation(ModelItem animatedObject, List<Point3D> pathPoints, double durationSeconds = 10.0) │
     │ {                                                                                                             │
     │     // ... 现有验证代码 ...                                                                                   │
     │                                                                                                               │
     │     // 计算总帧数                                                                                             │
     │     _totalFrames = (int)(1.0 / _frameStepSize); // 如0.01步进=100帧                                           │
     │     _animationFrames = new List<AnimationFrame>();                                                            │
     │                                                                                                               │
     │     LogManager.Info($"=== 开始预计算动画帧 ===");                                                             │
     │     LogManager.Info($"总帧数: {_totalFrames}, 步进大小: {_frameStepSize:F3}");                                │
     │                                                                                                               │
     │     PrecomputeAllFrames();                                                                                    │
     │                                                                                                               │
     │     LogManager.Info($"=== 预计算完成 ===");                                                                   │
     │     LogManager.Info($"总帧数: {_animationFrames.Count}");                                                     │
     │     LogManager.Info($"包含碰撞的帧: {_animationFrames.Count(f => f.Collisions.Count > 0)}");                  │
     │                                                                                                               │
     │     // 移动到起点                                                                                             │
     │     MoveToFrame(0);                                                                                           │
     │ }                                                                                                             │
     │                                                                                                               │
     │ private void PrecomputeAllFrames()                                                                            │
     │ {                                                                                                             │
     │     var modelItems = new ModelItemCollection { _animatedObject };                                             │
     │     var originalPosition = _currentPosition;                                                                  │
     │                                                                                                               │
     │     // 初始化碰撞检测                                                                                         │
     │     ClashDetectiveIntegration.Instance.Initialize();                                                          │
     │                                                                                                               │
     │     for (int i = 0; i <= _totalFrames; i++)                                                                   │
     │     {                                                                                                         │
     │         double progress = (double)i / _totalFrames;                                                           │
     │         var framePosition = InterpolatePosition(progress);                                                    │
     │                                                                                                               │
     │         // 临时移动到该帧位置                                                                                 │
     │         MoveObjectToPosition(framePosition);                                                                  │
     │                                                                                                               │
     │         // 执行碰撞检测                                                                                       │
     │         var collisions = ClashDetectiveIntegration.Instance.DetectCollisions(                                 │
     │             _animatedObject, null, _detectionTolerance:F4);                                                            │
     │                                                                                                               │
     │         // 创建帧数据                                                                                         │
     │         var frame = new AnimationFrame                                                                        │
     │         {                                                                                                     │
     │             FrameIndex = i,                                                                                   │
     │             Progress = progress,                                                                              │
     │             Position = framePosition,                                                                         │
     │             Collisions = new List<CollisionInfo>(),                                                           │
     │             Timestamp = DateTime.Now                                                                          │
     │         };                                                                                                    │
     │                                                                                                               │
     │         // 记录碰撞信息                                                                                       │
     │         foreach (var collision in collisions)                                                                 │
     │         {                                                                                                     │
     │             frame.Collisions.Add(new CollisionInfo                                                            │
     │             {                                                                                                 │
     │                 CollidingObject = collision.Item2,                                                            │
     │                 CollidingPosition = GetObjectPosition(collision.Item2),                                       │
     │                 Distance = collision.Distance                                                                 │
     │             });                                                                                               │
     │         }                                                                                                     │
     │                                                                                                               │
     │         _animationFrames.Add(frame);                                                                          │
     │                                                                                                               │
     │         // 进度报告                                                                                           │
     │         if (i % 10 == 0)                                                                                      │
     │         {                                                                                                     │
     │             LogManager.Info($"预计算进度: {i}/{_totalFrames} ({progress*100:F1}%)");                          │
     │         }                                                                                                     │
     │     }                                                                                                         │
     │                                                                                                               │
     │     // 恢复原始位置                                                                                           │
     │     MoveObjectToPosition(originalPosition);                                                                   │
     │ }                                                                                                             │
     │                                                                                                               │
     │ 3. 步进式播放控制                                                                                             │
     │                                                                                                               │
     │ // 播放模式枚举                                                                                               │
     │ public enum PlaybackMode                                                                                      │
     │ {                                                                                                             │
     │     Continuous,     // 连续播放                                                                               │
     │     StepByStep,     // 逐帧步进                                                                               │
     │     Manual          // 手动控制                                                                               │
     │ }                                                                                                             │
     │                                                                                                               │
     │ private PlaybackMode _playbackMode = PlaybackMode.StepByStep;                                                 │
     │                                                                                                               │
     │ // 修改OnApplicationIdle - 支持步进模式                                                                       │
     │ private void OnApplicationIdle(object sender, EventArgs e)                                                    │
     │ {                                                                                                             │
     │     if (_currentState != AnimationState.Playing)                                                              │
     │         return;                                                                                               │
     │                                                                                                               │
     │     // 帧率控制                                                                                               │
     │     var now = DateTime.Now;                                                                                   │
     │     var elapsed = (now - _lastFrameTime).TotalMilliseconds;                                                   │
     │                                                                                                               │
     │     if (elapsed < _frameInterval)                                                                             │
     │         return;                                                                                               │
     │                                                                                                               │
     │     // 根据播放模式执行                                                                                       │
     │     switch (_playbackMode)                                                                                    │
     │     {                                                                                                         │
     │         case PlaybackMode.Continuous:                                                                         │
     │             // 自动步进到下一帧                                                                               │
     │             if (_currentFrameIndex < _totalFrames)                                                            │
     │             {                                                                                                 │
     │                 MoveToFrame(_currentFrameIndex + 1);                                                          │
     │                 _lastFrameTime = now;                                                                         │
     │             }                                                                                                 │
     │             else                                                                                              │
     │             {                                                                                                 │
     │                 FinishAnimation();                                                                            │
     │             }                                                                                                 │
     │             break;                                                                                            │
     │                                                                                                               │
     │         case PlaybackMode.StepByStep:                                                                         │
     │             // 等待用户触发下一帧                                                                             │
     │             // 不自动前进                                                                                     │
     │             break;                                                                                            │
     │                                                                                                               │
     │         case PlaybackMode.Manual:                                                                             │
     │             // 完全手动控制                                                                                   │
     │             break;                                                                                            │
     │     }                                                                                                         │
     │ }                                                                                                             │
     │                                                                                                               │
     │ 4. 帧导航方法                                                                                                 │
     │                                                                                                               │
     │ // 移动到指定帧                                                                                               │
     │ public void MoveToFrame(int frameIndex)                                                                       │
     │ {                                                                                                             │
     │     if (frameIndex < 0 || frameIndex >= _animationFrames.Count)                                               │
     │     {                                                                                                         │
     │         LogManager.Warning($"帧索引 {frameIndex} 超出范围 [0, {_animationFrames.Count-1}]");                  │
     │         return;                                                                                               │
     │     }                                                                                                         │
     │                                                                                                               │
     │     var frame = _animationFrames[frameIndex];                                                                 │
     │     _currentFrameIndex = frameIndex;                                                                          │
     │                                                                                                               │
     │     // 更新位置                                                                                               │
     │     UpdateObjectPosition(frame.Position);                                                                     │
     │     _currentPosition = frame.Position;                                                                        │
     │                                                                                                               │
     │     // 更新碰撞高亮                                                                                           │
     │     HighlightFrameCollisions(frame);                                                                          │
     │                                                                                                               │
     │     // 触发进度事件                                                                                           │
     │     ProgressChanged?.Invoke(this, frame.Progress * 100);                                                      │
     │                                                                                                               │
     │     // 更新TimeLiner                                                                                          │
     │     if (_timeLinerManager != null && !string.IsNullOrEmpty(_currentTaskId))                                   │
     │     {                                                                                                         │
     │         _timeLinerManager.UpdateTaskProgress(_currentTaskId, frame.Progress, _currentState);                  │
     │     }                                                                                                         │
     │                                                                                                               │
     │     LogManager.Debug($"移动到帧 {frameIndex}/{_totalFrames} (进度: {frame.Progress*100:F1}%)");               │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 前进一帧                                                                                                   │
     │ public void StepForward()                                                                                     │
     │ {                                                                                                             │
     │     if (_currentFrameIndex < _totalFrames - 1)                                                                │
     │     {                                                                                                         │
     │         MoveToFrame(_currentFrameIndex + 1);                                                                  │
     │     }                                                                                                         │
     │     else                                                                                                      │
     │     {                                                                                                         │
     │         LogManager.Info("已到达最后一帧");                                                                    │
     │     }                                                                                                         │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 后退一帧                                                                                                   │
     │ public void StepBackward()                                                                                    │
     │ {                                                                                                             │
     │     if (_currentFrameIndex > 0)                                                                               │
     │     {                                                                                                         │
     │         MoveToFrame(_currentFrameIndex - 1);                                                                  │
     │     }                                                                                                         │
     │     else                                                                                                      │
     │     {                                                                                                         │
     │         LogManager.Info("已到达第一帧");                                                                      │
     │     }                                                                                                         │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 跳转到指定进度                                                                                             │
     │ public void JumpToProgress(double progress)                                                                   │
     │ {                                                                                                             │
     │     int targetFrame = (int)(progress * _totalFrames);                                                         │
     │     MoveToFrame(targetFrame);                                                                                 │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 快进/快退                                                                                                  │
     │ public void FastForward(int frames = 10)                                                                      │
     │ {                                                                                                             │
     │     int targetFrame = Math.Min(_currentFrameIndex + frames, _totalFrames - 1);                                │
     │     MoveToFrame(targetFrame);                                                                                 │
     │ }                                                                                                             │
     │                                                                                                               │
     │ public void FastBackward(int frames = 10)                                                                     │
     │ {                                                                                                             │
     │     int targetFrame = Math.Max(_currentFrameIndex - frames, 0);                                               │
     │     MoveToFrame(targetFrame);                                                                                 │
     │ }                                                                                                             │
     │                                                                                                               │
     │ 5. 碰撞高亮管理                                                                                               │
     │                                                                                                               │
     │ private HashSet<ModelItem> _currentHighlightedItems = new HashSet<ModelItem>();                               │
     │                                                                                                               │
     │ private void HighlightFrameCollisions(AnimationFrame frame)                                                   │
     │ {                                                                                                             │
     │     var newHighlights = new HashSet<ModelItem>(frame.Collisions.Select(c => c.CollidingObject));              │
     │                                                                                                               │
     │     // 只在高亮集合变化时更新                                                                                 │
     │     if (!newHighlights.SetEquals(_currentHighlightedItems))                                                   │
     │     {                                                                                                         │
     │         // 清除旧高亮                                                                                         │
     │         if (_currentHighlightedItems.Count > 0)                                                               │
     │         {                                                                                                     │
     │             ClashDetectiveIntegration.Instance.ClearHighlight();                                              │
     │         }                                                                                                     │
     │                                                                                                               │
     │         // 应用新高亮                                                                                         │
     │         if (newHighlights.Count > 0)                                                                          │
     │         {                                                                                                     │
     │             var collisionResults = frame.Collisions.Select(c => new CollisionResult                           │
     │             {                                                                                                 │
     │                 Item1 = _animatedObject,                                                                      │
     │                 Item2 = c.CollidingObject,                                                                    │
     │                 Distance = c.Distance                                                                         │
     │             }).ToList();                                                                                      │
     │                                                                                                               │
     │             ClashDetectiveIntegration.Instance.HighlightCollisions(collisionResults);                         │
     │         }                                                                                                     │
     │                                                                                                               │
     │         _currentHighlightedItems = newHighlights;                                                             │
     │                                                                                                               │
     │         if (frame.Collisions.Count > 0)                                                                       │
     │         {                                                                                                     │
     │             LogManager.Info($"帧 {frame.FrameIndex}: 高亮 {frame.Collisions.Count} 个碰撞");                  │
     │         }                                                                                                     │
     │     }                                                                                                         │
     │ }                                                                                                             │
     │                                                                                                               │
     │ 6. 播放控制API                                                                                                │
     │                                                                                                               │
     │ // 开始连续播放                                                                                               │
     │ public void Play()                                                                                            │
     │ {                                                                                                             │
     │     _playbackMode = PlaybackMode.Continuous;                                                                  │
     │     SetState(AnimationState.Playing);                                                                         │
     │     NavisApplication.Idle += OnApplicationIdle;                                                               │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 暂停（保持当前帧）                                                                                         │
     │ public void Pause()                                                                                           │
     │ {                                                                                                             │
     │     _playbackMode = PlaybackMode.StepByStep;                                                                  │
     │     SetState(AnimationState.Paused);                                                                          │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 设置播放速度（通过调整帧间隔）                                                                             │
     │ public void SetPlaybackSpeed(double speed)                                                                    │
     │ {                                                                                                             │
     │     _frameInterval = (1000.0 / _animationFrameRate) / speed;                                                  │
     │     LogManager.Info($"播放速度设置为 {speed}x");                                                              │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 获取当前帧信息                                                                                             │
     │ public AnimationFrame GetCurrentFrame()                                                                       │
     │ {                                                                                                             │
     │     if (_currentFrameIndex >= 0 && _currentFrameIndex < _animationFrames.Count)                               │
     │         return _animationFrames[_currentFrameIndex];                                                          │
     │     return null;                                                                                              │
     │ }                                                                                                             │
     │                                                                                                               │
     │ // 获取帧统计信息                                                                                             │
     │ public string GetFrameStatistics()                                                                            │
     │ {                                                                                                             │
     │     var current = GetCurrentFrame();                                                                          │
     │     if (current != null)                                                                                      │
     │     {                                                                                                         │
     │         return $"帧 {_currentFrameIndex}/{_totalFrames} | " +                                                 │
     │                $"进度 {current.Progress*100:F1}% | " +                                                        │
     │                $"碰撞 {current.Collisions.Count}";                                                            │
     │     }                                                                                                         │
     │     return "无帧数据";                                                                                        │
     │ }                                                                                                             │
     │                                                                                                               │
     │ 7. UI集成建议                                                                                                 │
     │                                                                                                               │
     │ // 动画控制面板应添加的控件                                                                                   │
     │ public class AnimationControlPanel                                                                            │
     │ {                                                                                                             │
     │     // 播放控制                                                                                               │
     │     Button PlayButton;          // 连续播放                                                                   │
     │     Button PauseButton;         // 暂停                                                                       │
     │     Button StepForwardButton;   // 前进一帧                                                                   │
     │     Button StepBackButton;      // 后退一帧                                                                   │
     │     Button FastForwardButton;   // 快进10帧                                                                   │
     │     Button FastRewindButton;    // 快退10帧                                                                   │
     │                                                                                                               │
     │     // 进度控制                                                                                               │
     │     Slider ProgressSlider;      // 进度条（可拖动跳转）                                                       │
     │     Label FrameLabel;          // 当前帧信息                                                                  │
     │     Label CollisionLabel;      // 碰撞信息                                                                    │
     │                                                                                                               │
     │     // 速度控制                                                                                               │
     │     Slider SpeedSlider;        // 播放速度(0.1x - 5x)                                                         │
     │     ComboBox PlayModeCombo;    // 播放模式选择                                                                │
     │ }                                                                                                             │
     │                                                                                                               │
     │ 优势                                                                                                          │
     │                                                                                                               │
     │ 1. 完全可控：每一帧都可以精确控制                                                                             │
     │ 2. 双向导航：支持前进和后退                                                                                   │
     │ 3. 性能优秀：预计算避免实时检测                                                                               │
     │ 4. 调试友好：可以逐帧分析碰撞                                                                                 │
     │ 5. 灵活播放：支持多种播放模式                                                                                 │
     │                                                                                                               │
     │ 实施步骤                                                                                                      │
     │                                                                                                               │
     │ 1. 添加AnimationFrame数据结构                                                                                 │
     │ 2. 实现预计算所有帧逻辑                                                                                       │
     │ 3. 改造播放控制为步进式                                                                                       │
     │ 4. 实现帧导航方法                                                                                             │
     │ 5. 更新UI添加步进控制                                                                                         │
     │ 6. 测试各种播放模式                  



     🎮 媒体控制功能：

  - 快退10帧 (Shift+←) - 快速后退功能
  - 上一帧 (←) - 精确单帧后退
  - 反向播放 (R键) - 连续反向播放动画
  - 暂停 (Space) - 居中暂停控制
  - 正向播放 - 标准前进播放
  - 下一帧 (→) - 精确单帧前进
  - 快进10帧 (Shift+→) - 快速前进功能
  - 停止 (Esc) - 停止并重置动画


  4. 优化性能的关键点
使用事务批量更新：通过 Application.ActiveDocument.BeginTransaction 将多个构件的变换操作包裹起来，最后一次性提交 (transaction.Commit())，这比单独更新每个构件高效得多。

优先使用DispatcherTimer而非Idle事件：DispatcherTimer 在UI线程上按固定间隔触发，比依赖不确定的Idle事件更能保证更新的及时性。优先级设置为 DispatcherPriority.Render。

控制帧率：Interval 设置为约16ms（约60FPS）。如果场景复杂导致卡顿，可以适当增大此值（如33ms对应~30FPS）。WPF中也可以通过 Timeline.DesiredFrameRate 附加属性来调整动画的帧率。

减少不必要的重绘：只在所有变换更新后调用一次 Redraw。

硬件加速：确保在Navisworks的选项 (Options) -> 显示 (Display) 中启用硬件加速 (Hardware Acceleration) 和 WPF硬件加速 (WPF Hardware Acceleration)（如果可用）。

优化图形设置：在Navisworks的显示设置中，适当降低细节层次 (Level of Detail) 或禁用保证帧频 (Guarantee Frame Rate)（根据实际情况测试）可能有助于提高复杂模型的交互性能。

5. 调试提示
如果动画仍然卡顿，首先尝试减少同时动画的构件数量。

在Navisworks的选项 -> 显示中，可以尝试调整图形模式 (Graphics Mode) 等设置来优化性能。

使用性能分析工具（如Visual Studio的诊断工具）检查代码中是否存在瓶颈。


Navisworks设置：
1、【界面】-【选取】中，可以设置精度，从几何体、最低层次的对象、最高层级的唯一对象、最高层级的对象、图层、文件，默认是最低层次的对象。