修改了ClashDetective集成逻辑,运行结束汇总显示测试结果。
This commit is contained in:
parent
82753855b9
commit
65712b675e
@ -5,7 +5,9 @@
|
||||
"Bash(dotnet build:*)",
|
||||
"WebFetch(domain:github.com)",
|
||||
"WebFetch(domain:adndevblog.typepad.com)",
|
||||
"Bash(.compile.bat)"
|
||||
"Bash(.compile.bat)",
|
||||
"Bash(rg:*)",
|
||||
"Bash(findstr:*)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
|
||||
@ -3,13 +3,15 @@
|
||||
## [0.1.9] - 2025-07-18
|
||||
|
||||
### 新增 🎉
|
||||
- **TimeLiner 集成功能**:完整的 Navisworks TimeLiner 集成支持
|
||||
|
||||
- **TimeLiner 集成功能**:不完整的 Navisworks TimeLiner 集成支持
|
||||
- 新增 `TimeLinerIntegrationManager` 类,实现运输任务与 TimeLiner 的无缝集成
|
||||
- 动画播放时自动在 TimeLiner 中创建对应的运输任务
|
||||
- 支持任务状态实时同步(播放中、暂停、停止、已完成)
|
||||
- 任务显示名称包含车辆信息、时间戳和进度状态
|
||||
|
||||
### 技术突破 🔧
|
||||
|
||||
- **API 兼容性解决**:成功解决 Navisworks 2017 TimeLiner API 限制
|
||||
- 发现并使用正确的 `TaskAddCopy()` 方法替代只读的 `Tasks.Add()`
|
||||
- 实现多重 fallback 机制:直接添加 → 插入副本 → 层次结构管理
|
||||
@ -20,6 +22,7 @@
|
||||
- 两个系统独立运行,互不干扰,确保稳定性
|
||||
|
||||
### 集成组件 📦
|
||||
|
||||
- **PathAnimationManager 增强**:
|
||||
- 添加 TimeLiner 相关公共属性:`IsTimeLinerAvailable`、`CurrentState`、`CurrentTaskId`、`TimeLinerManager`
|
||||
- 动画播放时自动创建 TimeLiner 任务
|
||||
@ -32,12 +35,14 @@
|
||||
- 事件系统:`StatusChanged`、`TaskCreated` 事件通知
|
||||
|
||||
### 用户体验 ✨
|
||||
|
||||
- **无缝集成**:原有动画功能完全保持不变,TimeLiner 功能作为增强特性
|
||||
- **可视化管理**:用户可在 TimeLiner 面板中查看所有运输任务
|
||||
- **状态同步**:任务名称实时显示动画状态和进度百分比
|
||||
- **错误恢复**:TimeLiner 功能异常时自动降级到基础动画模式
|
||||
|
||||
### 技术细节 📋
|
||||
|
||||
- **API 方法**:
|
||||
- `_documentTimeliner.TaskAddCopy(task)` - 添加任务副本
|
||||
- `_documentTimeliner.TaskInsertCopy(index, task)` - 插入任务副本
|
||||
@ -52,6 +57,7 @@
|
||||
- 异常情况下的资源自动释放
|
||||
|
||||
### 验证结果 ✅
|
||||
|
||||
- ✅ TimeLiner 窗口成功显示运输任务:"运输任务:SHINYSTE13_运输_131040"
|
||||
- ✅ 任务创建使用 `TaskAddCopy` 方法成功,任务数量从 0 增加到 1
|
||||
- ✅ 车辆关联正确:关联了 SHINYSTE13 车辆模型
|
||||
@ -60,6 +66,7 @@
|
||||
- ✅ 编译成功,在 Navisworks 2017 中稳定运行
|
||||
|
||||
### 代码优化 🛠️
|
||||
|
||||
- **日志系统简化**:移除冗余的调试日志,保留关键信息
|
||||
- **错误处理优化**:统一异常处理逻辑,提高代码可读性
|
||||
- **性能改进**:减少不必要的 API 调用和状态检查
|
||||
@ -69,6 +76,7 @@
|
||||
### 进一步修复对象生命周期和选择清除问题
|
||||
|
||||
#### 深度修复
|
||||
|
||||
- **选择清除安全性**:创建了`SafelyClearSelection()`方法,完全安全地处理选择清除
|
||||
- 新增`IsApplicationDocumentValid()`方法检查Application和Document对象有效性
|
||||
- 替换所有直接的`CurrentSelection.Clear()`调用为安全方法调用
|
||||
@ -79,6 +87,7 @@
|
||||
- 防止定时器继续尝试访问已释放的对象
|
||||
|
||||
#### 技术增强
|
||||
|
||||
- **多层防护机制**:
|
||||
- `IsApplicationDocumentValid()`:检查核心对象有效性
|
||||
- `SafelyClearSelection()`:安全的选择清除操作
|
||||
@ -93,6 +102,7 @@
|
||||
- 集中化的错误处理和日志记录
|
||||
|
||||
#### 解决的问题
|
||||
|
||||
- ✅ "Object has been Disposed" 在清除选择时的错误
|
||||
- ✅ 定时器继续访问已释放对象的问题
|
||||
- ✅ 多重异常处理导致的日志混乱
|
||||
@ -103,6 +113,7 @@
|
||||
## [0.1.11] - 2025-06-19
|
||||
|
||||
### 修复
|
||||
|
||||
- 🔧 恢复进入路径编辑模式后控制面板自动关闭功能
|
||||
- 在v0.1.10添加全局异常处理时意外删除了此功能
|
||||
- 现在进入路径编辑模式成功后,控制面板会自动关闭
|
||||
@ -112,18 +123,21 @@
|
||||
- 自动关闭确保焦点回到Navisworks主界面
|
||||
|
||||
### 改进
|
||||
|
||||
- 📝 更新用户提示信息
|
||||
- 明确告知用户控制面板已关闭,避免困惑
|
||||
- 提醒用户完成路径编辑后需要重新打开插件面板退出编辑模式
|
||||
- 保持原有的操作流程指导
|
||||
|
||||
### 用户体验
|
||||
|
||||
- **操作流程**:选择通道 → 点击进入编辑 → 面板自动关闭 → 3D点击添加路径点 → 重新打开插件 → 退出编辑
|
||||
- **交互优化**:确保用户能够无障碍地在3D环境中进行路径规划操作
|
||||
|
||||
## [0.1.10] - 2025-06-19
|
||||
|
||||
### 新增
|
||||
|
||||
- 🛡️ 全局异常处理机制,彻底防止程序崩溃
|
||||
- 新增GlobalExceptionHandler工具类,捕获AppDomain和Thread级别的未处理异常
|
||||
- 实现SafeExecute方法,为所有关键操作提供安全包装
|
||||
@ -134,6 +148,7 @@
|
||||
- 尝试恢复程序到安全状态
|
||||
|
||||
### 改进
|
||||
|
||||
- 📝 用户友好的错误提示
|
||||
- 技术详情与用户信息分离显示
|
||||
- 不同级别的错误提示(错误对话框 vs 简单提示)
|
||||
@ -144,6 +159,7 @@
|
||||
- 记录是否为终止性异常
|
||||
|
||||
### 技术细节
|
||||
|
||||
- 修改MainPlugin.Execute方法,使用GlobalExceptionHandler.SafeExecute包装
|
||||
- 为ShowCategorySelectionDialog方法添加异常保护
|
||||
- 为所有按钮点击事件添加SafeExecute包装
|
||||
@ -155,6 +171,7 @@
|
||||
### 修复对象生命周期管理问题
|
||||
|
||||
#### 主要修复
|
||||
|
||||
- **Object has been Disposed 错误**:修复了点击监听和高亮功能中的对象释放错误
|
||||
- 添加了`IsModelItemValid()`方法检查ModelItem对象是否有效
|
||||
- 在高亮功能中过滤无效的ModelItem对象
|
||||
@ -165,6 +182,7 @@
|
||||
- 简化了选择清除的错误处理机制
|
||||
|
||||
#### 技术改进
|
||||
|
||||
- **对象有效性检查**:
|
||||
- 新增`IsModelItemValid()`私有方法
|
||||
- 通过访问基本属性检测对象是否已被释放
|
||||
@ -179,6 +197,7 @@
|
||||
- 添加有效对象计数和状态反馈
|
||||
|
||||
#### 解决的具体问题
|
||||
|
||||
- ✅ "Argument 'path' has been Disposed" 错误
|
||||
- ✅ "Object has been Disposed (null)" 重复错误
|
||||
- ✅ 点击监听过程中的对象释放异常
|
||||
@ -191,12 +210,14 @@
|
||||
### 增加分层可见性控制功能
|
||||
|
||||
#### 主要变更
|
||||
|
||||
- **修复可见性逻辑缺陷**:解决了隐藏非物流项目时,具有物流属性的项目也被错误隐藏的问题
|
||||
- **改进用户界面**:将两个独立按钮("隐藏非物流分类项目"和"显示所有项目")替换为单个复选框"只显示物流分类项目"
|
||||
- **增强递归检查**:添加了`HasLogisticsAttributesRecursive`方法,确保父节点包含具有物流属性的子节点时不会被隐藏
|
||||
- **优化用户体验**:复选框状态实时反映当前可见性状态,操作失败时自动回滚状态
|
||||
|
||||
#### 技术成果
|
||||
|
||||
- **核心算法改进**:
|
||||
- 新增递归检查方法,避免误隐藏包含物流子项的父项
|
||||
- 修复了 `item.Children.Count` 方法组调用问题,改为 `item.Children.Count()`
|
||||
@ -208,6 +229,7 @@
|
||||
- 操作失败时的状态回滚机制
|
||||
|
||||
#### 验证结果
|
||||
|
||||
- ✅ 设置3个模型为物流分类后,勾选"只显示物流分类项目"复选框,成功隐藏非物流项目同时保持物流项目可见
|
||||
- ✅ 取消勾选复选框,所有项目正确恢复显示
|
||||
- ✅ 状态标签准确显示操作结果和隐藏项目数量
|
||||
@ -220,12 +242,14 @@
|
||||
### 增加物流类别属性功能
|
||||
|
||||
#### 主要变更
|
||||
|
||||
- **实现物流属性分类系统**:支持8种物流元素类型(门、电梯、楼梯、通道、障碍物、装卸区、停车位、检查点)
|
||||
- **集成COM API功能**:通过Navisworks COM API实现自定义属性的添加和管理
|
||||
- **优化代码架构**:将LogisticsCategories.cs功能整合到CategoryAttributeManager.cs中,避免重复定义
|
||||
- **修复API兼容性问题**:解决了多个Navisworks 2017 API兼容性问题
|
||||
|
||||
#### 技术成果
|
||||
|
||||
- **COM API集成**:
|
||||
- 正确实现了ComApiBridge.State的使用
|
||||
- 修复了ObjectFactory的调用方式
|
||||
@ -242,6 +266,7 @@
|
||||
- 优化了错误处理和调试信息输出
|
||||
|
||||
#### 验证结果
|
||||
|
||||
- ✅ 成功为选定模型项添加物流属性,属性在Navisworks属性面板中正确显示
|
||||
- ✅ 8种物流元素类型的按钮功能正常,属性设置准确
|
||||
- ✅ COM API调用稳定,无内存泄漏或崩溃问题
|
||||
@ -252,6 +277,7 @@
|
||||
## 版本 [0.1.3] - 2024-01-XX
|
||||
|
||||
### 修复
|
||||
|
||||
- **兼容性修复**: 修复C# 7.3兼容性问题,移除了nullable引用类型语法
|
||||
- **API兼容性**: 修复Navisworks 2017 API兼容性问题
|
||||
- 替换了不存在的`View.RequestSavedViewpoint()`方法
|
||||
@ -265,6 +291,7 @@
|
||||
- **射线投射算法**: 完善了射线与包围盒交点计算的错误处理
|
||||
|
||||
### 技术改进
|
||||
|
||||
- **错误处理**: 增强了所有射线投射相关方法的错误处理和日志记录
|
||||
- **后备方案**: 在精确坐标获取失败时提供包围盒中心点作为后备方案
|
||||
- **日志优化**: 改进了调试日志的详细程度和格式
|
||||
@ -272,15 +299,18 @@
|
||||
## 技术债务和改进计划
|
||||
|
||||
### 当前已知问题
|
||||
|
||||
- 暂无已知的功能性问题
|
||||
|
||||
### 已完成功能 ✅
|
||||
|
||||
1. ✅ **TimeLiner 集成**:已实现完整的 TimeLiner 集成功能(v0.1.9)
|
||||
- 运输任务自动创建和管理
|
||||
- 动画状态实时同步
|
||||
- 完善的错误处理和降级机制
|
||||
|
||||
### 下一步开发计划
|
||||
|
||||
1. **路径规划功能**:实现 A* 算法的 3D 路径规划
|
||||
2. **动态碰撞检测增强**:进一步集成 Clash Detective 功能
|
||||
3. **动画和可视化优化**:添加更多路径动画效果和碰撞高亮显示
|
||||
@ -291,6 +321,7 @@
|
||||
- 任务导入导出功能
|
||||
|
||||
### 性能优化目标
|
||||
|
||||
- 大型模型的处理性能优化
|
||||
- 异步操作的用户界面响应性改进
|
||||
- 内存使用优化和资源清理机制完善
|
||||
@ -298,6 +329,7 @@
|
||||
## [0.1.4] - 2024-01-XX
|
||||
|
||||
### 修复
|
||||
|
||||
- **点击监听问题**: 修复鼠标点击没有效果的问题
|
||||
- 添加了点击状态跟踪机制,避免重复处理同一选择
|
||||
- 增加最小点击间隔(500ms)防止误触
|
||||
@ -319,6 +351,7 @@
|
||||
- 实现地图中选中点的高亮重绘
|
||||
|
||||
### 技术改进
|
||||
|
||||
- **状态管理**: 增强点击状态跟踪和管理
|
||||
- 添加_lastProcessedItem和_lastProcessedTime字段
|
||||
- 实现MinClickInterval常量控制最小点击间隔
|
||||
15
CLAUDE.md
15
CLAUDE.md
@ -15,11 +15,13 @@ NavisworksTransport is a Navisworks 2017 plugin (v0.1.8) for logistics path plan
|
||||
## Architecture Overview
|
||||
|
||||
### Core Plugin Structure
|
||||
|
||||
- **MainPlugin.cs**: Primary AddInPlugin entry point with ribbon UI
|
||||
- **PathClickToolPlugin.cs**: ToolPlugin for 3D mouse interaction
|
||||
- **PathPointRenderPlugin.cs**: RenderPlugin for 3D visualization
|
||||
|
||||
### Manager Components
|
||||
|
||||
- **PathPlanningManager.cs**: Central path planning and route management logic
|
||||
- **PathAnimationManager.cs**: TimeLiner integration for object movement animation
|
||||
- **CoordinateConverter.cs**: 2D map overlay to 3D world coordinate conversion
|
||||
@ -28,64 +30,77 @@ NavisworksTransport is a Navisworks 2017 plugin (v0.1.8) for logistics path plan
|
||||
- **ModelSplitterManager.cs**: Model layer separation and export functionality
|
||||
|
||||
### Data and Utilities
|
||||
|
||||
- **PathPlanningModels.cs**: Core data structures (PathEditState, PathRoute, PathPoint)
|
||||
- **PathDataManager.cs**: Serialization and persistence using Newtonsoft.Json
|
||||
- **GeometryExtractor.cs**: 3D geometry analysis and bounding box calculations
|
||||
- **LogManager.cs**: Centralized logging with global exception handling
|
||||
|
||||
### UI Components
|
||||
|
||||
- **LogisticsPropertyEditDialog.cs**: Property editing interface
|
||||
- **ModelSplitterDialog.cs**: Model splitting configuration UI
|
||||
|
||||
## Key Technical Details
|
||||
|
||||
### Navisworks API Integration
|
||||
|
||||
- Uses dual API approach: Native API (`Autodesk.Navisworks.Api`) + COM API (`Autodesk.Navisworks.ComApi`)
|
||||
- COM API required for attribute persistence and TimeLiner operations
|
||||
- Plugin types: AddInPlugin (main), ToolPlugin (interaction), RenderPlugin (visualization)
|
||||
|
||||
### Exception Handling
|
||||
|
||||
Global exception handling implemented in MainPlugin with:
|
||||
|
||||
- AppDomain.CurrentDomain.UnhandledException
|
||||
- Application.ThreadException
|
||||
- Automatic recovery and user-friendly error reporting
|
||||
|
||||
### Coordinate Systems
|
||||
|
||||
- Supports 2D map overlay on 3D models with dynamic zoom/pan
|
||||
- Margin-based boundary calculations for click precision
|
||||
- Transform chains for coordinate conversion between spaces
|
||||
|
||||
### Logistics Categories
|
||||
|
||||
Eight predefined logistics element types:
|
||||
|
||||
- 门 (Doors), 电梯 (Elevators), 楼梯 (Stairs), 通道 (Channels)
|
||||
- 障碍物 (Obstacles), 装卸区 (Loading Zones), 停车区 (Parking), 检查点 (Checkpoints)
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Language Preference
|
||||
|
||||
- **使用中文进行所有交流和代码注释**
|
||||
- 与用户交流时优先使用中文
|
||||
- 代码注释和文档说明使用中文
|
||||
|
||||
### File Organization
|
||||
|
||||
- Core managers handle specific functionality areas
|
||||
- Models file contains shared data structures
|
||||
- UI dialogs are separate form classes
|
||||
- Utilities (logging, geometry, data) are standalone classes
|
||||
|
||||
### Plugin Registration Pattern
|
||||
|
||||
```csharp
|
||||
[Plugin("NavisworksTransport.PluginName", "YourDeveloperID")]
|
||||
[AddInPlugin(AddInLocation.AddIn)]
|
||||
```
|
||||
|
||||
### Error Handling Best Practices
|
||||
|
||||
- Use LogManager for consistent logging
|
||||
- Implement try-catch blocks around Navisworks API calls
|
||||
- Provide meaningful error messages to users
|
||||
- Use COM API error codes for troubleshooting
|
||||
|
||||
### Dependencies
|
||||
|
||||
- **System.Windows.Forms**: UI dialogs and controls
|
||||
- **System.Drawing**: Graphics and coordinate operations
|
||||
|
||||
|
||||
@ -7,16 +7,19 @@
|
||||
## 功能特性
|
||||
|
||||
### 1. 自动碰撞检测
|
||||
|
||||
- **实时检测**: 动画播放过程中实时检测碰撞
|
||||
- **智能回退**: 当 Clash Detective 不可用时,自动切换到简化碰撞检测
|
||||
- **双重模式**: 支持精确几何碰撞检测和简化包围盒检测
|
||||
|
||||
### 2. Clash Detective 集成
|
||||
|
||||
- **自动发现**: 自动检测并连接到 Clash Detective 插件
|
||||
- **测试管理**: 创建和管理动态碰撞测试
|
||||
- **结果同步**: 碰撞结果同步显示到 Clash Detective 窗口
|
||||
|
||||
### 3. 可视化高亮
|
||||
|
||||
- **碰撞高亮**: 自动高亮碰撞对象(红色显示)
|
||||
- **实时更新**: 动画过程中实时更新碰撞状态
|
||||
- **清理机制**: 动画结束后自动清理临时高亮
|
||||
@ -24,21 +27,25 @@
|
||||
## 使用方法
|
||||
|
||||
### 1. 启动插件
|
||||
|
||||
1. 打开 Navisworks Manage 2017
|
||||
2. 加载包含物流路径的模型
|
||||
3. 从菜单栏选择 "附加模块" > "Transport Plugin"
|
||||
|
||||
### 2. 设置动画
|
||||
|
||||
1. 在控制面板中选择要动画的车辆对象
|
||||
2. 选择预定义的路径或创建新路径
|
||||
3. 设置动画参数(时长、速度等)
|
||||
|
||||
### 3. 启用碰撞检测
|
||||
|
||||
1. 在动画控制面板中确保"启用碰撞检测"选项已勾选
|
||||
2. 可选择"高亮显示碰撞"以可视化碰撞结果
|
||||
3. 点击"播放动画"开始带碰撞检测的动画
|
||||
|
||||
### 4. 测试集成功能
|
||||
|
||||
1. 点击"测试Clash Detective集成"按钮
|
||||
2. 系统会自动运行完整的集成测试
|
||||
3. 查看测试结果和日志信息
|
||||
@ -48,6 +55,7 @@
|
||||
### 核心组件
|
||||
|
||||
#### 1. ClashDetectiveIntegration
|
||||
|
||||
- **功能**: 主要的集成管理器
|
||||
- **位置**: `src/ClashDetectiveIntegration.cs`
|
||||
- **职责**:
|
||||
@ -56,6 +64,7 @@
|
||||
- 处理结果同步
|
||||
|
||||
#### 2. PathAnimationManager
|
||||
|
||||
- **功能**: 动画管理器(已升级)
|
||||
- **位置**: `src/PathAnimationManager.cs`
|
||||
- **职责**:
|
||||
@ -64,6 +73,7 @@
|
||||
- 处理高亮显示
|
||||
|
||||
#### 3. ClashDetectiveIntegrationTest
|
||||
|
||||
- **功能**: 集成测试管理器
|
||||
- **位置**: `src/ClashDetectiveIntegrationTest.cs`
|
||||
- **职责**:
|
||||
@ -84,6 +94,7 @@
|
||||
### 主要方法
|
||||
|
||||
#### ClashDetectiveIntegration.Instance
|
||||
|
||||
```csharp
|
||||
// 初始化集成
|
||||
void Initialize()
|
||||
@ -99,6 +110,7 @@ void Cleanup()
|
||||
```
|
||||
|
||||
#### 事件处理
|
||||
|
||||
```csharp
|
||||
// 碰撞检测事件
|
||||
event EventHandler<CollisionDetectedEventArgs> CollisionDetected;
|
||||
@ -112,6 +124,7 @@ public class CollisionDetectedEventArgs : EventArgs
|
||||
```
|
||||
|
||||
### 碰撞结果数据结构
|
||||
|
||||
```csharp
|
||||
public class CollisionResult
|
||||
{
|
||||
@ -130,11 +143,13 @@ public class CollisionResult
|
||||
## 配置选项
|
||||
|
||||
### 碰撞检测参数
|
||||
|
||||
- **容差**: 默认 0.01 米(1厘米)
|
||||
- **测试类型**: 硬碰撞检测
|
||||
- **检测频率**: 50ms 间隔(20 FPS)
|
||||
|
||||
### 高亮设置
|
||||
|
||||
- **碰撞颜色**: 红色
|
||||
- **非碰撞对象**: 保持原色
|
||||
- **清理时机**: 动画结束或用户停止
|
||||
@ -144,22 +159,28 @@ public class CollisionResult
|
||||
### 常见问题
|
||||
|
||||
#### 1. Clash Detective 未找到
|
||||
|
||||
**症状**: 系统提示"未找到Clash Detective插件"
|
||||
**解决**:
|
||||
|
||||
- 确保 Clash Detective 已正确安装
|
||||
- 检查 Navisworks 版本兼容性
|
||||
- 查看日志文件获取详细信息
|
||||
|
||||
#### 2. 碰撞检测不工作
|
||||
|
||||
**症状**: 动画播放但无碰撞检测结果
|
||||
**解决**:
|
||||
|
||||
- 确保模型包含几何体
|
||||
- 检查动画对象是否有效
|
||||
- 使用测试按钮验证集成
|
||||
|
||||
#### 3. 高亮显示异常
|
||||
|
||||
**症状**: 碰撞对象未正确高亮
|
||||
**解决**:
|
||||
|
||||
- 重启动画播放
|
||||
- 检查对象选择是否正确
|
||||
- 清理临时材质覆盖
|
||||
@ -167,12 +188,15 @@ public class CollisionResult
|
||||
### 调试方法
|
||||
|
||||
#### 1. 查看日志
|
||||
|
||||
日志文件位置: `%USERPROFILE%\Documents\NavisworksTransport\Logs\`
|
||||
|
||||
#### 2. 运行测试
|
||||
|
||||
使用"测试Clash Detective集成"按钮进行全面测试
|
||||
|
||||
#### 3. 检查系统状态
|
||||
|
||||
```csharp
|
||||
// 检查COM API状态
|
||||
var state = ComApiBridge.ComApiBridge.State;
|
||||
@ -184,11 +208,13 @@ var pluginCount = state.Plugins().Count;
|
||||
## 性能优化
|
||||
|
||||
### 建议设置
|
||||
|
||||
- **大模型**: 增加碰撞检测间隔到 100ms
|
||||
- **复杂路径**: 减少路径点数量
|
||||
- **多对象**: 使用批处理检测
|
||||
|
||||
### 内存管理
|
||||
|
||||
- 动画结束后自动清理资源
|
||||
- 定期重置临时材质
|
||||
- 避免长时间运行动画
|
||||
@ -196,12 +222,14 @@ var pluginCount = state.Plugins().Count;
|
||||
## 更新日志
|
||||
|
||||
### v0.1.8 (当前版本)
|
||||
|
||||
- ✅ 新增 Clash Detective 集成功能
|
||||
- ✅ 实现实时碰撞检测
|
||||
- ✅ 添加自动化测试框架
|
||||
- ✅ 优化性能和错误处理
|
||||
|
||||
### 计划功能
|
||||
|
||||
- 🔄 支持自定义碰撞规则
|
||||
- 🔄 批量路径碰撞分析
|
||||
- 🔄 碰撞报告导出
|
||||
@ -210,6 +238,7 @@ var pluginCount = state.Plugins().Count;
|
||||
## 技术支持
|
||||
|
||||
如有问题请查看:
|
||||
|
||||
1. 日志文件: `%USERPROFILE%\Documents\NavisworksTransport\Logs\`
|
||||
2. 测试结果: 使用集成测试按钮
|
||||
3. 开发文档: `doc/design/` 目录
|
||||
|
||||
@ -10,9 +10,7 @@
|
||||
|
||||
我们的集成采用了**双重架构**:
|
||||
|
||||
```
|
||||
动画管理器 -> ClashDetectiveIntegration -> .NET API + COM API -> Clash Detective窗口
|
||||
```
|
||||
|
||||
- **动画播放时**: 自动检测碰撞并创建测试结果
|
||||
- **测试按钮**: 验证集成功能并强制显示结果
|
||||
@ -21,16 +19,19 @@
|
||||
### 2. 集成的具体表现
|
||||
|
||||
#### A. 测试创建
|
||||
|
||||
- ✅ 自动创建名为 "动态运输路径碰撞检测" 的测试
|
||||
- ✅ 测试会出现在Clash Detective的测试列表中
|
||||
- ✅ 测试参数:硬碰撞、1cm容差
|
||||
|
||||
#### B. 结果显示
|
||||
|
||||
- ✅ 碰撞结果会添加到测试中
|
||||
- ✅ 3D视图中高亮显示碰撞对象(红色)
|
||||
- ✅ 日志记录详细的检测信息
|
||||
|
||||
#### C. 窗口同步
|
||||
|
||||
- ✅ 自动刷新Clash Detective界面
|
||||
- ✅ 运行所有测试以触发更新
|
||||
- ✅ 强制重绘3D视图
|
||||
@ -38,18 +39,21 @@
|
||||
## 如何查看集成效果
|
||||
|
||||
### 方法1:检查测试列表
|
||||
|
||||
1. 打开 Clash Detective 窗口
|
||||
2. 查看左侧的测试列表
|
||||
3. 寻找 "动态运输路径碰撞检测" 项
|
||||
4. 点击该测试查看详细信息
|
||||
|
||||
### 方法2:查看测试结果
|
||||
|
||||
1. 在测试列表中选择我们的测试
|
||||
2. 查看右侧的结果面板
|
||||
3. 结果会显示碰撞的对象名称和状态
|
||||
4. 双击结果可以定位到3D视图
|
||||
|
||||
### 方法3:监控日志输出
|
||||
|
||||
1. 查看日志文件:`%USERPROFILE%\Documents\NavisworksTransport\Logs\`
|
||||
2. 搜索关键词:
|
||||
- "Clash Detective"
|
||||
@ -58,6 +62,7 @@
|
||||
- "同步结果到Clash Detective"
|
||||
|
||||
### 方法4:使用新的测试按钮
|
||||
|
||||
1. 点击 "测试Clash Detective集成" 按钮
|
||||
2. 查看弹出的详细信息对话框
|
||||
3. 按照提示检查Clash Detective窗口
|
||||
@ -65,34 +70,43 @@
|
||||
## 可能的显示问题及解决方案
|
||||
|
||||
### 问题1:测试列表中没有看到我们的测试
|
||||
|
||||
**可能原因**:
|
||||
|
||||
- Clash Detective窗口未刷新
|
||||
- 测试创建失败
|
||||
- 权限问题
|
||||
|
||||
**解决方案**:
|
||||
|
||||
1. 关闭并重新打开Clash Detective窗口
|
||||
2. 点击 "测试Clash Detective集成" 按钮强制刷新
|
||||
3. 查看日志了解详细错误信息
|
||||
|
||||
### 问题2:测试存在但无结果
|
||||
|
||||
**可能原因**:
|
||||
|
||||
- 动画对象与其他对象无碰撞
|
||||
- 选择集设置不正确
|
||||
- 测试参数过于严格
|
||||
|
||||
**解决方案**:
|
||||
|
||||
1. 确保动画对象与其他对象有重叠
|
||||
2. 调整碰撞容差(当前为1cm)
|
||||
3. 使用测试按钮执行强制检测
|
||||
|
||||
### 问题3:3D视图中看不到高亮
|
||||
|
||||
**可能原因**:
|
||||
|
||||
- 高亮颜色与背景相似
|
||||
- 临时材质被清除
|
||||
- 视图渲染问题
|
||||
|
||||
**解决方案**:
|
||||
|
||||
1. 改变视图背景颜色
|
||||
2. 重新运行动画
|
||||
3. 检查日志中的高亮信息
|
||||
@ -100,6 +114,7 @@
|
||||
## 调试和验证步骤
|
||||
|
||||
### 1. 基础验证
|
||||
|
||||
```
|
||||
1. 加载包含多个对象的模型
|
||||
2. 启动插件并打开Clash Detective
|
||||
@ -108,6 +123,7 @@
|
||||
```
|
||||
|
||||
### 2. 动画验证
|
||||
|
||||
```
|
||||
1. 设置动画对象和路径
|
||||
2. 启用"碰撞检测"选项
|
||||
@ -117,6 +133,7 @@
|
||||
```
|
||||
|
||||
### 3. 日志分析
|
||||
|
||||
```
|
||||
1. 打开日志文件
|
||||
2. 搜索集成相关信息
|
||||
@ -126,14 +143,16 @@
|
||||
|
||||
## 集成效果的预期表现
|
||||
|
||||
### 正常情况下您应该看到:
|
||||
### 正常情况下您应该看到
|
||||
|
||||
1. **测试列表**:出现 "动态运输路径碰撞检测" 项
|
||||
2. **结果面板**:显示检测到的碰撞结果
|
||||
3. **3D视图**:碰撞对象显示红色高亮
|
||||
4. **日志信息**:记录详细的检测过程
|
||||
5. **状态报告**:测试按钮提供的详细信息
|
||||
|
||||
### 如果仍然看不到效果:
|
||||
### 如果仍然看不到效果
|
||||
|
||||
1. 检查Navisworks版本是否为2017
|
||||
2. 确认Clash Detective插件已正确安装
|
||||
3. 验证模型中是否有足够的几何对象
|
||||
@ -142,13 +161,15 @@
|
||||
|
||||
## 技术细节
|
||||
|
||||
### 我们的集成方式:
|
||||
### 我们的集成方式
|
||||
|
||||
- 使用 .NET API 创建和管理碰撞测试
|
||||
- 使用 COM API 访问底层功能
|
||||
- 通过多种方式刷新窗口显示
|
||||
- 提供详细的状态监控和日志记录
|
||||
|
||||
### 与标准用法的区别:
|
||||
### 与标准用法的区别
|
||||
|
||||
- 动态创建测试而非预定义
|
||||
- 实时更新结果而非批处理
|
||||
- 集成到动画循环中而非独立运行
|
||||
|
||||
@ -3,12 +3,14 @@
|
||||
## 功能模块详细需求
|
||||
|
||||
### Navisworks插件开发和安装部署
|
||||
|
||||
| 次级功能点 | 功能点描述 |
|
||||
|------------|------------|
|
||||
| 插件二次开发 | 基于Navisworks 2017 SDK进行二次开发,用插件的方式,集成到Navisworks的菜单中。 |
|
||||
| 一键安装部署 | 支持Windows 7环境安装,程序自动识别Navisworks安装路径,并安装插件,自动修改配置和菜单。 |
|
||||
|
||||
### 通道选择及路径点规划模块
|
||||
|
||||
| 次级功能点 | 功能点描述 |
|
||||
|------------|------------|
|
||||
| 通道选择 | 支持选择通道模型功能,可通过选择树或三维视图点选的方式,选择模型并制定为通道类型。 |
|
||||
@ -17,12 +19,14 @@
|
||||
| 路径点自动贴合 | 路径点要自动贴合通道模型表面,路径点之间通过直线进行联通。 |
|
||||
|
||||
### 物流"类别"设置功能模块
|
||||
|
||||
| 次级功能点 | 功能点描述 |
|
||||
|------------|------------|
|
||||
| 类别设置 | 支持模型属性页面新增"物流属性"类别。 |
|
||||
| 属性设置 | 1、支持通过选择树和三维视图选择的方式,选择物流路径相关的元素(如门、电梯、楼梯、通道等),设置为特定的物流分类,并支持类型、可通行性、速度限制、宽度限制、优先级等属性;<br>2、支持在Navisworks中进行识别和筛选,支持物流分类属性的添加、编辑和清除。 |
|
||||
|
||||
### 层级创建功能模块
|
||||
|
||||
| 次级功能点 | 功能点描述 |
|
||||
|------------|------------|
|
||||
| 层级显示 | 支持自动隐藏或淡化非关键层,以便专注于物流路径相关的层级。 |
|
||||
@ -30,6 +34,7 @@
|
||||
| 路径时间标签 | 支持路径时间标签设置,以预估运输时间。 |
|
||||
|
||||
### 交互式导航功能模块
|
||||
|
||||
| 次级功能点 | 功能点描述 |
|
||||
|------------|------------|
|
||||
| 交互式导航控件 | 创建交互式导航控件,允许用户选择不同的起点和终点,动态生成路径。 |
|
||||
@ -37,6 +42,7 @@
|
||||
| 输出格式 | 支持路径规划结果结构化文件输出(XML/JSON/CSV),结果文件能够导入DELMIA。 |
|
||||
|
||||
### 碰撞检测功能模块
|
||||
|
||||
| 次级功能点 | 功能点描述 |
|
||||
|------------|------------|
|
||||
| 动画生成和播放 | 1、指定物流组件(待载转运车),选择路径,支持生成动画仿真物流组件的运动过程;<br>2、支持设置动画时长,支持动画的播放、停止和步进播放。 |
|
||||
@ -45,8 +51,10 @@
|
||||
| 路径规划分析 | 对多个路径运行的碰撞结果,进行分析,生成路径分析报告,选择最佳路径,提供调整建议。 |
|
||||
|
||||
## 技术指标要求
|
||||
|
||||
- 可实现不小于10种尺寸规格的带转载运车的路径规划
|
||||
|
||||
## 运行环境
|
||||
|
||||
- 操作系统:Windows 7
|
||||
- 软件环境:Navisworks 2017
|
||||
@ -287,62 +287,417 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建碰撞快照(仅在手动测试时使用)
|
||||
/// <summary>
|
||||
/// 创建碰撞快照(动画结束后一次性更新结果)
|
||||
/// </summary>
|
||||
public void CreateCollisionSnapshot(List<CollisionResult> results)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_documentClash == null || results.Count == 0)
|
||||
if (_documentClash == null)
|
||||
return;
|
||||
|
||||
var firstCollision = results[0];
|
||||
if (firstCollision.Item1 != null && firstCollision.Item2 != null)
|
||||
// 缓存结果,等动画结束后统一处理
|
||||
CacheCollisionResults(results);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"创建实时碰撞快照失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private List<CollisionResult> _cachedResults = new List<CollisionResult>();
|
||||
|
||||
/// <summary>
|
||||
/// 缓存碰撞结果
|
||||
/// </summary>
|
||||
private void CacheCollisionResults(List<CollisionResult> results)
|
||||
{
|
||||
if (results != null && results.Count > 0)
|
||||
{
|
||||
_cachedResults.AddRange(results);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动画结束后创建最终碰撞结果汇总 - 同步安全版本
|
||||
/// </summary>
|
||||
public void CreateFinalCollisionSummary()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("=== 开始创建最终碰撞结果汇总(同步模式) ===");
|
||||
LogManager.Info($"步骤1: 检查前置条件 - _documentClash是否存在: {_documentClash != null}");
|
||||
LogManager.Info($"步骤1: 检查前置条件 - 缓存结果数量: {_cachedResults.Count}");
|
||||
|
||||
if (_documentClash == null || _cachedResults.Count == 0)
|
||||
{
|
||||
// 检查对象是否仍然有效
|
||||
if (IsModelItemValid(firstCollision.Item1) && IsModelItemValid(firstCollision.Item2))
|
||||
LogManager.Info("前置条件不满足,退出创建");
|
||||
return;
|
||||
}
|
||||
|
||||
LogManager.Info($"步骤2: 开始处理 {_cachedResults.Count} 个碰撞结果");
|
||||
|
||||
// 去重处理
|
||||
LogManager.Info("步骤3: 开始去重处理...");
|
||||
var uniqueCollisions = _cachedResults
|
||||
.GroupBy(r => new { r.Item1, r.Item2 })
|
||||
.Select(g => g.First())
|
||||
.ToList();
|
||||
LogManager.Info($"步骤3: 去重后碰撞数量: {uniqueCollisions.Count}");
|
||||
|
||||
if (!uniqueCollisions.Any())
|
||||
{
|
||||
LogManager.Info("去重后无碰撞,退出创建");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建最终汇总测试
|
||||
var testName = $"物流路径碰撞汇总_{DateTime.Now:yyyyMMdd_HHmmss}";
|
||||
LogManager.Info($"步骤4: 创建测试对象 - 测试名称: {testName}");
|
||||
|
||||
var summaryTest = new ClashTest();
|
||||
summaryTest.DisplayName = testName;
|
||||
summaryTest.TestType = ClashTestType.Hard;
|
||||
summaryTest.Tolerance = 0.01;
|
||||
|
||||
LogManager.Info("步骤5: 构建选择集A - 动画对象");
|
||||
var selectionA = new ModelItemCollection();
|
||||
var animatedObjects = uniqueCollisions.Select(r => r.Item1).Distinct();
|
||||
int validAnimatedCount = 0;
|
||||
foreach (var obj in animatedObjects)
|
||||
{
|
||||
if (IsModelItemValid(obj))
|
||||
{
|
||||
// 创建一个快照测试来展示实际碰撞
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
var testName = $"动画碰撞快照_{timestamp}";
|
||||
selectionA.Add(obj);
|
||||
validAnimatedCount++;
|
||||
}
|
||||
}
|
||||
LogManager.Info($"步骤5: 选择集A - 有效对象数量: {validAnimatedCount}");
|
||||
|
||||
var snapshotTest = new ClashTest();
|
||||
snapshotTest.DisplayName = testName;
|
||||
snapshotTest.TestType = ClashTestType.Hard;
|
||||
snapshotTest.Tolerance = 0.01;
|
||||
LogManager.Info("步骤6: 构建选择集B - 碰撞对象");
|
||||
var selectionB = new ModelItemCollection();
|
||||
var collidingObjects = uniqueCollisions.Select(r => r.Item2).Distinct();
|
||||
int validCollidingCount = 0;
|
||||
foreach (var obj in collidingObjects)
|
||||
{
|
||||
if (IsModelItemValid(obj))
|
||||
{
|
||||
selectionB.Add(obj);
|
||||
validCollidingCount++;
|
||||
}
|
||||
}
|
||||
LogManager.Info($"步骤6: 选择集B - 有效对象数量: {validCollidingCount}");
|
||||
|
||||
var selectionA = new ModelItemCollection();
|
||||
selectionA.Add(firstCollision.Item1);
|
||||
snapshotTest.SelectionA.Selection.CopyFrom(selectionA);
|
||||
// 验证选择集是否为空
|
||||
if (selectionA.Count == 0 || selectionB.Count == 0)
|
||||
{
|
||||
LogManager.Error("选择集为空,无法创建测试");
|
||||
return;
|
||||
}
|
||||
|
||||
var selectionB = new ModelItemCollection();
|
||||
selectionB.Add(firstCollision.Item2);
|
||||
snapshotTest.SelectionB.Selection.CopyFrom(selectionB);
|
||||
summaryTest.SelectionA.Selection.CopyFrom(selectionA);
|
||||
summaryTest.SelectionB.Selection.CopyFrom(selectionB);
|
||||
LogManager.Info($"步骤7: 选择集设置完成 - A:{selectionA.Count}, B:{selectionB.Count}");
|
||||
|
||||
// 添加并运行测试
|
||||
_documentClash.TestsData.TestsAddCopy(snapshotTest);
|
||||
LogManager.Info("步骤8: 直接添加测试到文档");
|
||||
try
|
||||
{
|
||||
// 直接同步添加测试
|
||||
_documentClash.TestsData.TestsAddCopy(summaryTest);
|
||||
LogManager.Info("步骤8: 测试添加完成");
|
||||
|
||||
// 重新获取并运行测试
|
||||
var addedTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == testName);
|
||||
if (addedTest is ClashTest runTest)
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(runTest);
|
||||
LogManager.Info($"已创建并运行碰撞快照: {testName},展示 {firstCollision.Item1.DisplayName} <-> {firstCollision.Item2.DisplayName},结果数量: {runTest.Children.Count}");
|
||||
}
|
||||
// 立即重新获取测试引用
|
||||
var addedTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == testName) as ClashTest;
|
||||
if (addedTest != null)
|
||||
{
|
||||
LogManager.Info($"找到测试对象: {addedTest.DisplayName}, GUID: {addedTest.Guid}");
|
||||
|
||||
// 立即运行测试
|
||||
_documentClash.TestsData.TestsRunTest(addedTest);
|
||||
LogManager.Info($"测试运行完成: {testName}, 找到 {addedTest.Children.Count} 个碰撞");
|
||||
|
||||
// 强制刷新
|
||||
RefreshClashDetectiveUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("碰撞对象已被释放,跳过测试创建");
|
||||
LogManager.Error("未找到添加的测试对象");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"步骤8: 添加或运行测试失败 - {ex.GetType().Name}: {ex.Message}");
|
||||
LogManager.Error($"详细错误: {ex.StackTrace}");
|
||||
|
||||
// 尝试恢复 - 重新初始化
|
||||
LogManager.Info("尝试重新初始化Clash Detective...");
|
||||
Initialize();
|
||||
|
||||
try
|
||||
{
|
||||
_documentClash.TestsData.TestsAddCopy(summaryTest);
|
||||
var addedTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == testName) as ClashTest;
|
||||
if (addedTest != null)
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(addedTest);
|
||||
LogManager.Info($"重试成功: {testName}");
|
||||
}
|
||||
}
|
||||
catch (Exception retryEx)
|
||||
{
|
||||
LogManager.Error($"重试也失败: {retryEx.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 清空缓存
|
||||
_cachedResults.Clear();
|
||||
LogManager.Info("=== 最终碰撞结果汇总创建完成 ===");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"创建最终碰撞汇总失败 - {ex.GetType().Name}: {ex.Message}");
|
||||
LogManager.Error($"创建最终碰撞汇总失败 - 堆栈跟踪: {ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全运行汇总测试
|
||||
/// </summary>
|
||||
private void RunSummaryTestSafely(string testName)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("=== 开始安全运行汇总测试 ===");
|
||||
|
||||
if (Application.ActiveDocument == null)
|
||||
{
|
||||
LogManager.Error("文档已失效");
|
||||
return;
|
||||
}
|
||||
|
||||
var docClash = Application.ActiveDocument.GetClash();
|
||||
if (docClash == null || docClash.TestsData == null)
|
||||
{
|
||||
LogManager.Error("Clash数据不可用");
|
||||
return;
|
||||
}
|
||||
|
||||
var tests = docClash.TestsData.Tests;
|
||||
LogManager.Info($"文档中测试总数: {tests.Count}");
|
||||
|
||||
// 重新获取测试
|
||||
var addedTest = tests.FirstOrDefault(t => t.DisplayName == testName) as ClashTest;
|
||||
|
||||
if (addedTest != null)
|
||||
{
|
||||
LogManager.Info($"找到测试对象: {addedTest.DisplayName}, GUID: {addedTest.Guid}");
|
||||
|
||||
try
|
||||
{
|
||||
// 运行测试
|
||||
docClash.TestsData.TestsRunTest(addedTest);
|
||||
LogManager.Info($"测试运行完成: {testName}");
|
||||
|
||||
// 强制刷新UI
|
||||
RefreshClashDetectiveUI();
|
||||
|
||||
LogManager.Info("=== 最终碰撞结果汇总完成 ===");
|
||||
}
|
||||
catch (Exception runEx)
|
||||
{
|
||||
LogManager.Error($"运行测试失败: {runEx.Message}");
|
||||
// 尝试异步运行
|
||||
RunTestAsync(docClash, addedTest);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Error("未找到添加的测试对象");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"安全运行汇总测试失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 直接运行测试(回退方案)
|
||||
/// </summary>
|
||||
private void RunSummaryTestDirectly(ClashTest test, string testName)
|
||||
{
|
||||
try
|
||||
{
|
||||
_documentClash.TestsData.TestsAddCopy(test);
|
||||
var addedTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == testName) as ClashTest;
|
||||
|
||||
if (addedTest != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(addedTest);
|
||||
LogManager.Info($"直接运行测试完成: {testName}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
LogManager.Warning("直接运行测试失败,跳过");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"创建碰撞快照失败: {ex.Message}");
|
||||
LogManager.Error($"直接运行汇总测试失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步运行测试
|
||||
/// </summary>
|
||||
private void RunTestAsync(DocumentClash docClash, ClashTest test)
|
||||
{
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
docClash.TestsData.TestsRunTest(test);
|
||||
LogManager.Info($"异步运行测试完成: {test.DisplayName}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"异步运行测试失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新Clash Detective UI
|
||||
/// </summary>
|
||||
private void RefreshClashDetectiveUI()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 强制重绘视图
|
||||
var doc = Application.ActiveDocument;
|
||||
if (doc?.ActiveView != null)
|
||||
{
|
||||
doc.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
|
||||
}
|
||||
|
||||
LogManager.Info("Clash Detective UI已刷新");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"刷新Clash Detective UI失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新现有测试的选择集
|
||||
/// </summary>
|
||||
private void UpdateExistingTest(ClashTest existingTest, List<CollisionResult> validCollisions)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (existingTest == null || !validCollisions.Any())
|
||||
return;
|
||||
|
||||
// 重新构建选择集
|
||||
var selectionA = new ModelItemCollection();
|
||||
selectionA.Add(validCollisions[0].Item1); // 动画对象
|
||||
existingTest.SelectionA.Selection.CopyFrom(selectionA);
|
||||
|
||||
var selectionB = new ModelItemCollection();
|
||||
foreach (var collision in validCollisions)
|
||||
{
|
||||
if (!selectionB.Contains(collision.Item2))
|
||||
{
|
||||
selectionB.Add(collision.Item2);
|
||||
}
|
||||
}
|
||||
existingTest.SelectionB.Selection.CopyFrom(selectionB);
|
||||
|
||||
// 运行测试以更新结果
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(existingTest);
|
||||
LogManager.Info($"更新动画碰撞测试: {validCollisions.Count} 个碰撞对象");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"更新测试失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"更新现有测试失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建新的动画碰撞测试
|
||||
/// </summary>
|
||||
private void CreateNewAnimationTest(string testName, List<CollisionResult> validCollisions)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!validCollisions.Any())
|
||||
return;
|
||||
|
||||
var snapshotTest = new ClashTest();
|
||||
snapshotTest.DisplayName = testName;
|
||||
snapshotTest.TestType = ClashTestType.Hard;
|
||||
snapshotTest.Tolerance = 0.01;
|
||||
|
||||
// 设置选择集 - 动画对象
|
||||
var selectionA = new ModelItemCollection();
|
||||
selectionA.Add(validCollisions[0].Item1);
|
||||
snapshotTest.SelectionA.Selection.CopyFrom(selectionA);
|
||||
|
||||
// 设置选择集B - 所有碰撞对象
|
||||
var selectionB = new ModelItemCollection();
|
||||
foreach (var collision in validCollisions)
|
||||
{
|
||||
if (!selectionB.Contains(collision.Item2))
|
||||
{
|
||||
selectionB.Add(collision.Item2);
|
||||
}
|
||||
}
|
||||
snapshotTest.SelectionB.Selection.CopyFrom(selectionB);
|
||||
|
||||
// 添加到文档
|
||||
_documentClash.TestsData.TestsAddCopy(snapshotTest);
|
||||
|
||||
// 运行测试
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var addedTest = _documentClash.TestsData.Tests
|
||||
.FirstOrDefault(t => t.DisplayName == testName) as ClashTest;
|
||||
|
||||
if (addedTest != null)
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(addedTest);
|
||||
LogManager.Info($"创建动画碰撞测试: {testName}, 碰撞数量: {validCollisions.Count}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"运行新测试失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"创建新测试失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 更新主测试记录(避免频繁创建新测试)
|
||||
/// </summary>
|
||||
@ -430,6 +785,9 @@ namespace NavisworksTransport
|
||||
// 尝试访问对象的属性来检查是否有效
|
||||
var displayName = item.DisplayName;
|
||||
var hasGeometry = item.HasGeometry;
|
||||
|
||||
// 额外检查:确保对象没有被释放
|
||||
var boundingBox = item.BoundingBox();
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -811,7 +1169,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新Clash Detective窗口
|
||||
/// 刷新Clash Detective窗口(修复版 - 避免UI阻塞)
|
||||
/// </summary>
|
||||
private void RefreshClashDetectiveWindow()
|
||||
{
|
||||
@ -819,77 +1177,111 @@ namespace NavisworksTransport
|
||||
{
|
||||
LogManager.Info("开始刷新Clash Detective窗口...");
|
||||
|
||||
// 方法1: 通过COM API刷新(如果可用)
|
||||
if (_clashElement != null)
|
||||
// 检查文档是否有效
|
||||
if (Application.ActiveDocument == null)
|
||||
{
|
||||
LogManager.Warning("文档已失效,跳过刷新");
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用后台任务执行,避免UI阻塞
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_clashElement.RunAllTests();
|
||||
LogManager.Info("通过COM API刷新Clash Detective窗口成功");
|
||||
// 方法1: 通过COM API刷新(如果可用)
|
||||
if (_clashElement != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_clashElement.RunAllTests();
|
||||
LogManager.Info("通过COM API刷新Clash Detective窗口成功");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"COM API刷新失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 方法2: 通过.NET API刷新(主要方法)
|
||||
if (_documentClash != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 重新运行我们的测试
|
||||
var currentTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == "动态运输路径碰撞检测");
|
||||
if (currentTest != null && currentTest is ClashTest clashTest)
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(clashTest);
|
||||
LogManager.Info($"通过.NET API刷新测试结果,当前结果数: {clashTest.Children.Count}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Info("动态测试不存在,重新创建...");
|
||||
// 在后台任务中重新创建
|
||||
SetupDynamicClashTest();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($".NET API刷新失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 方法3: 强制重绘视图
|
||||
try
|
||||
{
|
||||
// 使用延迟重绘,避免立即操作
|
||||
System.Threading.Thread.Sleep(100);
|
||||
Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
|
||||
LogManager.Info("强制重绘视图成功");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"视图重绘失败: {ex.Message}");
|
||||
}
|
||||
|
||||
// 方法4: 尝试手动触发Clash Detective UI更新
|
||||
try
|
||||
{
|
||||
// 使用延迟操作,给UI时间处理
|
||||
System.Threading.Thread.Sleep(100);
|
||||
|
||||
// 强制保存和重新加载文档状态
|
||||
var doc = Application.ActiveDocument;
|
||||
if (doc != null && doc.CurrentSelection != null)
|
||||
{
|
||||
var tempSelection = doc.CurrentSelection.SelectedItems;
|
||||
doc.CurrentSelection.Clear();
|
||||
if (tempSelection.Count > 0)
|
||||
{
|
||||
doc.CurrentSelection.CopyFrom(tempSelection);
|
||||
}
|
||||
LogManager.Info("手动触发UI更新成功");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"手动UI更新失败: {ex.Message}");
|
||||
}
|
||||
|
||||
LogManager.Info("Clash Detective窗口刷新完成");
|
||||
|
||||
}
|
||||
catch (ObjectDisposedException ex)
|
||||
{
|
||||
LogManager.Warning($"刷新时对象已释放: {ex.Message}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"COM API刷新失败: {ex.Message}");
|
||||
LogManager.Error($"后台刷新失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 方法2: 通过.NET API刷新(主要方法)
|
||||
if (_documentClash != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 重新运行我们的测试
|
||||
var currentTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == "动态运输路径碰撞检测");
|
||||
if (currentTest != null && currentTest is ClashTest clashTest)
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(clashTest);
|
||||
LogManager.Info($"通过.NET API刷新测试结果,当前结果数: {clashTest.Children.Count}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Info("动态测试不存在,重新创建...");
|
||||
SetupDynamicClashTest();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($".NET API刷新失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 方法3: 强制重绘视图
|
||||
try
|
||||
{
|
||||
Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
|
||||
LogManager.Info("强制重绘视图成功");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"视图重绘失败: {ex.Message}");
|
||||
}
|
||||
|
||||
// 方法4: 尝试手动触发Clash Detective UI更新
|
||||
try
|
||||
{
|
||||
// 强制保存和重新加载文档状态
|
||||
var tempSelection = Application.ActiveDocument.CurrentSelection.SelectedItems;
|
||||
Application.ActiveDocument.CurrentSelection.Clear();
|
||||
if (tempSelection.Count > 0)
|
||||
{
|
||||
Application.ActiveDocument.CurrentSelection.CopyFrom(tempSelection);
|
||||
}
|
||||
LogManager.Info("手动触发UI更新成功");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"手动UI更新失败: {ex.Message}");
|
||||
}
|
||||
|
||||
LogManager.Info("Clash Detective窗口刷新完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"刷新Clash Detective窗口失败: {ex.Message}");
|
||||
LogManager.Error($"刷新Clash Detective窗口启动失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1170,153 +1562,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制显示测试结果(用于调试)
|
||||
/// </summary>
|
||||
public void ForceShowTestResults()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("强制显示测试结果...");
|
||||
|
||||
if (!_isInitialized)
|
||||
{
|
||||
LogManager.Warning("集成未初始化,重新初始化...");
|
||||
Initialize();
|
||||
}
|
||||
|
||||
if (_documentClash == null)
|
||||
{
|
||||
LogManager.Error("无法访问Clash Detective文档");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建一个完整的演示测试
|
||||
CreateDemoTest();
|
||||
|
||||
// 如果有最近的碰撞结果,也创建一个快照
|
||||
if (_currentCollisions.Count > 0)
|
||||
{
|
||||
var collisionResults = _currentCollisions.Select(c => new CollisionResult
|
||||
{
|
||||
ClashGuid = c.Guid,
|
||||
DisplayName = c.DisplayName,
|
||||
Status = c.Status,
|
||||
Item1 = c.Item1,
|
||||
Item2 = c.Item2,
|
||||
Center = c.Center,
|
||||
Distance = c.Distance,
|
||||
CreatedTime = DateTime.Now
|
||||
}).ToList();
|
||||
|
||||
CreateCollisionSnapshot(collisionResults);
|
||||
}
|
||||
|
||||
// 强制刷新显示
|
||||
RefreshClashDetectiveWindow();
|
||||
|
||||
// 记录最终状态
|
||||
LogManager.Info(GetTestStatusInfo());
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"强制显示测试结果失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建演示测试
|
||||
/// </summary>
|
||||
private void CreateDemoTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取一些测试对象,使用更安全的方法
|
||||
var doc = Application.ActiveDocument;
|
||||
var allItems = doc.Models.RootItemDescendantsAndSelf
|
||||
.Where(item => item.HasGeometry)
|
||||
.ToList();
|
||||
|
||||
// 过滤出有效的对象
|
||||
var validItems = new List<ModelItem>();
|
||||
foreach (var item in allItems)
|
||||
{
|
||||
if (IsModelItemValid(item))
|
||||
{
|
||||
validItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info($"找到 {validItems.Count} 个有效的几何对象");
|
||||
|
||||
if (validItems.Count >= 2)
|
||||
{
|
||||
// 创建演示测试
|
||||
var demoTest = new ClashTest();
|
||||
demoTest.DisplayName = "Clash Detective 集成演示";
|
||||
demoTest.TestType = ClashTestType.Hard;
|
||||
demoTest.Tolerance = 0.01;
|
||||
|
||||
// 设置测试选择 - 使用更保守的方法
|
||||
var selectionA = new ModelItemCollection();
|
||||
var selectionB = new ModelItemCollection();
|
||||
|
||||
// 选择A:前几个对象
|
||||
int countA = Math.Min(5, validItems.Count / 2);
|
||||
for (int i = 0; i < countA; i++)
|
||||
{
|
||||
if (IsModelItemValid(validItems[i]))
|
||||
{
|
||||
selectionA.Add(validItems[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 选择B:后几个对象
|
||||
int startB = Math.Max(countA, validItems.Count / 2);
|
||||
int countB = Math.Min(5, validItems.Count - startB);
|
||||
for (int i = 0; i < countB; i++)
|
||||
{
|
||||
int index = startB + i;
|
||||
if (index < validItems.Count && IsModelItemValid(validItems[index]))
|
||||
{
|
||||
selectionB.Add(validItems[index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (selectionA.Count > 0 && selectionB.Count > 0)
|
||||
{
|
||||
demoTest.SelectionA.Selection.CopyFrom(selectionA);
|
||||
demoTest.SelectionB.Selection.CopyFrom(selectionB);
|
||||
|
||||
LogManager.Info($"创建演示测试: A={selectionA.Count}, B={selectionB.Count}");
|
||||
|
||||
// 添加到文档
|
||||
_documentClash.TestsData.TestsAddCopy(demoTest);
|
||||
|
||||
// 重新获取并运行测试
|
||||
var addedTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == "Clash Detective 集成演示");
|
||||
if (addedTest is ClashTest runTest)
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(runTest);
|
||||
LogManager.Info($"演示测试运行完成,结果数量: {runTest.Children.Count}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("没有足够的有效对象来创建演示测试");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning($"有效对象数量不足: {validItems.Count},需要至少2个");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"创建演示测试失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
// 已删除:ForceShowTestResults 和 CreateDemoTest - 不再需要这些已废弃的方法
|
||||
|
||||
/// <summary>
|
||||
/// 清理资源
|
||||
@ -1334,8 +1580,7 @@ namespace NavisworksTransport
|
||||
// 清空结果
|
||||
_currentCollisions.Clear();
|
||||
|
||||
// 清理过多的快照测试(保留最近的5个)
|
||||
CleanupSnapshotTests();
|
||||
// 清理工作:动画结束后统一处理,无需频繁清理
|
||||
|
||||
LogManager.Info("Clash Detective集成清理完成");
|
||||
}
|
||||
@ -1345,38 +1590,9 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理过多的快照测试
|
||||
/// </summary>
|
||||
private void CleanupSnapshotTests()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_documentClash == null)
|
||||
return;
|
||||
// 已删除:ForceCloseClashDetectiveDialogs - 不再需要强制关闭对话框
|
||||
|
||||
// 查找所有快照测试
|
||||
var snapshotTests = _documentClash.TestsData.Tests
|
||||
.Where(t => t.DisplayName.StartsWith("动画碰撞快照_"))
|
||||
.Cast<ClashTest>()
|
||||
.ToList();
|
||||
|
||||
// 如果超过5个,删除最旧的
|
||||
if (snapshotTests.Count > 5)
|
||||
{
|
||||
var testsToRemove = snapshotTests.Take(snapshotTests.Count - 5);
|
||||
foreach (var test in testsToRemove)
|
||||
{
|
||||
_documentClash.TestsData.TestsRemove(test);
|
||||
LogManager.Debug($"已删除旧快照测试: {test.DisplayName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"清理快照测试失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
// 已删除:CleanupSnapshotTests - 不再需要,使用动画结束后汇总
|
||||
|
||||
/// <summary>
|
||||
/// 触发碰撞检测事件
|
||||
|
||||
@ -440,7 +440,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 快速验证集成功能
|
||||
/// 快速验证集成功能(修复版 - 避免UI阻塞)
|
||||
/// </summary>
|
||||
/// <returns>验证是否成功</returns>
|
||||
public static bool QuickValidation()
|
||||
@ -460,26 +460,51 @@ namespace NavisworksTransport
|
||||
// 2. 检查初始化
|
||||
instance.Initialize();
|
||||
|
||||
// 3. 检查基本功能
|
||||
// 3. 检查基本功能(使用异步方式)
|
||||
var doc = NavisApplication.ActiveDocument;
|
||||
if (doc?.Models?.RootItemDescendantsAndSelf != null)
|
||||
{
|
||||
var testItem = doc.Models.RootItemDescendantsAndSelf
|
||||
.FirstOrDefault(item => item.HasGeometry);
|
||||
.Where(item => item != null && item.HasGeometry)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (testItem != null)
|
||||
{
|
||||
var collisions = instance.DetectCollisions(testItem);
|
||||
LogManager.Info($"快速验证成功: 检测到 {collisions.Count} 个碰撞");
|
||||
try
|
||||
{
|
||||
var collisions = instance.DetectCollisions(testItem);
|
||||
LogManager.Info($"快速验证成功: 检测到 {collisions.Count} 个碰撞");
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
LogManager.Warning("快速验证时对象已释放,跳过碰撞检测");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 清理
|
||||
instance.Cleanup();
|
||||
// 4. 清理(异步执行)
|
||||
System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Threading.Thread.Sleep(50); // 给UI线程喘息时间
|
||||
instance.Cleanup();
|
||||
LogManager.Debug("快速验证清理完成");
|
||||
}
|
||||
catch (Exception cleanupEx)
|
||||
{
|
||||
LogManager.Warning($"快速验证清理失败: {cleanupEx.Message}");
|
||||
}
|
||||
});
|
||||
|
||||
LogManager.Info("快速验证完成");
|
||||
return true;
|
||||
}
|
||||
catch (ObjectDisposedException ex)
|
||||
{
|
||||
LogManager.Warning($"快速验证时对象已释放: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"快速验证失败: {ex.Message}");
|
||||
|
||||
@ -1468,74 +1468,6 @@ namespace NavisworksTransport
|
||||
};
|
||||
groupBox.Controls.Add(_animationProgressBar);
|
||||
|
||||
// 测试Clash Detective集成按钮
|
||||
Button testClashDetectiveButton = new Button
|
||||
{
|
||||
Text = "测试Clash Detective集成",
|
||||
Location = new Point(175, 25),
|
||||
Size = new Size(150, 30),
|
||||
Font = new Font("微软雅黑", 8),
|
||||
BackColor = System.Drawing.Color.LightBlue
|
||||
};
|
||||
|
||||
testClashDetectiveButton.Click += (sender, e) =>
|
||||
{
|
||||
GlobalExceptionHandler.SafeExecute(() =>
|
||||
{
|
||||
// 执行快速验证
|
||||
LogManager.Info("开始测试 Clash Detective 集成...");
|
||||
|
||||
bool quickValidation = ClashDetectiveIntegrationTest.QuickValidation();
|
||||
|
||||
if (quickValidation)
|
||||
{
|
||||
// 执行完整测试
|
||||
var testResults = ClashDetectiveIntegrationTest.RunFullIntegrationTest();
|
||||
|
||||
int passedTests = testResults.Count(r => r.IsSuccess);
|
||||
int totalTests = testResults.Count;
|
||||
|
||||
string message = $"测试完成!通过 {passedTests}/{totalTests} 个测试\n\n";
|
||||
|
||||
// 获取当前状态信息
|
||||
var statusInfo = ClashDetectiveIntegration.Instance.GetTestStatusInfo();
|
||||
|
||||
// 强制显示测试结果
|
||||
ClashDetectiveIntegration.Instance.ForceShowTestResults();
|
||||
|
||||
if (passedTests == totalTests)
|
||||
{
|
||||
message += "请检查 Clash Detective 窗口查看测试结果。\n";
|
||||
message += "如果窗口中没有显示测试,请:\n";
|
||||
message += "1. 确认 Clash Detective 窗口已打开\n";
|
||||
message += "2. 查看测试列表中的'动态运输路径碰撞检测'项\n";
|
||||
message += "3. 检查日志文件获取详细信息";
|
||||
|
||||
MessageBox.Show(message, "测试结果", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
message += "部分测试失败,详细信息:\n";
|
||||
foreach (var result in testResults.Where(r => !r.IsSuccess))
|
||||
{
|
||||
message += $"- {result.TestName}: {result.Message}\n";
|
||||
}
|
||||
message += "\n详细日志请查看日志文件";
|
||||
|
||||
MessageBox.Show(message, "测试结果", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
|
||||
// 显示状态信息
|
||||
LogManager.Info(statusInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("快速验证失败,请检查日志了解详情", "测试失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}, "测试Clash Detective集成");
|
||||
};
|
||||
|
||||
groupBox.Controls.Add(testClashDetectiveButton);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -346,6 +346,18 @@ namespace NavisworksTransport
|
||||
SetState(AnimationState.Finished); // 标记为完成
|
||||
AnimationCompleted?.Invoke(this, EventArgs.Empty); // 触发旧版完成事件
|
||||
LogManager.Info("动画播放完成");
|
||||
|
||||
// 动画结束后创建最终碰撞结果汇总(安全模式)
|
||||
try
|
||||
{
|
||||
LogManager.Info("开始执行碰撞结果汇总...");
|
||||
ClashDetectiveIntegration.Instance.CreateFinalCollisionSummary();
|
||||
LogManager.Info("碰撞结果汇总完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"碰撞汇总执行失败: {ex.GetType().Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -583,7 +595,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用 Clash Detective 集成进行碰撞检测和高亮显示
|
||||
/// 使用 Clash Detective 集成进行碰撞检测并在运行时显示结果
|
||||
/// </summary>
|
||||
private void CheckAndHighlightCollisionsWithClashDetective()
|
||||
{
|
||||
@ -598,10 +610,16 @@ namespace NavisworksTransport
|
||||
// 高亮显示碰撞对象
|
||||
ClashDetectiveIntegration.Instance.HighlightCollisions(collisionResults);
|
||||
|
||||
// 触发碰撞检测事件
|
||||
// 缓存碰撞结果,动画结束后统一处理
|
||||
if (collisionResults.Count > 0)
|
||||
{
|
||||
// 缓存碰撞结果
|
||||
ClashDetectiveIntegration.Instance.CreateCollisionSnapshot(collisionResults);
|
||||
|
||||
// 触发碰撞检测事件
|
||||
OnCollisionDetected(new CollisionDetectedEventArgs(collisionResults));
|
||||
|
||||
LogManager.Info($"检测到 {collisionResults.Count} 个碰撞,已缓存结果");
|
||||
}
|
||||
|
||||
LogManager.Debug($"碰撞检测完成: {collisionResults.Count} 个碰撞");
|
||||
@ -609,9 +627,6 @@ namespace NavisworksTransport
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"碰撞检测失败: {ex.Message}");
|
||||
|
||||
// 如果新方法失败,回退到简化版本
|
||||
CheckAndHighlightCollisions();
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,48 +677,7 @@ namespace NavisworksTransport
|
||||
CollisionDetected?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查并高亮碰撞(简化版本)
|
||||
/// </summary>
|
||||
private void CheckAndHighlightCollisions()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 简化的碰撞检测:检查动画对象是否与其他对象的包围盒相交
|
||||
var doc = NavisApplication.ActiveDocument;
|
||||
var animatedBoundingBox = _animatedObject.BoundingBox();
|
||||
|
||||
// 获取所有其他有几何体的对象
|
||||
var allItems = doc.Models.RootItemDescendantsAndSelf
|
||||
.Where(item => item.HasGeometry && !item.Equals(_animatedObject))
|
||||
.ToList();
|
||||
|
||||
var collidingItems = new ModelItemCollection();
|
||||
|
||||
foreach (var item in allItems)
|
||||
{
|
||||
var itemBoundingBox = item.BoundingBox();
|
||||
if (BoundingBoxesIntersect(animatedBoundingBox, itemBoundingBox))
|
||||
{
|
||||
collidingItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
// 清除之前的高亮
|
||||
doc.Models.ResetAllTemporaryMaterials();
|
||||
|
||||
// 高亮碰撞对象(红色)
|
||||
if (collidingItems.Count > 0)
|
||||
{
|
||||
doc.Models.OverrideTemporaryColor(collidingItems, Color.Red);
|
||||
LogManager.Debug($"检测到 {collidingItems.Count} 处碰撞");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Debug($"碰撞检测更新失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
// 已删除:CheckAndHighlightCollisions - 使用Clash Detective集成代替
|
||||
|
||||
/// <summary>
|
||||
/// 检查两个包围盒是否相交
|
||||
|
||||
Loading…
Reference in New Issue
Block a user