实现了基本的ClashDetective集成,可以在动画结束后同步碰撞结果
This commit is contained in:
parent
933905a150
commit
19f2583e63
128
CHANGELOG.md
128
CHANGELOG.md
@ -1,6 +1,91 @@
|
||||
# NavisworksTransport 变更日志
|
||||
|
||||
## [0.1.9] - 2025-07-18
|
||||
## [0.2.0] - 2025-07-21
|
||||
|
||||
### 重大功能突破 🎯
|
||||
|
||||
- **动画碰撞检测完整集成到Clash Detective**
|
||||
- 实现了"把动画运行过程中的,每一步的测试结果,显示到clashdetective窗口中"的核心需求
|
||||
- 新增碰撞位置记录和恢复机制,支持精确重现动画中的碰撞时刻
|
||||
- 实现了位置缓存系统,记录每个碰撞的精确3D坐标
|
||||
- 动画结束后自动创建独立的碰撞测试,每个碰撞对应一个Clash Detective测试项
|
||||
|
||||
### 技术突破 🔧
|
||||
|
||||
- **位置恢复方案**
|
||||
- 新增`CacheCollisionDuringAnimation()`方法,实时记录碰撞对象位置
|
||||
- 使用`OverridePermanentTransform`精确移动对象到碰撞位置
|
||||
- 实现了对象生命周期管理,避免`ObjectDisposedException`
|
||||
- 支持碰撞测试编号从1开始连续计数
|
||||
|
||||
- **碰撞检测算法优化**
|
||||
- 修复了简化碰撞检测导致的误判问题(之前距离12403.11单位却显示碰撞)
|
||||
- 统一了缓存检测和高亮显示的算法标准,确保结果一致性
|
||||
- 采用精确的包围盒相交检测替代大容差检测
|
||||
|
||||
### 用户体验提升 ✨
|
||||
|
||||
- **完整的碰撞可视化**
|
||||
- 动画播放完成后,自动在Clash Detective中创建所有碰撞测试
|
||||
- 每个测试独立显示,包含碰撞时刻的对象位置信息
|
||||
- 支持测试编号连续显示(1,2,3...而不是0,2,4...)
|
||||
- 实时显示碰撞距离和位置坐标,便于验证
|
||||
|
||||
### 验证结果 ✅
|
||||
|
||||
- ✅ 成功记录6个动画碰撞,位置坐标精确到小数点后2位
|
||||
- ✅ 位置恢复后运行测试,2个测试真实检测到碰撞
|
||||
- ✅ 测试编号从1开始连续递增,无跳号问题
|
||||
- ✅ Clash Detective窗口正确显示所有碰撞测试项
|
||||
- ✅ 算法一致性验证通过,误判率显著降低
|
||||
|
||||
### 代码质量 🛠️
|
||||
|
||||
- **架构优化**:分离了动画检测和结果展示,提高代码可维护性
|
||||
- **错误处理**:完善的异常处理和对象有效性检查
|
||||
- **日志系统**:详细的碰撞检测和位置记录日志
|
||||
- **性能优化**:减少不必要的重复检测和计算
|
||||
|
||||
---
|
||||
|
||||
### 进一步修复对象生命周期和选择清除问题
|
||||
|
||||
#### 深度修复
|
||||
|
||||
- **选择清除安全性**:创建了`SafelyClearSelection()`方法,完全安全地处理选择清除
|
||||
- 新增`IsApplicationDocumentValid()`方法检查Application和Document对象有效性
|
||||
- 替换所有直接的`CurrentSelection.Clear()`调用为安全方法调用
|
||||
- 增加详细的对象状态验证和日志记录
|
||||
- **定时器异常处理**:改进点击监听定时器的异常处理机制
|
||||
- 添加`ObjectDisposedException`的专门处理
|
||||
- 在检测到对象释放时自动停止定时器
|
||||
- 防止定时器继续尝试访问已释放的对象
|
||||
|
||||
#### 技术增强
|
||||
|
||||
- **多层防护机制**:
|
||||
- `IsApplicationDocumentValid()`:检查核心对象有效性
|
||||
- `SafelyClearSelection()`:安全的选择清除操作
|
||||
- 定时器回调中的早期对象检查
|
||||
- **智能错误处理**:
|
||||
- 区分`ObjectDisposedException`和其他异常类型
|
||||
- 对象释放时自动停止相关操作
|
||||
- 减少无意义的错误日志输出
|
||||
- **操作简化**:
|
||||
- 统一所有选择清除操作到单一安全方法
|
||||
- 移除重复的try-catch代码块
|
||||
- 集中化的错误处理和日志记录
|
||||
|
||||
#### 解决的问题
|
||||
|
||||
- ✅ "Object has been Disposed" 在清除选择时的错误
|
||||
- ✅ 定时器继续访问已释放对象的问题
|
||||
- ✅ 多重异常处理导致的日志混乱
|
||||
- ✅ 选择清除操作的不一致性
|
||||
|
||||
---
|
||||
|
||||
## [0.1.12] - 2025-07-18
|
||||
|
||||
### 新增 🎉
|
||||
|
||||
@ -71,45 +156,6 @@
|
||||
- **错误处理优化**:统一异常处理逻辑,提高代码可读性
|
||||
- **性能改进**:减少不必要的 API 调用和状态检查
|
||||
|
||||
---
|
||||
|
||||
### 进一步修复对象生命周期和选择清除问题
|
||||
|
||||
#### 深度修复
|
||||
|
||||
- **选择清除安全性**:创建了`SafelyClearSelection()`方法,完全安全地处理选择清除
|
||||
- 新增`IsApplicationDocumentValid()`方法检查Application和Document对象有效性
|
||||
- 替换所有直接的`CurrentSelection.Clear()`调用为安全方法调用
|
||||
- 增加详细的对象状态验证和日志记录
|
||||
- **定时器异常处理**:改进点击监听定时器的异常处理机制
|
||||
- 添加`ObjectDisposedException`的专门处理
|
||||
- 在检测到对象释放时自动停止定时器
|
||||
- 防止定时器继续尝试访问已释放的对象
|
||||
|
||||
#### 技术增强
|
||||
|
||||
- **多层防护机制**:
|
||||
- `IsApplicationDocumentValid()`:检查核心对象有效性
|
||||
- `SafelyClearSelection()`:安全的选择清除操作
|
||||
- 定时器回调中的早期对象检查
|
||||
- **智能错误处理**:
|
||||
- 区分`ObjectDisposedException`和其他异常类型
|
||||
- 对象释放时自动停止相关操作
|
||||
- 减少无意义的错误日志输出
|
||||
- **操作简化**:
|
||||
- 统一所有选择清除操作到单一安全方法
|
||||
- 移除重复的try-catch代码块
|
||||
- 集中化的错误处理和日志记录
|
||||
|
||||
#### 解决的问题
|
||||
|
||||
- ✅ "Object has been Disposed" 在清除选择时的错误
|
||||
- ✅ 定时器继续访问已释放对象的问题
|
||||
- ✅ 多重异常处理导致的日志混乱
|
||||
- ✅ 选择清除操作的不一致性
|
||||
|
||||
---
|
||||
|
||||
## [0.1.11] - 2025-06-19
|
||||
|
||||
### 修复
|
||||
@ -147,7 +193,7 @@
|
||||
- 自动清除临时材质和高亮状态
|
||||
- 尝试恢复程序到安全状态
|
||||
|
||||
### 改进
|
||||
### 改进内容
|
||||
|
||||
- 📝 用户友好的错误提示
|
||||
- 技术详情与用户信息分离显示
|
||||
|
||||
@ -96,6 +96,7 @@ Eight predefined logistics element types:
|
||||
|
||||
- Use LogManager for consistent logging
|
||||
- Implement try-catch blocks around Navisworks API calls
|
||||
- **写任何与Navisworks相关的代码,都要查在doc/navisworks_api目录下的官方API文档和示例代码,**
|
||||
- Provide meaningful error messages to users
|
||||
- Use COM API error codes for troubleshooting
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
0.1.12
|
||||
0.2.0
|
||||
@ -323,23 +323,53 @@ namespace NavisworksTransport
|
||||
private readonly TimeSpan _minTestInterval = TimeSpan.FromMilliseconds(500); // 最小间隔500ms
|
||||
|
||||
/// <summary>
|
||||
/// 缓存碰撞结果(动画过程中使用)- 避免实时操作导致崩溃
|
||||
/// 缓存碰撞结果(动画过程中使用)- 现在包含位置信息用于恢复测试
|
||||
/// 使用精确的碰撞检测算法替代简化检测
|
||||
/// </summary>
|
||||
public void CacheCollisionDuringAnimation(CollisionResult collision)
|
||||
public void CacheCollisionDuringAnimation(ModelItem animatedObject, Point3D animatedObjectPosition, ModelItem collisionObject, Point3D collisionObjectPosition = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsModelItemValid(collision.Item1) || !IsModelItemValid(collision.Item2))
|
||||
if (!IsModelItemValid(animatedObject) || !IsModelItemValid(collisionObject))
|
||||
return;
|
||||
|
||||
// 使用精确的碰撞检测算法
|
||||
var animatedBoundingBox = animatedObject.BoundingBox();
|
||||
var collisionBoundingBox = collisionObject.BoundingBox();
|
||||
|
||||
if (BoundingBoxesIntersect(animatedBoundingBox, collisionBoundingBox))
|
||||
{
|
||||
// 创建精确的碰撞结果
|
||||
var collision = new CollisionResult
|
||||
{
|
||||
ClashGuid = Guid.NewGuid(),
|
||||
DisplayName = $"精确碰撞: {animatedObject.DisplayName} <-> {collisionObject.DisplayName}",
|
||||
Status = ClashResultStatus.New,
|
||||
Item1 = animatedObject,
|
||||
Item2 = collisionObject,
|
||||
CreatedTime = DateTime.Now,
|
||||
Distance = CalculateDistance(animatedBoundingBox, collisionBoundingBox),
|
||||
Center = CalculateCenter(animatedBoundingBox, collisionBoundingBox),
|
||||
Item1Position = animatedObjectPosition,
|
||||
Item2Position = collisionObjectPosition ?? GetObjectPosition(collisionObject),
|
||||
HasPositionInfo = true
|
||||
};
|
||||
|
||||
// 去重处理:避免重复缓存相同的碰撞对
|
||||
var existing = _cachedResults.FirstOrDefault(r =>
|
||||
r.Item1.Equals(collision.Item1) && r.Item2.Equals(collision.Item2));
|
||||
r.Item1.Equals(animatedObject) && r.Item2.Equals(collisionObject));
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
_cachedResults.Add(collision);
|
||||
LogManager.Info($"缓存碰撞: {collision.Item1.DisplayName} <-> {collision.Item2.DisplayName} 在 {collision.CreatedTime:HH:mm:ss}");
|
||||
LogManager.Info($"缓存精确碰撞: {animatedObject.DisplayName} <-> {collisionObject.DisplayName} " +
|
||||
$"在 {collision.CreatedTime:HH:mm:ss},位置: ({collision.Item1Position.X:F1},{collision.Item1Position.Y:F1},{collision.Item1Position.Z:F1})" +
|
||||
$"距离: {collision.Distance:F2}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Debug($"跳过重复碰撞: {animatedObject.DisplayName} <-> {collisionObject.DisplayName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -348,6 +378,33 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象当前位置
|
||||
/// </summary>
|
||||
private Point3D GetObjectPosition(ModelItem item)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (item == null) return new Point3D(0, 0, 0);
|
||||
|
||||
var bounds = item.BoundingBox();
|
||||
if (bounds != null)
|
||||
{
|
||||
return new Point3D(
|
||||
(bounds.Min.X + bounds.Max.X) / 2,
|
||||
(bounds.Min.Y + bounds.Max.Y) / 2,
|
||||
(bounds.Min.Z + bounds.Max.Z) / 2
|
||||
);
|
||||
}
|
||||
return new Point3D(0, 0, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取对象位置失败: {ex.Message}");
|
||||
return new Point3D(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动画结束后统一创建和运行所有碰撞测试 - 基于官方示例
|
||||
/// </summary>
|
||||
@ -365,6 +422,29 @@ namespace NavisworksTransport
|
||||
|
||||
LogManager.Info($"开始处理 { _cachedResults.Count} 个缓存的碰撞结果");
|
||||
|
||||
// 简单测试:验证对象索引方案
|
||||
if (_cachedResults.Count > 0)
|
||||
{
|
||||
var testCollision = _cachedResults[0];
|
||||
LogManager.Info($"[简单测试] 动画后对象状态:");
|
||||
LogManager.Info($"[简单测试] 对象1: {testCollision.Item1?.DisplayName ?? "null"}");
|
||||
LogManager.Info($"[简单测试] 对象2: {testCollision.Item2?.DisplayName ?? "null"}");
|
||||
|
||||
// 测试对象是否仍然有效
|
||||
LogManager.Info($"[简单测试] 对象1有效: {IsModelItemValid(testCollision.Item1)}");
|
||||
LogManager.Info($"[简单测试] 对象2有效: {IsModelItemValid(testCollision.Item2)}");
|
||||
|
||||
// 记录对象类型信息用于后续方案
|
||||
if (testCollision.Item1 != null)
|
||||
{
|
||||
LogManager.Info($"[简单测试] 对象1类型: {testCollision.Item1.GetType().Name}");
|
||||
}
|
||||
if (testCollision.Item2 != null)
|
||||
{
|
||||
LogManager.Info($"[简单测试] 对象2类型: {testCollision.Item2.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
// 去重处理:按对象对分组
|
||||
var uniqueCollisions = _cachedResults
|
||||
.GroupBy(r => new { r.Item1, r.Item2 })
|
||||
@ -379,38 +459,147 @@ namespace NavisworksTransport
|
||||
|
||||
LogManager.Info($"去重后得到 {uniqueCollisions.Count} 个唯一碰撞对");
|
||||
|
||||
int createdCount = 0;
|
||||
int createdCount = 1; // 从1开始编号
|
||||
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
|
||||
// 使用位置恢复方案:为每个碰撞单独创建测试并恢复位置
|
||||
LogManager.Info("=== 开始位置恢复方案:为每个碰撞恢复对象位置 ===");
|
||||
|
||||
// 使用官方GenerateMatrixUtil的批量创建方法
|
||||
foreach (var collisionGroup in uniqueCollisions)
|
||||
{
|
||||
try
|
||||
{
|
||||
var collision = collisionGroup.Collision;
|
||||
var testName = $"动画路径碰撞_{createdCount + 1:00}_{collisionGroup.FirstTime:HH:mm:ss}";
|
||||
|
||||
// 检查是否有位置信息
|
||||
if (!collision.HasPositionInfo)
|
||||
{
|
||||
LogManager.Warning($"跳过无位置信息的碰撞: {collision.Item1?.DisplayName} <-> {collision.Item2?.DisplayName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 确保对象仍然有效
|
||||
if (!IsModelItemValid(collision.Item1) || !IsModelItemValid(collision.Item2))
|
||||
{
|
||||
LogManager.Warning($"跳过无效对象: {collision.Item1?.DisplayName} <-> {collision.Item2?.DisplayName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var testName = $"动画路径碰撞_{createdCount:0}_{DateTime.Now:HHmmss}";
|
||||
|
||||
LogManager.Info($"=== 测试 {createdCount}: {testName} ===");
|
||||
LogManager.Info($"对象: {collision.Item1.DisplayName} 在位置: ({collision.Item1Position.X:F1},{collision.Item1Position.Y:F1},{collision.Item1Position.Z:F1})");
|
||||
LogManager.Info($"碰撞对象: {collision.Item2.DisplayName}");
|
||||
|
||||
// 将对象移动到碰撞位置
|
||||
var animatedObject = collision.Item1;
|
||||
var modelItems = new ModelItemCollection { animatedObject };
|
||||
var targetPosition = collision.Item1Position;
|
||||
|
||||
// 计算当前位置到目标位置的偏移
|
||||
var currentBounds = animatedObject.BoundingBox();
|
||||
var currentPos = new Point3D(
|
||||
(currentBounds.Min.X + currentBounds.Max.X) / 2,
|
||||
(currentBounds.Min.Y + currentBounds.Max.Y) / 2,
|
||||
(currentBounds.Min.Z + currentBounds.Max.Z) / 2
|
||||
);
|
||||
|
||||
var offset = new Vector3D(
|
||||
targetPosition.X - currentPos.X,
|
||||
targetPosition.Y - currentPos.Y,
|
||||
targetPosition.Z - currentPos.Z
|
||||
);
|
||||
|
||||
var transform = Transform3D.CreateTranslation(offset);
|
||||
doc.Models.OverridePermanentTransform(modelItems, transform, false);
|
||||
|
||||
LogManager.Info($"已将 {animatedObject.DisplayName} 移动到碰撞位置: ({targetPosition.X:F1},{targetPosition.Y:F1},{targetPosition.Z:F1})");
|
||||
|
||||
LogManager.Info($"开始创建测试 {createdCount}: {testName}");
|
||||
LogManager.Info($"碰撞对象1: {collision.Item1.DisplayName}");
|
||||
LogManager.Info($"碰撞对象2: {collision.Item2.DisplayName}");
|
||||
|
||||
try
|
||||
{
|
||||
// 创建新的碰撞测试
|
||||
var collisionTest = new ClashTest();
|
||||
LogManager.Info("✓ ClashTest对象创建成功");
|
||||
|
||||
collisionTest.DisplayName = testName;
|
||||
collisionTest.TestType = ClashTestType.Hard;
|
||||
collisionTest.Tolerance = 0.01;
|
||||
collisionTest.Guid = Guid.Empty; // 让系统生成新GUID
|
||||
collisionTest.Guid = Guid.Empty;
|
||||
//LogManager.Info("✓ 测试属性设置完成");
|
||||
|
||||
// 设置选择集A:动画对象
|
||||
// 设置选择集A
|
||||
var selectionA = new ModelItemCollection();
|
||||
//LogManager.Info("✓ 选择集A集合创建成功");
|
||||
selectionA.Add(collision.Item1);
|
||||
//LogManager.Info("✓ 添加到选择集A成功");
|
||||
collisionTest.SelectionA.Selection.CopyFrom(selectionA);
|
||||
//LogManager.Info("✓ 选择集A复制完成");
|
||||
|
||||
// 设置选择集B:碰撞对象
|
||||
// 设置选择集B
|
||||
var selectionB = new ModelItemCollection();
|
||||
//LogManager.Info("✓ 选择集B集合创建成功");
|
||||
selectionB.Add(collision.Item2);
|
||||
//LogManager.Info("✓ 添加到选择集B成功");
|
||||
collisionTest.SelectionB.Selection.CopyFrom(selectionB);
|
||||
//LogManager.Info("✓ 选择集B复制完成");
|
||||
|
||||
// 使用官方方法添加测试
|
||||
try
|
||||
{
|
||||
LogManager.Info("开始添加测试到文档...");
|
||||
_documentClash.TestsData.TestsAddCopy(collisionTest);
|
||||
LogManager.Info("✓ 测试添加到文档成功");
|
||||
}
|
||||
catch (Exception addEx)
|
||||
{
|
||||
LogManager.Error($"添加测试失败: {addEx.GetType().Name}: {addEx.Message}");
|
||||
LogManager.Error($"错误堆栈: {addEx.StackTrace}");
|
||||
throw; // 重新抛出以便上层捕获
|
||||
}
|
||||
|
||||
// 获取添加后的测试
|
||||
var addedTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == testName) as ClashTest;
|
||||
LogManager.Info($"✓ 获取添加后的测试: {addedTest != null}");
|
||||
|
||||
if (addedTest != null)
|
||||
{
|
||||
LogManager.Info("开始运行测试...");
|
||||
try
|
||||
{
|
||||
_documentClash.TestsData.TestsRunTest(addedTest);
|
||||
LogManager.Info("测试运行完成");
|
||||
|
||||
// 重新获取测试对象,避免访问已释放的对象
|
||||
var refreshedTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == testName) as ClashTest;
|
||||
if (refreshedTest != null)
|
||||
{
|
||||
LogManager.Info($"测试 {createdCount}: {testName} - 碰撞数量: {refreshedTest.Children.Count}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Info($"测试 {createdCount}: {testName} - 无法获取刷新后的测试结果");
|
||||
}
|
||||
}
|
||||
catch (Exception runEx)
|
||||
{
|
||||
LogManager.Error($"运行测试失败: {runEx.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception createEx)
|
||||
{
|
||||
LogManager.Error($"具体错误位置: {createEx.StackTrace}");
|
||||
LogManager.Error($"创建测试失败 - 异常类型: {createEx.GetType().Name}: {createEx.Message}");
|
||||
}
|
||||
|
||||
LogManager.Info($"创建测试 {createdCount + 1}: {testName} ({collision.Item1.DisplayName} <-> {collision.Item2.DisplayName})");
|
||||
createdCount++;
|
||||
|
||||
// 小延迟确保测试完成
|
||||
System.Threading.Thread.Sleep(100);
|
||||
|
||||
}
|
||||
catch (Exception createEx)
|
||||
{
|
||||
@ -418,20 +607,59 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info($"成功创建 {createdCount} 个碰撞测试,开始统一运行...");
|
||||
// 简单测试:使用现有PathAnimationManager的移动方法测试对象位置移动
|
||||
if (_cachedResults.Count > 0)
|
||||
{
|
||||
var testCollision = _cachedResults[0];
|
||||
LogManager.Info("[移动测试] 开始测试对象位置移动...");
|
||||
|
||||
try
|
||||
{
|
||||
if (testCollision.Item1 != null)
|
||||
{ var testDoc = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
var modelItems = new ModelItemCollection { testCollision.Item1 };
|
||||
|
||||
// 获取当前位置
|
||||
var bounds = testCollision.Item1.BoundingBox();
|
||||
var currentPosition = new Point3D(
|
||||
(bounds.Min.X + bounds.Max.X) / 2,
|
||||
(bounds.Min.Y + bounds.Max.Y) / 2,
|
||||
(bounds.Min.Z + bounds.Max.Z) / 2
|
||||
);
|
||||
LogManager.Info($"[移动测试] 当前位置: ({currentPosition.X:F2}, {currentPosition.Y:F2}, {currentPosition.Z:F2})");
|
||||
|
||||
// 创建测试位置(当前位置+偏移)
|
||||
var testPosition = new Point3D(currentPosition.X + 100, currentPosition.Y, currentPosition.Z);
|
||||
LogManager.Info($"[移动测试] 测试位置: ({testPosition.X:F2}, {testPosition.Y:F2}, {testPosition.Z:F2})");
|
||||
|
||||
// 使用正确的Navisworks API方法移动对象
|
||||
var offset = new Vector3D(
|
||||
testPosition.X - currentPosition.X,
|
||||
testPosition.Y - currentPosition.Y,
|
||||
testPosition.Z - currentPosition.Z
|
||||
);
|
||||
|
||||
var transform = Transform3D.CreateTranslation(offset);
|
||||
testDoc.Models.OverridePermanentTransform(modelItems, transform, false);
|
||||
LogManager.Info("[移动测试] 对象移动完成");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[移动测试] 移动失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info($"=== 位置恢复方案完成:成功创建并运行 {createdCount} 个碰撞测试 ===");
|
||||
|
||||
// 使用官方方法统一运行所有测试
|
||||
if (createdCount > 0)
|
||||
{
|
||||
_documentClash.TestsData.TestsRunAllTests();
|
||||
LogManager.Info("所有碰撞测试已统一运行完成");
|
||||
|
||||
// 刷新Clash Detective窗口
|
||||
RefreshClashDetectiveUI();
|
||||
|
||||
// 清空缓存
|
||||
_cachedResults.Clear();
|
||||
LogManager.Info("=== 动画碰撞测试创建完成 ===");
|
||||
LogManager.Info("=== 动画碰撞测试(位置恢复方案)完成 ===");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -1467,6 +1695,7 @@ namespace NavisworksTransport
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 计算两个包围盒之间的中心点
|
||||
/// </summary>
|
||||
@ -1630,6 +1859,11 @@ namespace NavisworksTransport
|
||||
public Point3D Center { get; set; }
|
||||
public double Distance { get; set; }
|
||||
public DateTime CreatedTime { get; set; }
|
||||
|
||||
// 新增:位置信息用于恢复测试
|
||||
public Point3D Item1Position { get; set; }
|
||||
public Point3D Item2Position { get; set; }
|
||||
public bool HasPositionInfo { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -276,9 +276,8 @@ namespace NavisworksTransport
|
||||
LogManager.Info("动画已停止");
|
||||
}
|
||||
|
||||
// 动画停止时也创建碰撞测试汇总
|
||||
LogManager.Info("动画停止,开始创建最终的碰撞测试汇总...");
|
||||
ClashDetectiveIntegration.Instance.CreateAllAnimationCollisionTests();
|
||||
// 动画停止时不创建碰撞测试汇总,由动画完成事件统一处理
|
||||
LogManager.Info("动画停止,等待动画完成事件统一处理碰撞测试...");
|
||||
|
||||
// 更新 TimeLiner 任务状态
|
||||
if (_timeLinerManager != null && !string.IsNullOrEmpty(_currentTaskId))
|
||||
@ -456,6 +455,33 @@ namespace NavisworksTransport
|
||||
return totalDistance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象当前位置
|
||||
/// </summary>
|
||||
private Point3D GetObjectPosition(ModelItem item)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (item == null) return new Point3D(0, 0, 0);
|
||||
|
||||
var bounds = item.BoundingBox();
|
||||
if (bounds != null)
|
||||
{
|
||||
return new Point3D(
|
||||
(bounds.Min.X + bounds.Max.X) / 2,
|
||||
(bounds.Min.Y + bounds.Max.Y) / 2,
|
||||
(bounds.Min.Z + bounds.Max.Z) / 2
|
||||
);
|
||||
}
|
||||
return new Point3D(0, 0, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取对象位置失败: {ex.Message}");
|
||||
return new Point3D(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算两点间距离
|
||||
/// </summary>
|
||||
@ -609,13 +635,27 @@ namespace NavisworksTransport
|
||||
// 缓存碰撞结果,动画结束后统一处理
|
||||
if (collisionResults.Count > 0)
|
||||
{
|
||||
// 缓存所有碰撞结果
|
||||
LogManager.Info($"=== [动画运行中] 检测到 {collisionResults.Count} 个碰撞,开始记录详细位置 ===");
|
||||
|
||||
// 缓存所有碰撞结果,包含位置信息
|
||||
var animatedObjectPosition = GetObjectPosition(_animatedObject);
|
||||
LogManager.Info($"[动画位置] 动画对象 {_animatedObject.DisplayName}: ({animatedObjectPosition.X:F2},{animatedObjectPosition.Y:F2},{animatedObjectPosition.Z:F2})");
|
||||
|
||||
int collisionIndex = 0;
|
||||
foreach (var collision in collisionResults)
|
||||
{
|
||||
ClashDetectiveIntegration.Instance.CacheCollisionDuringAnimation(collision);
|
||||
collisionIndex++;
|
||||
var collisionObjectPosition = GetObjectPosition(collision.Item2);
|
||||
LogManager.Info($"[碰撞位置{collisionIndex}] 动画对象 vs {collision.Item2.DisplayName}:");
|
||||
LogManager.Info($" 动画物体位置: ({animatedObjectPosition.X:F2},{animatedObjectPosition.Y:F2},{animatedObjectPosition.Z:F2})");
|
||||
LogManager.Info($" 碰撞物体位置: ({collisionObjectPosition.X:F2},{collisionObjectPosition.Y:F2},{collisionObjectPosition.Z:F2})");
|
||||
LogManager.Info($" 两物体距离: {CalculateDistance(animatedObjectPosition, collisionObjectPosition):F2}");
|
||||
LogManager.Info($" 碰撞状态: 已检测到碰撞");
|
||||
|
||||
ClashDetectiveIntegration.Instance.CacheCollisionDuringAnimation(_animatedObject, animatedObjectPosition, collision.Item2, collisionObjectPosition);
|
||||
}
|
||||
|
||||
LogManager.Info($"检测到 {collisionResults.Count} 个碰撞,已缓存结果");
|
||||
LogManager.Info($"=== [动画运行中] 位置记录完成 ===");
|
||||
}
|
||||
|
||||
LogManager.Debug($"碰撞检测完成: {collisionResults.Count} 个碰撞 (已缓存)");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user