From bd7eeb3d4646316c07b7982f0aaac82e9356f511 Mon Sep 17 00:00:00 2001
From: tian <11429339@qq.com>
Date: Mon, 13 Oct 2025 19:14:46 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=B7=AF=E5=BE=84=E9=A2=84?=
=?UTF-8?q?=E8=AE=A1=E7=AE=97=E8=8C=83=E5=9B=B4=E4=B8=8D=E5=AF=B9=E3=80=81?=
=?UTF-8?q?=E7=A2=B0=E6=92=9E=E6=A3=80=E6=B5=8B=E6=8A=A5=E5=91=8A=E5=90=8D?=
=?UTF-8?q?=E5=AD=97=E5=8C=B9=E9=85=8D=E9=94=99=E8=AF=AF=E7=9A=84BUG?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
NavisworksTransportPlugin.csproj | 1 +
.../GenerateCollisionReportCommand.cs | 67 +++++++++-----
src/Core/Animation/PathAnimationManager.cs | 90 +++++++++++++------
src/Utils/ModelItemTransformHelper.cs | 60 +++++++++++++
4 files changed, 167 insertions(+), 51 deletions(-)
create mode 100644 src/Utils/ModelItemTransformHelper.cs
diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj
index f7d2066..53068b9 100644
--- a/NavisworksTransportPlugin.csproj
+++ b/NavisworksTransportPlugin.csproj
@@ -294,6 +294,7 @@
+
diff --git a/src/Commands/GenerateCollisionReportCommand.cs b/src/Commands/GenerateCollisionReportCommand.cs
index 72ba2ee..83ac599 100644
--- a/src/Commands/GenerateCollisionReportCommand.cs
+++ b/src/Commands/GenerateCollisionReportCommand.cs
@@ -275,27 +275,36 @@ namespace NavisworksTransport.Commands
return null;
}
- // 查找最新的物流碰撞检测测试
- var latestTest = documentClash.TestsData.Tests.Cast()
- .Where(t => t.DisplayName.StartsWith("物流碰撞检测_"))
- .OrderByDescending(t => t.DisplayName)
+ // 从动画管理器获取当前路径名称
+ var animationManager = Core.Animation.PathAnimationManager.GetInstance();
+ var currentPathName = animationManager?.PathName;
+
+ if (string.IsNullOrEmpty(currentPathName))
+ {
+ throw new InvalidOperationException("无法获取当前路径名称");
+ }
+
+ // 精确匹配当前路径的测试
+ var matchedTest = documentClash.TestsData.Tests.Cast()
+ .Where(t => t.DisplayName.StartsWith("物流碰撞检测_") &&
+ t.DisplayName.Contains(currentPathName))
+ .OrderByDescending(t => t.DisplayName) // 同一路径可能有多个测试,取最新的
.FirstOrDefault();
- if (latestTest != null)
+ if (matchedTest != null)
{
- LogManager.Debug($"缓存键用测试名称: {latestTest.DisplayName}");
- return latestTest.DisplayName;
+ LogManager.Info($"找到当前路径的测试: {matchedTest.DisplayName}");
+ return matchedTest.DisplayName;
}
else
{
- LogManager.Info("未找到物流碰撞检测测试,无法生成缓存键");
- return null;
+ throw new InvalidOperationException($"未找到路径 '{currentPathName}' 的碰撞测试");
}
}
catch (Exception ex)
{
LogManager.Error($"获取测试名称作为缓存键失败: {ex.Message}");
- return null;
+ throw; // 让错误暴露出来
}
}
@@ -337,27 +346,37 @@ namespace NavisworksTransport.Commands
int totalCollisionCount = 0; // Clash Detective总碰撞数
- // 🔧 修复:只统计最新的物流碰撞检测测试,避免重复累积
- var latestTest = documentClash.TestsData.Tests.Cast()
- .Where(t => t.DisplayName.StartsWith("物流碰撞检测_"))
+ // 从动画管理器获取当前路径名称
+ var animationManager = Core.Animation.PathAnimationManager.GetInstance();
+ var currentPathName = animationManager?.PathName;
+
+ if (string.IsNullOrEmpty(currentPathName))
+ {
+ throw new InvalidOperationException("无法获取当前路径名称");
+ }
+
+ // 精确匹配当前路径的测试
+ var matchedTest = documentClash.TestsData.Tests.Cast()
+ .Where(t => t.DisplayName.StartsWith("物流碰撞检测_") &&
+ t.DisplayName.Contains(currentPathName))
.OrderByDescending(t => t.DisplayName)
.FirstOrDefault();
-
- if (latestTest != null)
+
+ if (matchedTest != null)
{
- LogManager.Info($"找到最新的物流路径测试: {latestTest.DisplayName}");
-
- // 提取最新测试的碰撞数据
- var testCollisions = ExtractCollisionsFromTest(latestTest);
+ LogManager.Info($"找到当前路径的测试: {matchedTest.DisplayName}");
+
+ // 提取匹配测试的碰撞数据
+ var testCollisions = ExtractCollisionsFromTest(matchedTest);
allCollisions.AddRange(testCollisions);
-
- // 统计最新测试的碰撞总数
- totalCollisionCount = GetTotalClashResultCountFromTest(latestTest);
- LogManager.Debug($"最新测试 '{latestTest.DisplayName}' 包含 {totalCollisionCount} 个碰撞");
+
+ // 统计匹配测试的碰撞总数
+ totalCollisionCount = GetTotalClashResultCountFromTest(matchedTest);
+ LogManager.Debug($"匹配测试 '{matchedTest.DisplayName}' 包含 {totalCollisionCount} 个碰撞");
}
else
{
- LogManager.Info("未找到物流碰撞检测测试");
+ throw new InvalidOperationException($"未找到路径 '{currentPathName}' 的碰撞测试");
}
// 去重处理
diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs
index 61ba61c..db104d0 100644
--- a/src/Core/Animation/PathAnimationManager.cs
+++ b/src/Core/Animation/PathAnimationManager.cs
@@ -466,45 +466,81 @@ namespace NavisworksTransport.Core.Animation
// 构建通道缓存
ClashDetectiveIntegration.Instance.BuildChannelObjectsCache();
ClashDetectiveIntegration.BuildAllGeometryItemsCache();
-
+
// 获取所有有几何体的对象
var allItems = NavisApplication.ActiveDocument.Models.RootItemDescendantsAndSelf
.Where(item => item.HasGeometry)
.ToList();
-
+
// 构建排除列表:动画对象本身及其子对象
var excludeList = new ModelItemCollection();
excludeList.AddRange(_animatedObject.DescendantsAndSelf);
-
- // 使用ClashDetectiveIntegration的碰撞检测方法,它会自动排除通道对象
- // 创建一个较大的检测间隙来获取路径范围内所有潜在碰撞对象
- var detectionGap = 100.0; // 100米范围内的对象都视为潜在碰撞对象
-
- // 调用ClashDetectiveIntegration的DetectCollisions方法
- // 该方法内部会自动排除通道对象(通过IsChannelObject方法)
- var collisionResults = ClashDetectiveIntegration.Instance.DetectCollisions(
- _animatedObject,
- excludeList,
- detectionGap
+
+ // 计算路径包围盒
+ var pathBounds = CalculatePathBounds();
+
+ // 计算路径包围盒中心点(模型单位)
+ var pathCenter = new Point3D(
+ (pathBounds.Min.X + pathBounds.Max.X) / 2,
+ (pathBounds.Min.Y + pathBounds.Max.Y) / 2,
+ (pathBounds.Min.Z + pathBounds.Max.Z) / 2
);
-
- // 从碰撞结果中提取唯一的碰撞对象
- var potentialColliders = new HashSet();
- foreach (var result in collisionResults)
+
+ // 计算包围盒对角线长度
+ var diagonal = Math.Sqrt(
+ Math.Pow(pathBounds.Max.X - pathBounds.Min.X, 2) +
+ Math.Pow(pathBounds.Max.Y - pathBounds.Min.Y, 2) +
+ Math.Pow(pathBounds.Max.Z - pathBounds.Min.Z, 2)
+ );
+
+ // 检测半径 = 包围盒对角线的一半(精确覆盖整条路径)
+ var detectionGap = diagonal / 2;
+
+ LogManager.Info($"路径包围盒: Min=({pathBounds.Min.X:F2}, {pathBounds.Min.Y:F2}, {pathBounds.Min.Z:F2}), " +
+ $"Max=({pathBounds.Max.X:F2}, {pathBounds.Max.Y:F2}, {pathBounds.Max.Z:F2})");
+ LogManager.Info($"路径中心: ({pathCenter.X:F2}, {pathCenter.Y:F2}, {pathCenter.Z:F2})");
+ LogManager.Info($"包围盒对角线: {diagonal:F2} 模型单位");
+
+ // 临时移动物体到路径中心,以便在路径范围内检测潜在碰撞对象
+ var offset = ModelItemTransformHelper.MoveItemToPosition(_animatedObject, pathCenter);
+
+ try
{
- if (result.Item2 != null && !potentialColliders.Contains(result.Item2))
+ LogManager.Info($"检测半径: {detectionGap:F2} 模型单位(对角线的一半)");
+
+ // 调用ClashDetectiveIntegration的DetectCollisions方法
+ // 现在物体在路径中心,检测路径长度半径内的对象
+ // 该方法内部会自动排除通道对象(通过IsChannelObject方法)
+ var collisionResults = ClashDetectiveIntegration.Instance.DetectCollisions(
+ _animatedObject,
+ excludeList,
+ detectionGap
+ );
+
+ // 从碰撞结果中提取唯一的碰撞对象
+ var potentialColliders = new HashSet();
+ foreach (var result in collisionResults)
{
- potentialColliders.Add(result.Item2);
+ if (result.Item2 != null && !potentialColliders.Contains(result.Item2))
+ {
+ potentialColliders.Add(result.Item2);
+ }
}
+
+ var finalList = potentialColliders.ToList();
+
+ LogManager.Info($"获取潜在碰撞对象完成: 总对象={allItems.Count}, " +
+ $"排除自身及子对象={excludeList.Count}, " +
+ $"路径沿途潜在碰撞对象={finalList.Count}(已自动排除通道)");
+
+ return finalList;
+ }
+ finally
+ {
+ // 恢复物体到原位置
+ ModelItemTransformHelper.RestoreItemPosition(_animatedObject, offset);
+ LogManager.Info("物体已恢复到原始位置");
}
-
- var finalList = potentialColliders.ToList();
-
- LogManager.Info($"获取潜在碰撞对象完成: 总对象={allItems.Count}, " +
- $"排除自身及子对象={excludeList.Count}, " +
- $"检测范围内潜在碰撞对象={finalList.Count}(已自动排除通道)");
-
- return finalList;
}
catch (Exception ex)
{
diff --git a/src/Utils/ModelItemTransformHelper.cs b/src/Utils/ModelItemTransformHelper.cs
new file mode 100644
index 0000000..9a9a212
--- /dev/null
+++ b/src/Utils/ModelItemTransformHelper.cs
@@ -0,0 +1,60 @@
+using Autodesk.Navisworks.Api;
+
+namespace NavisworksTransport.Utils
+{
+ ///
+ /// ModelItem变换辅助工具
+ /// 提供临时移动和恢复物体位置的通用方法
+ ///
+ public static class ModelItemTransformHelper
+ {
+ ///
+ /// 临时移动物体到指定位置
+ ///
+ /// 要移动的物体
+ /// 目标位置(物体中心)
+ /// 用于恢复的偏移向量
+ public static Vector3D MoveItemToPosition(ModelItem item, Point3D targetPosition)
+ {
+ var doc = Application.ActiveDocument;
+ var modelItems = new ModelItemCollection { item };
+
+ // 计算当前中心位置
+ var currentBounds = item.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);
+
+ return offset;
+ }
+
+ ///
+ /// 恢复物体到原位置
+ ///
+ /// 要恢复的物体
+ /// 原始移动偏移向量
+ public static void RestoreItemPosition(ModelItem item, Vector3D originalOffset)
+ {
+ var doc = Application.ActiveDocument;
+ var modelItems = new ModelItemCollection { item };
+
+ // 反向偏移
+ var restoreOffset = new Vector3D(-originalOffset.X, -originalOffset.Y, -originalOffset.Z);
+ var restoreTransform = Transform3D.CreateTranslation(restoreOffset);
+ doc.Models.OverridePermanentTransform(modelItems, restoreTransform, false);
+ }
+ }
+}