# Navisworks 2026 API 迁移实施计划

## 项目概述

本文档详细规划了NavisworksTransport项目从2017版本迁移到2026版本的具体实施步骤，包括时间安排、技术路径和风险控制措施。

### 核心迁移目标
1. **动画系统重构**：从手动Transform变换升级到Navisworks 2026原生动画组件
2. **物流属性管理优化**：从复杂COM API迁移到简化的属性集功能
3. **模型分层拆分稳定性**：解决崩溃问题，提升大型模型处理能力
4. **新功能实现**：导航地图输出、增强碰撞检测等

### 预期收益
- **动画流畅度提升200%**：从不稳定15-30fps提升到稳定60fps
- **开发效率提升400%**：动画开发时间从2-3天缩短到2-4小时
- **CPU使用率降低60%**：特别是动画播放时的资源占用
- **代码维护成本降低70%**：简化复杂的手动时间轴管理

## 1. 迁移准备阶段（第1周）

### 1.1 环境搭建
- [ ] 安装Navisworks 2026开发环境
- [ ] 升级Visual Studio到2022版本
- [ ] 配置.NET Framework 4.8开发环境
- [ ] 获取Navisworks 2026 SDK文档

### 1.2 项目结构调整
```
NavisworksTransport/
├── src/
│   ├── Core/                 # 核心API封装
│   ├── Legacy/              # 2017版本兼容层
│   ├── Migration/           # 迁移工具类
│   └── UI/                  # 用户界面
├── tests/
│   ├── ApiTests/            # API功能测试
│   └── IntegrationTests/    # 集成测试
└── docs/
    └── migration/           # 迁移文档
```

### 1.3 基础设施准备
- [ ] 创建API兼容性测试套件
- [ ] 建立性能基准测试
- [ ] 设置持续集成环境

## 2. 阶段1：核心API迁移（第2-4周）

### 2.1 动画系统重构（🔥 新增重要优化）

#### 2.1.1 动画系统现状分析
当前动画系统存在严重问题：
- 手动Transform变换，性能差
- Thread.Sleep时间控制，不流畅
- 缺乏标准动画控制功能
- 维护成本高，扩展性差

#### 2.1.2 新的动画管理器设计
```csharp
// 基于Navisworks 2026原生动画组件的新实现
public class LogisticsAnimationManager2026
{
    private readonly Document _document;
    private readonly Dictionary<string, AnimationSet> _animationSets;
    private readonly Dictionary<string, AnimationController> _controllers;
    
    public LogisticsAnimationManager2026(Document document)
    {
        _document = document;
        _animationSets = new Dictionary<string, AnimationSet>();
        _controllers = new Dictionary<string, AnimationController>();
    }
    
    // 创建基于关键帧的路径动画
    public AnimationSet CreatePathAnimation(
        string name,
        ModelItem movingObject,
        List<PathPoint> pathPoints,
        TimeSpan duration,
        AnimationOptions options = null)
    {
        var animationSet = new AnimationSet(_document, name);
        
        // 创建变换轨道
        var transformTrack = animationSet.CreateTransformTrack(movingObject, "Transform");
        
        // 添加关键帧
        for (int i = 0; i < pathPoints.Count; i++)
        {
            var progress = (double)i / (pathPoints.Count - 1);
            var keyTime = TimeSpan.FromMilliseconds(duration.TotalMilliseconds * progress);
            
            var keyframe = transformTrack.CreateKeyframe(keyTime);
            keyframe.Transform = CreateTransformFromPoint(pathPoints[i]);
            
            // 设置插值类型（样条、线性、贝塞尔等）
            keyframe.InterpolationType = options?.InterpolationType ?? InterpolationType.Spline;
        }
        
        // 创建专业动画控制器
        var controller = new AnimationController(animationSet);
        
        _animationSets[name] = animationSet;
        _controllers[name] = controller;
        
        return animationSet;
    }
}

// 专业动画控制器
public class AnimationController
{
    private readonly AnimationSet _animationSet;
    private readonly Timer _updateTimer;
    private TimeSpan _currentTime;
    private bool _isPlaying;
    private double _playbackSpeed = 1.0;
    
    public event EventHandler<AnimationProgressEventArgs> ProgressChanged;
    public event EventHandler AnimationCompleted;
    
    // 标准播放控制
    public void Play()
    {
        _isPlaying = true;
        _updateTimer.Change(0, 16); // 60 FPS
    }
    
    public void Pause() => _isPlaying = false;
    public void Stop() => ResetToInitialState();
    public void SeekTo(TimeSpan time) => _animationSet.EvaluateAt(time);
    public void SetPlaybackSpeed(double speed) => _playbackSpeed = speed;
    public void PlayReverse() => _playbackSpeed = -Math.Abs(_playbackSpeed);
}
```

#### 2.1.3 相机跟随动画实现
```csharp
public class CameraFollowAnimation
{
    public SavedViewpointAnimation CreateFollowAnimation(
        List<PathPoint> pathPoints,
        CameraFollowSettings settings)
    {
        var viewpointAnimation = new SavedViewpointAnimation();
        viewpointAnimation.Name = "物流路径跟随";
        viewpointAnimation.Duration = settings.Duration;
        viewpointAnimation.SmoothTransition = true;
        
        foreach (var point in pathPoints)
        {
            var viewpoint = CreateOptimalViewpoint(point, settings);
            viewpointAnimation.SavedViewpoints.Add(viewpoint);
        }
        
        return viewpointAnimation;
    }
}
```

#### 2.1.4 迁移时间表
- **第2周**: 动画系统架构设计和基础框架
- **第3周**: 实现AnimationSet和控制器
- **第4周**: 相机跟随和高级功能，性能测试

#### 2.1.5 验收标准
- [ ] 动画流畅度提升 > 200%（稳定60fps）
- [ ] CPU使用率降低 > 60%
- [ ] 支持标准动画控制（播放/暂停/停止/调速）
- [ ] 支持相机跟随动画
- [ ] 开发效率提升 > 400%

### 2.2 物流属性管理系统重构

#### 2.1.1 新的属性管理器设计
```csharp
// 新的属性管理器架构
public class LogisticsPropertyManager2026
{
    private readonly Document _document;
    private readonly ILogger _logger;
    
    public LogisticsPropertyManager2026(Document document, ILogger logger)
    {
        _document = document;
        _logger = logger;
    }
    
    // 使用2026属性集功能
    public async Task<bool> SetLogisticsCategoryAsync(
        ModelItemCollection items, 
        LogisticsCategory category)
    {
        using (var transaction = new Transaction(_document))
        {
            try
            {
                foreach (ModelItem item in items)
                {
                    await SetItemCategoryAsync(item, category);
                }
                
                transaction.Commit();
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError($"设置物流类别失败: {ex.Message}");
                return false;
            }
        }
    }
    
    private async Task SetItemCategoryAsync(ModelItem item, LogisticsCategory category)
    {
        // 利用2026属性集功能
        var propertyCategory = item.PropertyCategories
            .FindPropertyByDisplayName("物流属性", "类型");
            
        if (propertyCategory == null)
        {
            // 创建新的属性集
            await CreateLogisticsPropertySetAsync(item);
        }
        
        // 设置属性值
        propertyCategory.Value = VariantData.FromDisplayString(category.ToString());
    }
}
```

#### 2.2.2 迁移时间表
- **第2周**: 设计新的属性管理架构（与动画系统并行）
- **第3周**: 实现核心属性操作功能
- **第4周**: 测试和优化，性能对比

#### 2.2.3 验收标准
- [ ] 属性设置成功率 > 99%
- [ ] 批量操作性能提升 > 3倍
- [ ] 消除COM API缓存同步问题
- [ ] 支持最多4个属性面板显示

### 2.3 模型分层拆分功能重构

#### 2.3.1 新的模型切分器设计
```csharp
public class ModelSplitter2026
{
    private readonly Document _document;
    private readonly ILogger _logger;
    
    public async Task<bool> ExportModelSubsetAsync(
        ModelItemCollection itemsToExport, 
        string outputPath,
        ExportOptions options = null)
    {
        using (var transaction = new Transaction(_document))
        {
            try
            {
                // 计算需要隐藏的项目
                var itemsToHide = CalculateItemsToHide(itemsToExport);
                
                // 批量隐藏操作（2026优化）
                _document.Models.SetHidden(itemsToHide, true);
                
                // 2026新特性：自动排除隐藏项
                await ExportWithHiddenExclusionAsync(outputPath, options);
                
                // 自动恢复可见性
                _document.Models.UnhideAll();
                
                transaction.Commit();
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError($"模型导出失败: {ex.Message}");
                return false;
            }
        }
    }
    
    private async Task ExportWithHiddenExclusionAsync(string outputPath, ExportOptions options)
    {
        // 利用2026的自动排除隐藏项功能
        var exportOptions = options ?? new ExportOptions
        {
            ExcludeHiddenItems = true,
            FileVersion = DocumentFileVersion.Navisworks2026
        };
        
        await Task.Run(() => _document.SaveFile(outputPath, exportOptions.FileVersion));
    }
}
```

#### 2.3.2 崩溃问题解决方案
```csharp
public class CrashPreventionManager
{
    // 内存管理优化
    public void OptimizeMemoryUsage()
    {
        // 强制垃圾回收
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
    }
    
    // 递归深度控制
    public ModelItemCollection GetItemsSafely(ModelItem root, int maxDepth = 10)
    {
        var result = new ModelItemCollection();
        GetItemsRecursive(root, result, 0, maxDepth);
        return result;
    }
    
    private void GetItemsRecursive(ModelItem item, ModelItemCollection result, 
        int currentDepth, int maxDepth)
    {
        if (currentDepth >= maxDepth) return;
        
        result.Add(item);
        foreach (ModelItem child in item.Children)
        {
            GetItemsRecursive(child, result, currentDepth + 1, maxDepth);
        }
    }
}
```

## 3. 阶段2：功能增强（第5-7周）

### 3.1 高级动画功能实现

#### 3.1.1 TimeLiner集成的4D动画
```csharp
public class TimeLinedLogisticsAnimation
{
    private readonly Document _document;
    private readonly TimeLiner _timeLiner;
    
    public void CreateLogisticsSchedule(LogisticsSchedule schedule)
    {
        // 创建时间线任务
        foreach (var task in schedule.Tasks)
        {
            var timeLineTask = _timeLiner.Tasks.Add(task.Name);
            timeLineTask.StartDate = task.StartTime;
            timeLineTask.EndDate = task.EndTime;
            timeLineTask.Selection = task.ModelItems;
            
            // 关联动画
            if (task.HasAnimation)
            {
                var animation = CreatePathAnimation(task.Animation);
                timeLineTask.AttachedAnimations.Add(animation);
                
                // 设置动画触发
                timeLineTask.OnStart += () => animation.Play();
                timeLineTask.OnEnd += () => animation.Stop();
            }
        }
    }
}
```

#### 3.1.2 交互式动画控制
```csharp
public class InteractiveAnimationSystem
{
    private readonly Scripter _scripter;
    private readonly Dictionary<string, AnimationTrigger> _triggers;
    
    private void SetupEventHandlers()
    {
        _scripter.OnKeyPress += HandleKeyPress;
        _scripter.OnMouseClick += HandleMouseClick;
    }
    
    private void HandleKeyPress(KeyPressEventArgs e)
    {
        switch (e.Key)
        {
            case Keys.Space: ToggleAnimation("主要路径动画"); break;
            case Keys.R: RestartAnimation("主要路径动画"); break;
            case Keys.S: StopAllAnimations(); break;
        }
    }
}
```

### 3.2 碰撞检测系统升级

#### 3.2.1 增强的碰撞检测器
```csharp
public class EnhancedClashDetector2026
{
    public ClashTestResult RunLogisticsClashTest(
        ModelItemCollection pathItems,
        ModelItemCollection obstacleItems,
        ClashTestOptions options)
    {
        var clashTest = new ClashTest(_document);
        
        // 2026新功能：设置优先级
        clashTest.Priority = options.Priority;
        clashTest.Description = "物流路径碰撞检测";
        
        // 配置选择集
        clashTest.SelectionA = CreateClashSelection(pathItems);
        clashTest.SelectionB = CreateClashSelection(obstacleItems);
        
        // 2026增强：按属性分组
        clashTest.GroupBy = ClashGroupBy.Property;
        clashTest.GroupByProperty = "物流类型";
        
        clashTest.Run();
        
        return ProcessClashResults(clashTest.Results);
    }
}
```

### 3.3 导航地图输出功能

#### 3.3.1 图片导出实现
```csharp
public class NavigationMapExporter
{
    public async Task<bool> ExportImageAsync(string outputPath, ImageExportOptions options)
    {
        try
        {
            var doc = Application.ActiveDocument;
            var oState = ComApiBridge.State;
            
            // 获取图像导出插件选项
            var exportOptions = oState.GetIOPluginOptions("lcodpimage");
            
            // 配置导出参数
            ConfigureImageExportOptions(exportOptions, options);
            
            // 执行导出
            await Task.Run(() => oState.DriveIOPlugin("lcodpimage", outputPath, exportOptions));
            
            return File.Exists(outputPath);
        }
        catch (Exception ex)
        {
            _logger.LogError($"图片导出失败: {ex.Message}");
            return false;
        }
    }
    
    private void ConfigureImageExportOptions(ComApi.InwOaPropertyVec options, ImageExportOptions settings)
    {
        foreach (ComApi.InwOaProperty opt in options.Properties())
        {
            switch (opt.name)
            {
                case "export.image.format":
                    opt.value = settings.Format == ImageFormat.PNG ? "lcodpexpng" : "lcodpexjpeg";
                    break;
                case "export.image.width":
                    opt.value = settings.Width;
                    break;
                case "export.image.height":
                    opt.value = settings.Height;
                    break;
            }
        }
    }
}
```

#### 3.3.2 视频导出实现（结合新动画系统）
```csharp
public class VideoExporter
{
    public async Task<bool> ExportAnimationVideoAsync(
        string outputPath, 
        List<AnimationFrame> frames,
        VideoExportOptions options)
    {
        string tempDir = Path.Combine(Path.GetTempPath(), "NavisFrames", Guid.NewGuid().ToString());
        
        try
        {
            Directory.CreateDirectory(tempDir);
            
            // 逐帧捕获
            var framePaths = await CaptureFramesAsync(frames, tempDir);
            
            // 使用FFmpeg合成视频
            return await ComposeVideoAsync(framePaths, outputPath, options);
        }
        finally
        {
            // 清理临时文件
            if (Directory.Exists(tempDir))
            {
                Directory.Delete(tempDir, true);
            }
        }
    }
    
    private async Task<List<string>> CaptureFramesAsync(AnimationSet animationSet, string tempDir, int frameCount)
    {
        var framePaths = new List<string>();
        var duration = animationSet.Duration;
        
        for (int i = 0; i < frameCount; i++)
        {
            // 使用新动画系统的精确时间控制
            var timeRatio = (double)i / (frameCount - 1);
            var currentTime = TimeSpan.FromMilliseconds(duration.TotalMilliseconds * timeRatio);
            
            // 让动画系统更新到指定时间点
            animationSet.EvaluateAt(currentTime);
            
            // 捕获当前帧
            string framePath = Path.Combine(tempDir, $"frame_{i:D5}.png");
            await ExportCurrentFrameAsync(framePath);
            
            framePaths.Add(framePath);
            
            // 进度报告
            OnProgressChanged?.Invoke((i + 1.0) / frameCount);
        }
        
        return framePaths;
    }
    
    private async Task<bool> ComposeVideoAsync(List<string> framePaths, string outputPath, VideoExportOptions options)
    {
        var ffmpegArgs = BuildFFmpegArguments(framePaths, outputPath, options);
        
        using (var process = new Process())
        {
            process.StartInfo = new ProcessStartInfo
            {
                FileName = "ffmpeg",
                Arguments = ffmpegArgs,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                CreateNoWindow = true
            };
            
            process.Start();
            await process.WaitForExitAsync();
            
            return process.ExitCode == 0;
        }
    }
}
```

## 4. 阶段3：UI现代化和新功能（第8-10周）

### 4.1 WPF界面迁移

#### 4.1.1 主界面重构
```xml
<!-- 新的WPF主界面 -->
<UserControl x:Class="NavisworksTransport.UI.MainPanel2026">
    <Grid>
        <TabControl>
            <TabItem Header="物流属性">
                <local:LogisticsPropertyPanel />
            </TabItem>
            <TabItem Header="模型切分">
                <local:ModelSplitterPanel />
            </TabItem>
            <TabItem Header="路径规划">
                <local:PathPlanningPanel />
            </TabItem>
            <TabItem Header="导航地图">
                <local:NavigationMapPanel />
            </TabItem>
        </TabControl>
    </Grid>
</UserControl>
```

#### 4.1.2 可停靠面板实现
```csharp
[Plugin("NavisworksTransport.DockablePane2026", "YourDeveloperID")]
public class LogisticsDockablePane : DockPanePlugin
{
    public override Control CreateControlPane()
    {
        // 使用ElementHost托管WPF控件
        var elementHost = new ElementHost
        {
            Dock = DockStyle.Fill,
            Child = new MainPanel2026()
        };
        
        return elementHost;
    }
    
    public override void DestroyControlPane(Control pane)
    {
        if (pane is ElementHost elementHost)
        {
            elementHost.Child = null;
            elementHost.Dispose();
        }
    }
}
```

### 4.2 DELMIA集成准备

#### 4.2.1 数据导出格式
```csharp
public class DelmiaDataExporter
{
    public async Task<bool> ExportLogisticsDataAsync(string outputPath, LogisticsData data)
    {
        var exportData = new
        {
            Metadata = new
            {
                ExportTime = DateTime.UtcNow,
                NavisworksVersion = "2026",
                ProjectName = data.ProjectName
            },
            Paths = data.Paths.Select(p => new
            {
                Id = p.Id,
                Name = p.Name,
                Points = p.Points.Select(pt => new { X = pt.X, Y = pt.Y, Z = pt.Z }),
                Properties = p.Properties
            }),
            Objects = data.Objects.Select(o => new
            {
                Id = o.Id,
                Name = o.Name,
                Category = o.Category,
                BoundingBox = o.BoundingBox,
                Transform = o.Transform,
                Properties = o.Properties
            })
        };
        
        var json = JsonSerializer.Serialize(exportData, new JsonSerializerOptions
        {
            WriteIndented = true,
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });
        
        await File.WriteAllTextAsync(outputPath, json);
        return true;
    }
}
```

## 5. 测试和验证（第11-12周）

### 5.1 功能测试
- [ ] **动画系统功能测试**（新增重点）
  - [ ] 基础动画播放控制测试
  - [ ] 相机跟随动画测试
  - [ ] TimeLiner集成测试
  - [ ] 交互式动画控制测试
- [ ] 物流属性管理功能测试
- [ ] 模型分层拆分功能测试
- [ ] 碰撞检测功能测试
- [ ] 导航地图输出功能测试
- [ ] UI界面交互测试

### 5.2 性能测试
- [ ] **动画系统性能测试**（新增重点）
  - [ ] 动画流畅度测试（目标：稳定60fps）
  - [ ] CPU使用率对比测试（目标：降低60%）
  - [ ] 内存使用稳定性测试
  - [ ] 长时间动画播放稳定性测试
- [ ] 大型模型加载性能测试
- [ ] 批量属性操作性能测试
- [ ] 内存使用情况测试
- [ ] 崩溃稳定性测试

### 5.3 兼容性测试
- [ ] 不同版本NWD文件兼容性
- [ ] 多种模型格式支持测试
- [ ] Windows不同版本兼容性测试

## 6. 部署和发布（第13周）

### 6.1 打包和分发
- [ ] 创建安装程序
- [ ] 准备用户文档
- [ ] 创建迁移指南

### 6.2 用户培训
- [ ] 准备培训材料
- [ ] 录制功能演示视频
- [ ] 编写用户手册

## 7. 风险控制措施

### 7.1 技术风险
| 风险 | 概率 | 影响 | 应对措施 |
|------|------|------|----------|
| API兼容性问题 | 中 | 高 | 建立兼容性测试套件，准备降级方案 |
| 性能回归 | 低 | 中 | 持续性能监控，基准测试对比 |
| **动画系统迁移复杂度** | **中** | **高** | **渐进式迁移，保留手动变换作为备用** |
| **动画流畅度不达预期** | **低** | **中** | **充分的动画场景测试，性能调优** |
| 新功能缺陷 | 中 | 中 | 充分测试，分阶段发布 |

### 7.2 项目风险
| 风险 | 概率 | 影响 | 应对措施 |
|------|------|------|----------|
| 时间延期 | 中 | 中 | 优先级管理，关键路径监控 |
| 资源不足 | 低 | 高 | 提前资源规划，外部支持 |
| 需求变更 | 中 | 中 | 变更控制流程，影响评估 |

## 8. 成功标准

### 8.1 技术指标
- [ ] 代码复杂度降低 > 30%
- [ ] 整体性能提升 > 20%
- [ ] **动画系统性能提升 > 200%**（新增关键指标）
- [ ] **动画开发效率提升 > 400%**（新增关键指标）
- [ ] 崩溃率降低 > 90%
- [ ] 新功能覆盖率 > 95%

### 8.2 业务指标
- [ ] 用户满意度 > 90%
- [ ] 功能完整性 > 98%
- [ ] 文档完整性 > 95%
- [ ] 培训效果 > 85%

## 9. 后续维护计划

### 9.1 短期维护（3个月）
- 监控系统稳定性
- 收集用户反馈
- 修复发现的问题

### 9.2 长期维护（1年）
- 功能增强和优化
- 新版本API适配
- 性能持续改进

这个实施计划确保了迁移过程的有序进行，同时最大化了2026版本API的优势，为项目的长期发展奠定了坚实基础。