优化ClashDetective集成,减少临时测试创建和删除的性能开销,简化碰撞结果的DisplayName设置
This commit is contained in:
parent
9fac32741e
commit
cdd6ee9319
@ -483,7 +483,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
_currentYaw = ModelItemTransformHelper.GetYawFromTransform(_originalTransform);
|
||||
LogManager.Debug($"[MoveVehicleToPathStart初始化] 当前实际yaw={_currentYaw * 180 / Math.PI:F2}度, _isVirtualVehicle={_isVirtualVehicle}");
|
||||
}
|
||||
|
||||
|
||||
if (pathPoints != null)
|
||||
{
|
||||
_pathPoints = pathPoints;
|
||||
@ -499,7 +499,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
// 计算朝向(使用前两个路径点的方向)
|
||||
double pathDirectionYaw = Math.Atan2(_pathPoints[1].Y - _pathPoints[0].Y, _pathPoints[1].X - _pathPoints[0].X);
|
||||
double yaw;
|
||||
|
||||
|
||||
LogManager.Info($"[移动到起点] 路径方向yaw: {pathDirectionYaw * 180 / Math.PI:F2}度, 角度修正: {_objectRotationCorrection:F1}度");
|
||||
|
||||
// 根据路径类型调整朝向
|
||||
@ -564,7 +564,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
}
|
||||
|
||||
LogManager.Info($"物体已初始化到路径起点并对齐朝向: pos=({startPosition.X:F2},{startPosition.Y:F2},{startPosition.Z:F2}), yaw={yaw:F3}rad, 路径类型={pathTypeName}");
|
||||
|
||||
|
||||
// 打印实际物体的位置和方向
|
||||
if (_animatedObject != null)
|
||||
{
|
||||
@ -719,10 +719,10 @@ namespace NavisworksTransport.Core.Animation
|
||||
if (!manualOverrideActive)
|
||||
{
|
||||
LogManager.Info("=== 构建全局空间索引 ===");
|
||||
|
||||
|
||||
// 🔥 设置移动物体到 ClashDetectiveIntegration,以便从空间索引中排除
|
||||
ClashDetectiveIntegration.SetAnimatedObject(_animatedObject);
|
||||
|
||||
|
||||
spatialIndexManager = SpatialIndexManager.Instance;
|
||||
|
||||
// 使用动画专用的空间索引格子大小配置 - 使用模型单位接口
|
||||
@ -731,9 +731,9 @@ namespace NavisworksTransport.Core.Animation
|
||||
LogManager.Info($"[空间索引] 格子大小: {cellSizeInModelUnits:F2}模型单位 (动画配置)");
|
||||
|
||||
// 检查空间索引是否需要重新构建(格子大小变化或未初始化)
|
||||
bool needRebuild = !spatialIndexManager.IsInitialized ||
|
||||
bool needRebuild = !spatialIndexManager.IsInitialized ||
|
||||
Math.Abs(spatialIndexManager.CellSize - cellSizeInModelUnits) > 0.0001;
|
||||
|
||||
|
||||
if (needRebuild)
|
||||
{
|
||||
LogManager.Info("[空间索引] 空间索引未初始化或格子大小已改变,开始重新构建...");
|
||||
@ -767,15 +767,15 @@ namespace NavisworksTransport.Core.Animation
|
||||
double yawRadians;
|
||||
|
||||
if (isAerialPath)
|
||||
{
|
||||
// === 空中路径:在路径点之间进行线性插值 ===
|
||||
int segmentIndex = FindSegmentForDistance(targetDistance, segmentLengths);
|
||||
if (segmentIndex < 0 || segmentIndex >= segmentLengths.Count)
|
||||
{
|
||||
string subTypeName = _route.PathType == PathType.Rail ? "空轨" : "吊装";
|
||||
LogManager.Warning($"[{subTypeName}路径] 无法找到线段,目标距离:{targetDistance / metersToModelUnits:F2}米");
|
||||
continue;
|
||||
}
|
||||
{
|
||||
// === 空中路径:在路径点之间进行线性插值 ===
|
||||
int segmentIndex = FindSegmentForDistance(targetDistance, segmentLengths);
|
||||
if (segmentIndex < 0 || segmentIndex >= segmentLengths.Count)
|
||||
{
|
||||
string subTypeName = _route.PathType == PathType.Rail ? "空轨" : "吊装";
|
||||
LogManager.Warning($"[{subTypeName}路径] 无法找到线段,目标距离:{targetDistance / metersToModelUnits:F2}米");
|
||||
continue;
|
||||
}
|
||||
double accumulatedLength = segmentLengths.Take(segmentIndex).Sum();
|
||||
double segmentProgress = (targetDistance - accumulatedLength) / segmentLengths[segmentIndex];
|
||||
|
||||
@ -846,14 +846,14 @@ namespace NavisworksTransport.Core.Animation
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// === 地面路径:在边内插值 ===
|
||||
int edgeIndex = FindEdgeForDistance(targetDistance, segmentLengths);
|
||||
if (edgeIndex < 0 || edgeIndex >= _route.Edges.Count)
|
||||
{
|
||||
LogManager.Warning($"无法找到边,目标距离:{targetDistance / metersToModelUnits:F2}米");
|
||||
continue;
|
||||
}
|
||||
{
|
||||
// === 地面路径:在边内插值 ===
|
||||
int edgeIndex = FindEdgeForDistance(targetDistance, segmentLengths);
|
||||
if (edgeIndex < 0 || edgeIndex >= _route.Edges.Count)
|
||||
{
|
||||
LogManager.Warning($"无法找到边,目标距离:{targetDistance / metersToModelUnits:F2}米");
|
||||
continue;
|
||||
}
|
||||
var edge = _route.Edges[edgeIndex];
|
||||
double accumulatedLength = segmentLengths.Take(edgeIndex).Sum();
|
||||
double edgeProgress = (targetDistance - accumulatedLength) / edge.PhysicalLength;
|
||||
@ -941,9 +941,9 @@ namespace NavisworksTransport.Core.Animation
|
||||
|
||||
if (intersects)
|
||||
{
|
||||
LogManager.Debug($"帧 {i} 检测到碰撞: {_animatedObject.DisplayName} <-> {collider.DisplayName}, 距离: {distance:F4},阈值: {safetyMarginInModelUnits:F4}");
|
||||
LogManager.Debug($"移动物体位置: {framePosition.X:F2},{framePosition.Y:F2},{framePosition.Z:F2}");
|
||||
LogManager.Debug($"被撞物体位置:{GetObjectPosition(collider).X:F2},{GetObjectPosition(collider).Y:F2},{GetObjectPosition(collider).Z:F2}");
|
||||
// LogManager.Debug($"帧 {i} 检测到碰撞: {_animatedObject.DisplayName} <-> {collider.DisplayName}, 距离: {distance:F4},阈值: {safetyMarginInModelUnits:F4}");
|
||||
// LogManager.Debug($"移动物体位置: {framePosition.X:F2},{framePosition.Y:F2},{framePosition.Z:F2}");
|
||||
// LogManager.Debug($"被撞物体位置:{GetObjectPosition(collider).X:F2},{GetObjectPosition(collider).Y:F2},{GetObjectPosition(collider).Z:F2}");
|
||||
|
||||
var collisionResult = new CollisionResult
|
||||
{
|
||||
@ -990,7 +990,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
LogManager.Info($"包含碰撞的帧: {framesWithCollision}");
|
||||
LogManager.Info($"总碰撞次数: {totalCollisions}");
|
||||
LogManager.Info($"记录的碰撞结果总数: {_allCollisionResults.Count} 个");
|
||||
|
||||
|
||||
// 🔥 清除移动物体集合
|
||||
ClashDetectiveIntegration.ClearAnimatedObject();
|
||||
}
|
||||
@ -1525,11 +1525,11 @@ namespace NavisworksTransport.Core.Animation
|
||||
if (!_completedCollisionTests.Contains(_currentAnimationHash))
|
||||
{
|
||||
LogManager.Info($"此动画配置首次完成,开始创建碰撞测试汇总(基于 {_allCollisionResults.Count} 个预计算碰撞记录)...");
|
||||
|
||||
|
||||
// 🔥 设置等待光标,避免进度条关闭后的无响应
|
||||
var oldCursor = System.Windows.Input.Mouse.OverrideCursor;
|
||||
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// 🔥 使用用户设置的检测容差(米)
|
||||
@ -1552,7 +1552,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
// 恢复光标
|
||||
System.Windows.Input.Mouse.OverrideCursor = oldCursor;
|
||||
}
|
||||
|
||||
|
||||
_completedCollisionTests.Add(_currentAnimationHash); // 记录此配置已完成碰撞检测
|
||||
LogManager.Info($"碰撞测试汇总已创建并记录,此配置后续播放将跳过碰撞检测");
|
||||
}
|
||||
@ -1954,7 +1954,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
// 我们需要手动计算旋转导致的位置偏移,并补偿
|
||||
|
||||
double deltaYaw = newYaw - _currentYaw;
|
||||
LogManager.Debug($"[UpdateObjectPosition] 当前yaw={_currentYaw * 180 / Math.PI:F2}度, 目标yaw={newYaw * 180 / Math.PI:F2}度, 旋转增量deltaYaw={deltaYaw * 180 / Math.PI:F2}度");
|
||||
//LogManager.Debug($"[UpdateObjectPosition] 当前yaw={_currentYaw * 180 / Math.PI:F2}度, 目标yaw={newYaw * 180 / Math.PI:F2}度, 旋转增量deltaYaw={deltaYaw * 180 / Math.PI:F2}度");
|
||||
|
||||
// 计算绕当前位置旋转的等效变换:
|
||||
// 1. 如果绕原点旋转deltaYaw,当前位置_currentPosition会移动到哪里?
|
||||
@ -1982,17 +1982,18 @@ namespace NavisworksTransport.Core.Animation
|
||||
_currentYaw = newYaw;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 纯平移
|
||||
incrementalTransform = Transform3D.CreateTranslation(deltaPos);
|
||||
LogManager.Debug($"[UpdateObjectPosition] 纯平移: ({deltaPos.X:F2},{deltaPos.Y:F2},{deltaPos.Z:F2})");
|
||||
}
|
||||
|
||||
// 应用增量变换(false = 增量模式)
|
||||
doc.Models.OverridePermanentTransform(modelItems, incrementalTransform, false);
|
||||
|
||||
// 更新当前位置
|
||||
_currentPosition = newPosition; }
|
||||
{
|
||||
// 纯平移
|
||||
incrementalTransform = Transform3D.CreateTranslation(deltaPos);
|
||||
LogManager.Debug($"[UpdateObjectPosition] 纯平移: ({deltaPos.X:F2},{deltaPos.Y:F2},{deltaPos.Z:F2})");
|
||||
}
|
||||
|
||||
// 应用增量变换(false = 增量模式)
|
||||
doc.Models.OverridePermanentTransform(modelItems, incrementalTransform, false);
|
||||
|
||||
// 更新当前位置
|
||||
_currentPosition = newPosition;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"更新部件位置失败: {ex.Message}");
|
||||
@ -2601,10 +2602,10 @@ namespace NavisworksTransport.Core.Animation
|
||||
}
|
||||
|
||||
// 设置动画参数并预计算动画帧
|
||||
// 注意:物体应该在调用CreateAnimation之前已经通过MoveVehicleToPathStart旋转到起点
|
||||
LogManager.Debug($"[CreateAnimation开始] _currentYaw之前={_currentYaw * 180 / Math.PI:F2}度, _isVirtualVehicle={_isVirtualVehicle}");
|
||||
SetupAnimation(animatedObject, durationSeconds, _route);
|
||||
LogManager.Debug($"[CreateAnimation结束] _currentYaw之后={_currentYaw * 180 / Math.PI:F2}度");
|
||||
// 注意:物体应该在调用CreateAnimation之前已经通过MoveVehicleToPathStart旋转到起点
|
||||
LogManager.Debug($"[CreateAnimation开始] _currentYaw之前={_currentYaw * 180 / Math.PI:F2}度, _isVirtualVehicle={_isVirtualVehicle}");
|
||||
SetupAnimation(animatedObject, durationSeconds, _route);
|
||||
LogManager.Debug($"[CreateAnimation结束] _currentYaw之后={_currentYaw * 180 / Math.PI:F2}度");
|
||||
// 设置动画状态为Ready(动画已生成,可以播放)
|
||||
SetState(AnimationState.Ready);
|
||||
LogManager.Info($"[CreateAnimation] 动画已创建,状态设置为Ready");
|
||||
@ -2771,7 +2772,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
if (_currentFrameIndex < _animationFrames.Count)
|
||||
{
|
||||
var frameData = _animationFrames[_currentFrameIndex];
|
||||
|
||||
|
||||
// 计算实际朝向 = 路径方向 + 角度修正
|
||||
double actualYaw = frameData.YawRadians;
|
||||
if (_objectRotationCorrection != 0.0)
|
||||
@ -2779,7 +2780,7 @@ namespace NavisworksTransport.Core.Animation
|
||||
double correctionRad = _objectRotationCorrection * Math.PI / 180.0;
|
||||
actualYaw += correctionRad;
|
||||
}
|
||||
|
||||
|
||||
UpdateObjectPosition(frameData.Position, actualYaw);
|
||||
|
||||
// 更新碰撞高亮(基于预计算结果)
|
||||
|
||||
@ -608,6 +608,9 @@ namespace NavisworksTransport
|
||||
int skippedCount = 0;
|
||||
var doc = Application.ActiveDocument;
|
||||
|
||||
// 收集所有临时测试,用于批量删除
|
||||
var tempTestsToRemove = new List<ClashTest>();
|
||||
|
||||
// 2. 遍历每一组
|
||||
for (int groupIndex = 0; groupIndex < groupedCollisions.Count; groupIndex++)
|
||||
{
|
||||
@ -655,6 +658,8 @@ namespace NavisworksTransport
|
||||
doc.Models.OverridePermanentTransform(modelItems, transform, false);
|
||||
|
||||
var tempTestName = $"临时验证_{confirmedCount + 1}_{i}_{DateTime.Now:HHmmss_fff}";
|
||||
|
||||
// 🔥 优化3:预配置 ClashTest,避免后续 CreateCopy 和 TestsEditTestFromCopy 调用
|
||||
var tempTest = new ClashTest
|
||||
{
|
||||
DisplayName = tempTestName,
|
||||
@ -668,17 +673,19 @@ namespace NavisworksTransport
|
||||
var selectionB = new ModelItemCollection { candidate.Item2 };
|
||||
tempTest.SelectionA.Selection.CopyFrom(selectionA);
|
||||
tempTest.SelectionB.Selection.CopyFrom(selectionB);
|
||||
|
||||
// 直接设置 PrimitiveTypes,避免后续的 CreateCopy 和 TestsEditTestFromCopy
|
||||
tempTest.SelectionA.PrimitiveTypes = PrimitiveTypes.Triangles;
|
||||
tempTest.SelectionB.PrimitiveTypes = PrimitiveTypes.Triangles | PrimitiveTypes.Lines | PrimitiveTypes.Points;
|
||||
|
||||
_documentClash.TestsData.TestsAddCopy(tempTest);
|
||||
var addedTempTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == tempTestName) as ClashTest;
|
||||
|
||||
if (addedTempTest != null)
|
||||
{
|
||||
var copyTest = addedTempTest.CreateCopy() as ClashTest;
|
||||
copyTest.SelectionA.PrimitiveTypes = PrimitiveTypes.Triangles | PrimitiveTypes.Lines | PrimitiveTypes.Points;
|
||||
copyTest.SelectionB.PrimitiveTypes = PrimitiveTypes.Triangles | PrimitiveTypes.Lines | PrimitiveTypes.Points;
|
||||
_documentClash.TestsData.TestsEditTestFromCopy(addedTempTest, copyTest);
|
||||
|
||||
// 🔥 优化3:跳过了 addedTempTest.CreateCopy() 和 TestsEditTestFromCopy 调用
|
||||
// 因为 PrimitiveTypes 已在创建 tempTest 时设置好
|
||||
|
||||
_documentClash.TestsData.TestsRunTest(addedTempTest);
|
||||
|
||||
var refreshedTempTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == tempTestName) as ClashTest;
|
||||
@ -697,15 +704,10 @@ namespace NavisworksTransport
|
||||
var copiedResult = result.CreateCopy() as ClashResult;
|
||||
copiedResult.Guid = Guid.NewGuid(); // 生成新的GUID
|
||||
|
||||
// 设置唯一且有意义的碰撞名称
|
||||
// 先找到有意义的容器对象,再获取其名称
|
||||
var container1 = ModelItemAnalysisHelper.FindNamedParentContainer(result.Item1);
|
||||
var container2 = ModelItemAnalysisHelper.FindNamedParentContainer(result.Item2);
|
||||
var object1Name = ModelItemAnalysisHelper.GetSafeDisplayName(container1);
|
||||
var object2Name = ModelItemAnalysisHelper.GetSafeDisplayName(container2);
|
||||
|
||||
// 🔥 优化:简化 DisplayName,避免复杂的父容器查找
|
||||
// 详细的名称将在去重后统一设置
|
||||
var timeStamp = DateTime.Now.ToString("HHmmss");
|
||||
copiedResult.DisplayName = $"物流碰撞#{confirmedCount:00}-{subResultIndex:00}_{timeStamp}: {object1Name} ↔ {object2Name}";
|
||||
copiedResult.DisplayName = $"碰撞_{confirmedCount:00}_{subResultIndex:00}_{timeStamp}";
|
||||
|
||||
collisionGroup.Children.Add(copiedResult);
|
||||
subResultIndex++;
|
||||
@ -713,7 +715,8 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
_documentClash.TestsData.TestsRemove(refreshedTempTest ?? addedTempTest);
|
||||
// 🔥 优化4:收集测试用于批量删除,而不是立即删除
|
||||
tempTestsToRemove.Add(refreshedTempTest ?? addedTempTest);
|
||||
|
||||
if (pairConfirmed)
|
||||
{
|
||||
@ -728,6 +731,23 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
// 🔥 优化4:批量删除所有临时测试
|
||||
if (tempTestsToRemove.Count > 0)
|
||||
{
|
||||
LogManager.Debug($"[分组测试] 批量删除 {tempTestsToRemove.Count} 个临时测试");
|
||||
foreach (var test in tempTestsToRemove)
|
||||
{
|
||||
try
|
||||
{
|
||||
_documentClash.TestsData.TestsRemove(test);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Debug($"[分组测试] 删除临时测试失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info($"[分组测试] ClashDetective检测完成: 确认碰撞 {confirmedCount} 组, 跳过 {skippedCount} 个冗余检测点");
|
||||
|
||||
// 第三步:处理碰撞结果
|
||||
@ -766,6 +786,18 @@ namespace NavisworksTransport
|
||||
|
||||
LogManager.Info($"[最终去重] ClashDetective结果去重: {clashResults.Count} 个碰撞 -> {finalClashResults.Count} 个唯一碰撞对");
|
||||
|
||||
// 🔥 优化:在去重后为结果设置详细的 DisplayName
|
||||
// 这样只对保留的结果进行名称计算,避免在子碰撞结果上浪费性能
|
||||
foreach (var result in finalClashResults)
|
||||
{
|
||||
if (result.Item1 != null && result.Item2 != null)
|
||||
{
|
||||
var object1Name = ModelItemAnalysisHelper.GetSafeDisplayName(result.Item1);
|
||||
var object2Name = ModelItemAnalysisHelper.GetSafeDisplayName(result.Item2);
|
||||
result.DisplayName = $"物流碰撞: {object1Name} ↔ {object2Name}";
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存最终结果
|
||||
lock (_clashResultsCacheLock)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user