优化代码格式,调整空行和注释位置;更新生成碰撞报告的方法为异步执行
This commit is contained in:
parent
a94d1c35b7
commit
6be1de113e
@ -77,6 +77,7 @@ set MSBUILD_PATH="C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuil
|
||||
```
|
||||
|
||||
该脚本将:
|
||||
|
||||
1. 构建主项目
|
||||
2. 构建测试项目
|
||||
3. 使用 VSTest.Console 运行单元测试
|
||||
@ -162,6 +163,7 @@ UnitTests/ # 单元测试
|
||||
### 关键依赖
|
||||
|
||||
**Navisworks API(必须安装Navisworks 2026):**
|
||||
|
||||
- `Autodesk.Navisworks.Api.dll`
|
||||
- `Autodesk.Navisworks.ComApi.dll`
|
||||
- `Autodesk.Navisworks.Interop.ComApi.dll`
|
||||
@ -170,6 +172,7 @@ UnitTests/ # 单元测试
|
||||
- `Autodesk.Navisworks.Controls.dll`
|
||||
|
||||
**NuGet包:**
|
||||
|
||||
- `RoyT.AStar 3.0.2` - A*寻路算法
|
||||
- `geometry4Sharp 1.0.0` - 3D几何计算(体素路径规划)
|
||||
- `System.Data.SQLite.Core 1.0.118.0` - SQLite数据库
|
||||
@ -233,6 +236,7 @@ if (heightDiff > MAX_HEIGHT_DIFF) // 单位不匹配,严重Bug!
|
||||
```
|
||||
|
||||
`UnitsConverter` 提供以下方法:
|
||||
|
||||
- `GetUnitsToMetersConversionFactor()` - 文档单位转米
|
||||
- `GetMetersToUnitsConversionFactor()` - 米转文档单位
|
||||
- `ConvertToMeters(distance)` - 转换距离为米
|
||||
@ -408,7 +412,7 @@ namespace NavisworksTransport.UnitTests
|
||||
|
||||
1. **查看日志**: 日志文件位于 `C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\NavisworksTransportPlugin\logs\`
|
||||
2. **使用 LogManager**: 所有重要操作都应记录日志
|
||||
3. **Navisworks插件调试**:
|
||||
3. **Navisworks插件调试**:
|
||||
- 附加到 `Roamer.exe` 进程
|
||||
- 使用 `LogManager.Debug()` 输出调试信息
|
||||
|
||||
|
||||
@ -213,7 +213,7 @@ namespace NavisworksTransport
|
||||
{
|
||||
// 使用 CreatePathId API 获取 ModelIndex 和 PathId
|
||||
var pathId = Application.ActiveDocument.Models.CreatePathId(collision.Item2);
|
||||
|
||||
|
||||
collisionObjects.Add(new ClashDetectiveCollisionObjectRecord
|
||||
{
|
||||
ResultId = resultId,
|
||||
@ -328,14 +328,14 @@ namespace NavisworksTransport
|
||||
if (testInfo.IsVirtualVehicle)
|
||||
{
|
||||
// 显示虚拟车辆
|
||||
var modelToMeters = UnitsConverter.GetUnitsToMetersConversionFactor();
|
||||
VirtualVehicleManager.Instance.ShowVirtualVehicle(
|
||||
testInfo.VirtualVehicleLength,
|
||||
testInfo.VirtualVehicleWidth,
|
||||
testInfo.VirtualVehicleHeight
|
||||
testInfo.VirtualVehicleLength * modelToMeters,
|
||||
testInfo.VirtualVehicleWidth * modelToMeters,
|
||||
testInfo.VirtualVehicleHeight * modelToMeters
|
||||
);
|
||||
vehicleObject = VirtualVehicleManager.Instance.CurrentVirtualVehicle
|
||||
vehicleObject = VirtualVehicleManager.Instance.CurrentVirtualVehicle
|
||||
?? throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 显示虚拟车辆失败");
|
||||
LogManager.Info($"[LoadClashDetectiveResultsFromDatabase] 已显示虚拟车辆: {testInfo.VirtualVehicleLength}×{testInfo.VirtualVehicleWidth}×{testInfo.VirtualVehicleHeight}m");
|
||||
}
|
||||
else if (testInfo.VehicleModelIndex.HasValue && !string.IsNullOrEmpty(testInfo.VehiclePathId))
|
||||
{
|
||||
@ -368,15 +368,15 @@ namespace NavisworksTransport
|
||||
{
|
||||
var pathPlanningManager = PathPlanningManager.Instance;
|
||||
var route = pathPlanningManager.GetAllRoutes().FirstOrDefault(r => r.Id == testInfo.RouteId);
|
||||
|
||||
|
||||
if (route != null && route.Points != null && route.Points.Count > 0)
|
||||
{
|
||||
// 获取第一个点(起点)
|
||||
var startPoint = route.Points.FirstOrDefault(p => p.Type == PathPointType.StartPoint) ?? route.Points[0];
|
||||
var startPointPosition = startPoint.Position;
|
||||
|
||||
|
||||
// 使用 PathAnimationManager 将车辆移动到起点
|
||||
var pathAnimationManager = Core.Animation.PathAnimationManager.GetInstance();
|
||||
var pathAnimationManager = PathAnimationManager.GetInstance();
|
||||
pathAnimationManager.MoveVehicleToPathStart(vehicleObject, new List<Point3D> { startPointPosition, startPointPosition });
|
||||
LogManager.Info($"[LoadClashDetectiveResultsFromDatabase] 虚拟车辆已移动到路径起点: ({startPointPosition.X:F2}, {startPointPosition.Y:F2}, {startPointPosition.Z:F2})");
|
||||
}
|
||||
@ -419,7 +419,7 @@ namespace NavisworksTransport
|
||||
foreach (var obj in collisionObjects)
|
||||
{
|
||||
ModelItem collidedObject = null;
|
||||
|
||||
|
||||
// 优先使用 ResolvePathId API(新方式)
|
||||
if (obj.ModelIndex.HasValue && !string.IsNullOrEmpty(obj.PathId))
|
||||
{
|
||||
@ -435,12 +435,12 @@ namespace NavisworksTransport
|
||||
throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] ResolvePathId 失败: ModelIndex={obj.ModelIndex}, PathId={obj.PathId}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (collidedObject == null)
|
||||
{
|
||||
throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 无法通过路径找到车辆对象: {obj.ModelIndex},{obj.PathId}");
|
||||
}
|
||||
|
||||
|
||||
if (!ModelItemAnalysisHelper.IsModelItemValid(collidedObject))
|
||||
{
|
||||
throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 找到的 ModelItem 无效: {obj.ModelIndex},{obj.PathId}");
|
||||
@ -500,7 +500,7 @@ namespace NavisworksTransport
|
||||
return new Point3D(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通过PathId向上查找匹配的原始对象
|
||||
/// 从ClashDetective返回的几何体组件开始,向上遍历父节点,
|
||||
@ -545,7 +545,7 @@ namespace NavisworksTransport
|
||||
try
|
||||
{
|
||||
var currentPathId = doc.Models.CreatePathId(current);
|
||||
|
||||
|
||||
// 检查PathId是否在预计算记录中
|
||||
if (precomputedPathIds.Contains((currentPathId.ModelIndex, currentPathId.PathId)))
|
||||
{
|
||||
@ -635,10 +635,10 @@ namespace NavisworksTransport
|
||||
if (validCollisions.Count == 0)
|
||||
{
|
||||
LogManager.Warning("[ClashDetective] 没有有效的碰撞,保存空碰撞记录");
|
||||
|
||||
|
||||
// 重置碰撞计数器(重要:避免保留上次测试的值)
|
||||
_clashDetectiveCollisionCount = 0;
|
||||
|
||||
|
||||
// 保存到数据库
|
||||
SaveClashDetectiveResultToDatabase(
|
||||
routeId,
|
||||
@ -653,7 +653,7 @@ namespace NavisworksTransport
|
||||
virtualVehicleHeight,
|
||||
precomputedCollisionCount
|
||||
);
|
||||
|
||||
|
||||
return (null, addedMainTest, 0);
|
||||
}
|
||||
|
||||
@ -739,7 +739,7 @@ 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
|
||||
{
|
||||
@ -754,7 +754,7 @@ 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;
|
||||
@ -766,9 +766,9 @@ namespace NavisworksTransport
|
||||
{
|
||||
// 🔥 优化3:跳过了 addedTempTest.CreateCopy() 和 TestsEditTestFromCopy 调用
|
||||
// 因为 PrimitiveTypes 已在创建 tempTest 时设置好
|
||||
|
||||
|
||||
_documentClash.TestsData.TestsRunTest(addedTempTest);
|
||||
|
||||
|
||||
// 增加检测计数并打印进度日志(每100次)
|
||||
testCount++;
|
||||
if (testCount % 100 == 0)
|
||||
@ -788,7 +788,7 @@ namespace NavisworksTransport
|
||||
int subResultIndex = 1;
|
||||
// 🔥 优化:预获取运动物体名称,避免在循环中重复获取
|
||||
var animatedObjectName = ModelItemAnalysisHelper.GetSafeDisplayName(animatedObject);
|
||||
|
||||
|
||||
foreach (var child in refreshedTempTest.Children)
|
||||
{
|
||||
if (child is ClashResult result)
|
||||
@ -948,48 +948,48 @@ namespace NavisworksTransport
|
||||
try
|
||||
{
|
||||
LogManager.Info($"=== 使用预计算碰撞数据创建ClashDetective测试(容差: {detectionGap}米)===");
|
||||
|
||||
LogManager.Info($"[预计算数据] 共有 {precomputedCollisions.Count} 个碰撞记录");
|
||||
|
||||
// 直接使用所有预计算结果,只过滤有效对象(不去重)
|
||||
var collisionResults = precomputedCollisions
|
||||
.Where(result => IsModelItemValid(result.Item1) && IsModelItemValid(result.Item2))
|
||||
.ToList();
|
||||
|
||||
// 记录预计算碰撞数量(作为参考值,不作为类状态)
|
||||
int precomputedCollisionCount = collisionResults.Count;
|
||||
LogManager.Info($"[预计算处理] 原始记录: {precomputedCollisions.Count},有效碰撞: {precomputedCollisionCount}");
|
||||
|
||||
// 获取动画对象
|
||||
if (collisionResults.Count > 0)
|
||||
{
|
||||
animatedObject = collisionResults[0].Item1;
|
||||
}
|
||||
|
||||
var doc = Application.ActiveDocument;
|
||||
|
||||
// 调用公共方法运行ClashDetective测试并保存到数据库
|
||||
Progress progress = Application.BeginProgress("碰撞检测数据分析中,请稍候...");
|
||||
ClashTest addedMainTest = null;
|
||||
ClashResultGroup collisionGroup = null;
|
||||
int confirmedCount = 0;
|
||||
|
||||
try
|
||||
{
|
||||
var result = RunClashDetectiveTestsAndSaveToDatabase(
|
||||
precomputedCollisions,
|
||||
detectionGap,
|
||||
routeId,
|
||||
animatedObject,
|
||||
isVirtualVehicle,
|
||||
frameRate,
|
||||
duration,
|
||||
virtualVehicleLength,
|
||||
virtualVehicleWidth,
|
||||
virtualVehicleHeight,
|
||||
progress,
|
||||
precomputedCollisionCount
|
||||
);
|
||||
LogManager.Info($"[预计算数据] 共有 {precomputedCollisions.Count} 个碰撞记录");
|
||||
|
||||
// 直接使用所有预计算结果,只过滤有效对象(不去重)
|
||||
var collisionResults = precomputedCollisions
|
||||
.Where(result => IsModelItemValid(result.Item1) && IsModelItemValid(result.Item2))
|
||||
.ToList();
|
||||
|
||||
// 记录预计算碰撞数量(作为参考值,不作为类状态)
|
||||
int precomputedCollisionCount = collisionResults.Count;
|
||||
LogManager.Info($"[预计算处理] 原始记录: {precomputedCollisions.Count},有效碰撞: {precomputedCollisionCount}");
|
||||
|
||||
// 获取动画对象
|
||||
if (collisionResults.Count > 0)
|
||||
{
|
||||
animatedObject = collisionResults[0].Item1;
|
||||
}
|
||||
|
||||
var doc = Application.ActiveDocument;
|
||||
|
||||
// 调用公共方法运行ClashDetective测试并保存到数据库
|
||||
Progress progress = Application.BeginProgress("碰撞检测数据分析中,请稍候...");
|
||||
ClashTest addedMainTest = null;
|
||||
ClashResultGroup collisionGroup = null;
|
||||
int confirmedCount = 0;
|
||||
|
||||
try
|
||||
{
|
||||
var result = RunClashDetectiveTestsAndSaveToDatabase(
|
||||
precomputedCollisions,
|
||||
detectionGap,
|
||||
routeId,
|
||||
animatedObject,
|
||||
isVirtualVehicle,
|
||||
frameRate,
|
||||
duration,
|
||||
virtualVehicleLength,
|
||||
virtualVehicleWidth,
|
||||
virtualVehicleHeight,
|
||||
progress,
|
||||
precomputedCollisionCount
|
||||
);
|
||||
collisionGroup = result.collisionGroup;
|
||||
addedMainTest = result.addedMainTest;
|
||||
confirmedCount = result.confirmedCount;
|
||||
@ -1156,11 +1156,11 @@ namespace NavisworksTransport
|
||||
LogManager.Debug($"[ClashDetective结果] 从缓存获取 '{testName}' 的结果:{cachedResults.Count}个碰撞");
|
||||
return cachedResults;
|
||||
}
|
||||
|
||||
|
||||
// 缓存中没有,尝试从数据库加载
|
||||
LogManager.Info($"[ClashDetective结果] 缓存中没有 '{testName}',尝试从数据库加载");
|
||||
var loadedResults = GetClashDetectiveResultsFromDatabase(testName);
|
||||
|
||||
|
||||
if (loadedResults != null && loadedResults.Count > 0)
|
||||
{
|
||||
// 缓存加载的结果
|
||||
@ -1168,7 +1168,7 @@ namespace NavisworksTransport
|
||||
LogManager.Info($"[ClashDetective结果] 已从数据库加载 '{testName}' 的结果并缓存:{loadedResults.Count}个碰撞");
|
||||
return loadedResults;
|
||||
}
|
||||
|
||||
|
||||
// 没有找到结果,返回空列表
|
||||
LogManager.Info($"[ClashDetective结果] 未找到测试 '{testName}' 的碰撞结果,返回空列表");
|
||||
return new List<CollisionResult>();
|
||||
@ -1384,7 +1384,7 @@ namespace NavisworksTransport
|
||||
{
|
||||
_animatedObject = animatedObject;
|
||||
LogManager.Info($"移动物体已设置: {animatedObject?.DisplayName ?? "null"}");
|
||||
|
||||
|
||||
// 🔥 关键:清除几何对象缓存,强制重新构建以排除移动物体
|
||||
// 原因:BuildNonHidddenGeometryItemsCache 使用双重检查锁定,只构建一次
|
||||
// 如果在第一次构建时移动物体为 null,摩托车会被添加到缓存
|
||||
@ -1392,7 +1392,7 @@ namespace NavisworksTransport
|
||||
_allGeometryItemsCache = null;
|
||||
_nonChannelGeometryItemsCache = null;
|
||||
LogManager.Info("几何对象缓存已清除,将重新构建以排除移动物体");
|
||||
|
||||
|
||||
// 🔥 立即重新构建几何对象缓存(排除移动物体)
|
||||
BuildNonHidddenGeometryItemsCache();
|
||||
LogManager.Info("几何对象缓存已重新构建完成");
|
||||
@ -1589,7 +1589,7 @@ namespace NavisworksTransport
|
||||
{
|
||||
lock (_cacheLock)
|
||||
{
|
||||
return _allGeometryItemsCache;
|
||||
return _allGeometryItemsCache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1652,7 +1652,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
/// </summary>
|
||||
private void OnAnimationStateChanged(object sender, Core.Animation.AnimationState state)
|
||||
{
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Func<Task>(async () =>
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
@ -1678,9 +1678,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
UpdateMediaControlProperties(); // 更新媒体控制属性
|
||||
// 先清除所有碰撞高亮(包括预计算和ClashDetective)
|
||||
ModelHighlightHelper.ClearCollisionHighlights();
|
||||
// 生成碰撞报告(无论有无碰撞)
|
||||
GenerateAndSaveCollisionReport();
|
||||
// 高亮ClashDetective结果(只在动画自然完成时进行)
|
||||
// 生成碰撞报告(无论有无碰撞)并等待完成
|
||||
await GenerateAndSaveCollisionReport();
|
||||
// 高亮ClashDetective结果(只在动画自然完成时进行,确保报告生成完成)
|
||||
HighlightClashDetectiveResults();
|
||||
break;
|
||||
case NavisworksTransport.Core.Animation.AnimationState.Stopped:
|
||||
@ -1704,7 +1704,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
/// <summary>
|
||||
/// 生成并保存碰撞报告(无论有无碰撞都生成)
|
||||
/// </summary>
|
||||
private async void GenerateAndSaveCollisionReport()
|
||||
private async Task GenerateAndSaveCollisionReport()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user