diff --git a/CLAUDE.md b/CLAUDE.md
index e5d3810..80d2b3b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -115,8 +115,23 @@ public class PathClickToolPlugin : ToolPlugin { }
### Development Principles
-- **不考虑向后兼容性**: 直接修改现有代码逻辑,无需保持向后兼容性,专注于解决当前问题和改进现有功能
-- **最小化修改原则**: 进行任何代码修改时,必须遵循最小化原则,只修改必要的部分,不添加额外的功能或逻辑,以确保问题能够清晰暴露和定位
+- 防御性编程的正确态度:
+ - ✅ 应该做:检测异常情况并报错,让问题暴露出来
+ - ❌ 不应该做:用默认值掩盖问题,让bug隐藏在系统中
+
+- 对于"备份方案"和"容错处理":
+ - ✅ 正确做法:发现问题时记录错误日志,中断处理流程
+ - ❌ 错误做法:遇到异常数据时自动"修复"或使用替代值继续执行
+
+- 对于"向后兼容性":
+ - 明确拒绝考虑向后兼容性
+ - 专注解决当前问题,不为旧版本或边缘情况妥协
+
+- 核心原则:
+ - "让问题快速暴露" > "让程序看起来正常运行"
+ - "报错比静默失败好" > "容忍错误数据继续处理"
+ - "数据一致性检查" > "宽松的数据验证"
+ - "最小化修改" > "复杂全面的逻辑"
### Critical API Usage Patterns
@@ -188,4 +203,4 @@ public class PathClickToolPlugin : ToolPlugin { }
- **2026 Features**: Test advanced animation capabilities, enhanced collision detection, and improved model handling
- 在编码中,不要用回退或向后兼容的思路和步骤
- 程序的日志在:C:\ProgramData\Autodesk\Navisworks Manage 2026\NavisworksTransport\logs\debug.log
-- 不要搞向后兼容
\ No newline at end of file
+- 不要搞向后兼容
diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs
index 7b95aee..023c55a 100644
--- a/src/Core/PathPlanningManager.cs
+++ b/src/Core/PathPlanningManager.cs
@@ -829,7 +829,6 @@ namespace NavisworksTransport
try
{
- LogManager.Info($"开始调用GridMapGenerator.GenerateFromBIM(2.5D模式)");
var performanceStart = System.Diagnostics.Stopwatch.StartNew();
// 获取当前文档
@@ -841,8 +840,6 @@ namespace NavisworksTransport
try
{
- // 使用2.5D通道检测模式
- LogManager.Info("使用BoundingBoxBased2_5D模式生成网格");
gridMap = gridMapGenerator.GenerateFromBIM(
document,
bounds,
@@ -851,14 +848,13 @@ namespace NavisworksTransport
safetyMargin,
startPoint.Position,
endPoint.Position,
- GridGenerationMode.BoundingBoxBased2_5D, // 新增:使用优化的边界框算法
- vehicleHeight // 传递车辆高度参数
+ vehicleHeight
);
- LogManager.Info("✅ BoundingBoxBased2_5D模式网格生成成功");
+ LogManager.Info("✅ 网格地图生成成功");
}
catch (Exception modeEx)
{
- LogManager.Warning($"BoundingBoxBased2_5D模式失败,{modeEx.Message}");
+ LogManager.Warning($"网格地图生成失败,{modeEx.Message}");
}
performanceStart.Stop();
@@ -871,21 +867,14 @@ namespace NavisworksTransport
throw new Exception($"网格地图生成失败: {ex.Message}", ex);
}
- LogManager.Info($"网格地图生成完成: {gridMap.GetStatistics()}");
-
// 根据用户设置决定是否进行网格可视化
if (_showWalkableGrid || _showObstacleGrid || _showUnknownGrid || _showDoorGrid)
{
LogManager.Info("开始网格可视化,显示所有可通行网格单元");
VisualizeGridCells(gridMap);
}
- else
- {
- LogManager.Info("网格可视化已关闭,跳过可视化步骤");
- }
- // 3. 获取通道数据用于精确高度计算
- LogManager.Info("开始获取通道数据用于精确高度计算...");
+ // 3. 获取通道高度数据
var channelItems = GetChannelItemsForHeightCalculation(gridMap);
LogManager.Info($"获取通道数据完成: {channelItems?.Count() ?? 0} 个通道项");
@@ -918,11 +907,9 @@ namespace NavisworksTransport
try
{
pathFinder = new AutoPathFinder();
-
double vehicleHeightInModelUnits = vehicleHeight * UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
LogManager.Info($"使用2.5D模式进行路径查找,车辆高度: {vehicleHeight}m ({vehicleHeightInModelUnits:F2}模型单位),策略: {strategy}");
pathResult = pathFinder.FindPath(startPoint.Position, endPoint.Position, gridMap, channelCoverage, vehicleHeightInModelUnits, strategy);
-
LogManager.Info("FindPath方法调用完成");
}
catch (Exception ex)
diff --git a/src/PathPlanning/AutoPathFinder.cs b/src/PathPlanning/AutoPathFinder.cs
index 56503e7..07ca37b 100644
--- a/src/PathPlanning/AutoPathFinder.cs
+++ b/src/PathPlanning/AutoPathFinder.cs
@@ -48,45 +48,6 @@ namespace NavisworksTransport.PathPlanning
///
public class AutoPathFinder
{
- ///
- /// 查找路径(支持通道数据和高度约束)
- ///
- /// 起点(世界坐标)
- /// 终点(世界坐标)
- /// 网格地图
- /// 通道覆盖数据(可选,用于2.5D路径规划)
- /// 车辆高度(模型单位,用于高度约束检查)
- /// 路径查找结果
- public PathFindingResult FindPath(Point3D start, Point3D end, GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight)
- {
- // 调用支持策略的重载方法,默认使用最短路径策略
- return FindPath(start, end, gridMap, channelCoverage, vehicleHeight, PathStrategy.Shortest);
- }
-
- ///
- /// 查找路径(支持通道数据、高度约束和路径策略)
- ///
- /// 起点(世界坐标)
- /// 终点(世界坐标)
- /// 网格地图
- /// 通道覆盖数据(可选,用于2.5D路径规划)
- /// 车辆高度(模型单位,用于高度约束检查)
- /// 路径规划策略
- /// 路径查找结果
- public PathFindingResult FindPath(Point3D start, Point3D end, GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, PathStrategy strategy)
- {
- LogManager.Info($"开始A*路径查找: 起点({start?.X:F2}, {start?.Y:F2}, {start?.Z:F2}), 终点({end?.X:F2}, {end?.Y:F2}, {end?.Z:F2}), 策略: {strategy}");
-
- // 如果提供了通道覆盖数据,使用2.5D模式进行路径规划
- if (channelCoverage != null && channelCoverage.ChannelItems.Any())
- {
- LogManager.Info($"[2.5D路径规划] 使用通道覆盖数据,通道数量: {channelCoverage.ChannelItems.Count}, 车辆高度: {vehicleHeight}m, 策略: {strategy}");
- return FindPath2_5D(start, end, gridMap, channelCoverage, vehicleHeight, strategy);
- }
-
- return new PathFindingResult { PathPoints = new List() };
- }
-
///
/// 2.5D路径规划(使用通道覆盖数据、高度约束和路径策略)
///
@@ -97,7 +58,7 @@ namespace NavisworksTransport.PathPlanning
/// 车辆高度(模型单位)
/// 路径规划策略
/// 路径查找结果
- private PathFindingResult FindPath2_5D(Point3D start, Point3D end, GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, PathStrategy strategy = PathStrategy.Shortest)
+ public PathFindingResult FindPath(Point3D start, Point3D end, GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, PathStrategy strategy = PathStrategy.Shortest)
{
try
{
diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs
index a15bc7e..01d87df 100644
--- a/src/PathPlanning/GridMapGenerator.cs
+++ b/src/PathPlanning/GridMapGenerator.cs
@@ -46,152 +46,8 @@ namespace NavisworksTransport.PathPlanning
_verticalScanner = null;
}
- ///
- /// 从BIM模型生成网格地图
- ///
- /// Navisworks文档
- /// 规划区域边界
- /// 网格单元格大小(米)
- /// 车辆半径(用于障碍物膨胀)
- /// 安全间隙(额外的膨胀间距,米)
- /// 规划起点(用于确定楼层)
- /// 规划终点(用于确定楼层)
- /// 网格生成模式,默认为2.5D模式
- /// 车辆高度(用于垂直通行检查)
- /// 生成的网格地图
- public GridMap GenerateFromBIM(Document document, BoundingBox3D bounds, double cellSize, double vehicleRadius, double safetyMargin, Point3D planningStartPoint, Point3D planningEndPoint, GridGenerationMode mode, double vehicleHeight)
- {
- try
- {
- LogManager.Info($"[网格生成器] 使用模式: {mode}");
-
- // 根据模式选择不同的生成策略
- switch (mode)
- {
- case GridGenerationMode.ChannelBased2_5D:
- return GenerateChannelBased2_5D(document, bounds, cellSize, vehicleRadius, safetyMargin, planningStartPoint, planningEndPoint, vehicleHeight);
-
- case GridGenerationMode.BoundingBoxBased2_5D:
- return GenerateBoundingBoxBased2_5D(document, bounds, cellSize, vehicleRadius, safetyMargin, planningStartPoint, planningEndPoint, vehicleHeight);
-
- default:
- return GenerateBoundingBoxBased2_5D(document, bounds, cellSize, vehicleRadius, safetyMargin, planningStartPoint, planningEndPoint, vehicleHeight);
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"生成网格地图时发生错误: {ex.Message}");
- throw new AutoPathPlanningException($"网格地图生成失败: {ex.Message}", ex);
- }
- }
-
- ///
- /// 通道基础2.5D模式的网格生成
- /// 使用通道优先策略和垂直扫描处理器
- ///
- /// 术语说明:
- /// - "通道"在此指所有可通行结构(楼板、走廊、过道等)
- /// - 对于楼板类通道,车辆在其顶面行驶
- /// - 生成的网格地图用于车辆路径规划
- ///
- private GridMap GenerateChannelBased2_5D(Document document, BoundingBox3D bounds, double cellSize, double vehicleRadius, double safetyMargin, Point3D planningStartPoint, Point3D planningEndPoint, double vehicleHeight)
- {
- try
- {
- LogManager.Info("[通道2.5D模式] 开始生成网格地图");
-
- // 重要:将米制网格大小转换为模型单位
- double metersToModelUnitsConversionFactor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
- double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor;
- LogManager.Info($"[通道2.5D模式] 网格大小单位转换: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位 (转换系数: {metersToModelUnitsConversionFactor:F2})");
-
- // 1. 使用通道构建器构建基础通道覆盖网格
- LogManager.Info("[通道2.5D模式] 步骤1: 构建通道覆盖网格");
- var channelCoverage = _channelBuilder.BuildChannelCoverage(cellSizeInModelUnits, document);
-
- LogManager.Info($"[通道2.5D模式] 通道覆盖构建完成: {channelCoverage.GetStatistics()}");
- LogManager.Info($"[阶段1完成] 通道覆盖网格统计: {channelCoverage.GridMap.GetStatistics()}");
-
- // 2. 构建垂直扫描处理器的空间索引
- LogManager.Info("[通道2.5D模式] 步骤2: 构建空间哈希索引");
- double spatialHashMultiplier = 10.0; // 可以根据模型密度调整(高密设为6,低密设为10)
- _verticalScanner = new VerticalScanProcessor(cellSize * spatialHashMultiplier);
-
- var allItems = document.Models.RootItemDescendantsAndSelf;
- _verticalScanner.BuildSpatialHashIndex(allItems, bounds, channelCoverage.ChannelItems);
-
- // 3. 生成网格点坐标用于垂直扫描
- LogManager.Info("[通道2.5D模式] 步骤3: 生成网格扫描点");
- var gridPoints = GenerateGridPoints(channelCoverage.GridMap);
- LogManager.Info($"[阶段3完成] 生成 {gridPoints.Count} 个扫描点");
-
- // 4. 并行执行垂直扫描,计算2.5D高度区间
- LogManager.Info("[通道2.5D模式] 步骤4: 执行并行垂直扫描");
- double scanHeight = vehicleHeight + safetyMargin; // 扫描高度 = 车辆高度 + 安全间隙
- var heightIntervals = _verticalScanner.ParallelScanHeightIntervals(
- gridPoints, scanHeight, vehicleHeight);
-
- LogManager.Info($"[阶段4完成] 垂直扫描结果: 扫描了{gridPoints.Count}个通道点,生成了{heightIntervals.Count}个高度区间数据");
-
- // 5. 将高度区间信息集成到网格地图中
- LogManager.Info("[通道2.5D模式] 步骤5: 集成高度信息到网格");
-
- // 添加集成前的验证日志
- var preIntegrationStats = channelCoverage.GridMap.GetStatistics();
- LogManager.Info($"[验证] 高度信息集成前网格统计: {preIntegrationStats}");
-
- IntegrateHeightIntervalsToGrid(channelCoverage.GridMap, heightIntervals);
-
- // 添加集成后的验证日志
- var postIntegrationStats = channelCoverage.GridMap.GetStatistics();
- LogManager.Info($"[阶段5完成] 高度信息集成后网格统计: {postIntegrationStats}");
-
- // 验证网格统计一致性
- ValidateGridStatisticsConsistency(channelCoverage.GridMap, "高度信息集成后");
-
- // 6. 应用车辆尺寸膨胀(如果需要)
- if (vehicleRadius > 0 || safetyMargin > 0)
- {
- LogManager.Info("[通道2.5D模式] 步骤6: 应用车辆膨胀");
- double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
- double totalInflationRadius = (vehicleRadius + safetyMargin) * metersToModelUnits;
- ApplyVehicleInflation(channelCoverage.GridMap, totalInflationRadius);
- LogManager.Info($"[通道2.5D模式] 车辆膨胀完成,膨胀半径: {totalInflationRadius:F2}模型单位");
- LogManager.Info($"[阶段6完成] 车辆膨胀后网格统计: {channelCoverage.GridMap.GetStatistics()}");
- }
-
- // 注意:边界膨胀已集成到车辆膨胀中,无需单独处理
-
- // 8. 设置规划起点和终点信息
- if (planningStartPoint != default(Point3D) && planningEndPoint != default(Point3D))
- {
- channelCoverage.GridMap.PlanningStartPoint = planningStartPoint;
- channelCoverage.GridMap.PlanningEndPoint = planningEndPoint;
- channelCoverage.GridMap.HasPlanningPoints = true;
-
- // 注意:网格的Z坐标已在通道生成时设置为实际通道高度,无需重新计算
- }
-
- // 🔥 关键修复:将通道数据设置到GridMap中,供后续PathPlanningManager使用
- if (channelCoverage.ChannelItems != null && channelCoverage.ChannelItems.Any())
- {
- channelCoverage.GridMap.ChannelItems = new List(channelCoverage.ChannelItems);
- LogManager.Info($"[通道2.5D模式] 已将 {channelCoverage.ChannelItems.Count} 个通道数据设置到GridMap中");
- }
-
- LogManager.Info($"[通道2.5D模式] 网格地图生成完成: {channelCoverage.GridMap.GetStatistics()}");
- return channelCoverage.GridMap;
- }
- catch (Exception ex)
- {
- LogManager.Error($"[通道2.5D模式] 生成失败: {ex.Message}");
- return null;
- }
- }
-
///
/// 基于包围盒遍历的网格地图生成方法(优化版)
- /// 使用简化的包围盒检测替代空间索引+垂直扫描,提升性能
///
/// Navisworks文档
/// 扫描边界
@@ -202,61 +58,61 @@ namespace NavisworksTransport.PathPlanning
/// 规划终点
/// 车辆高度(米)
/// 生成的网格地图
- private GridMap GenerateBoundingBoxBased2_5D(Document document, BoundingBox3D bounds, double cellSize, double vehicleRadius, double safetyMargin, Point3D planningStartPoint, Point3D planningEndPoint, double vehicleHeight)
+ public GridMap GenerateFromBIM(Document document, BoundingBox3D bounds, double cellSize, double vehicleRadius, double safetyMargin, Point3D planningStartPoint, Point3D planningEndPoint, double vehicleHeight)
{
try
{
- LogManager.Info("【包围盒2.5D模式】开始生成网格地图");
+ LogManager.Info("【生成网格地图】开始生成网格地图");
var startTime = DateTime.Now;
// 重要:将米制网格大小转换为模型单位
double metersToModelUnitsConversionFactor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor;
- LogManager.Info($"【包围盒2.5D模式】网格大小单位转换: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位 (转换系数: {metersToModelUnitsConversionFactor:F2})");
+ LogManager.Info($"【生成网格地图】网格大小单位转换: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位 (转换系数: {metersToModelUnitsConversionFactor:F2})");
// 1. 使用通道构建器构建基础通道覆盖网格
- LogManager.Info("【包围盒2.5D模式】步骤1: 构建通道覆盖网格");
+ LogManager.Info("【生成网格地图】步骤1: 构建通道覆盖网格");
var channelCoverage = _channelBuilder.BuildChannelCoverage(cellSizeInModelUnits, document);
- LogManager.Info($"【包围盒2.5D模式】通道覆盖构建完成: {channelCoverage.GetStatistics()}");
+ LogManager.Info($"【生成网格地图】通道覆盖构建完成: {channelCoverage.GetStatistics()}");
LogManager.Info($"【阶段1完成】通道覆盖网格统计: {channelCoverage.GridMap.GetStatistics()}");
// 1.5. 使用智能收集策略收集所有通道相关节点
- LogManager.Info("【包围盒2.5D模式】步骤1.5: 智能收集通道相关节点");
+ LogManager.Info("【生成网格地图】步骤1.5: 智能收集通道相关节点");
// 直接获取所有可通行的物流模型项
var allChannelItems = CategoryAttributeManager.GetAllTraversableLogisticsItems(document);
- LogManager.Info($"【包围盒2.5D模式】直接获取到 {allChannelItems.Count} 个可通行物流元素");
+ LogManager.Info($"【生成网格地图】直接获取到 {allChannelItems.Count} 个可通行物流元素");
// 智能收集通道相关节点(包括父节点、同级节点等)
var channelRelatedItems = CollectChannelRelatedItems(allChannelItems.ToList());
- LogManager.Info($"【包围盒2.5D模式】智能收集到 {channelRelatedItems.Count} 个通道相关节点");
+ LogManager.Info($"【生成网格地图】智能收集到 {channelRelatedItems.Count} 个通道相关节点");
// 2. 直接遍历处理障碍物(包围盒检测) - 使用高性能优化版本
- LogManager.Info("【包围盒2.5D模式】步骤2: 高性能包围盒遍历处理障碍物");
+ LogManager.Info("【生成网格地图】步骤2: 高性能包围盒遍历处理障碍物");
double scanHeight = vehicleHeight + safetyMargin; // 扫描高度 = 车辆高度 + 安全间隙
ProcessObstaclesWithBoundingBoxOptimized(document, channelCoverage.GridMap, channelRelatedItems, scanHeight);
LogManager.Info($"【阶段2完成】障碍物处理后网格统计: {channelCoverage.GridMap.GetStatistics()}");
// 2.5. 单独处理门元素,设置为可通行
- LogManager.Info("【包围盒2.5D模式】步骤2.5: 处理门元素");
+ LogManager.Info("【生成网格地图】步骤2.5: 处理门元素");
ProcessDoorElements(channelCoverage.GridMap, allChannelItems);
LogManager.Info($"【阶段2.5完成】门元素处理后网格统计: {channelCoverage.GridMap.GetStatistics()}");
// 2.6. 为通道网格设置PassableHeights确保高度约束检查
- LogManager.Info("【包围盒2.5D模式】步骤2.6: 为通道网格设置高度约束");
+ LogManager.Info("【生成网格地图】步骤2.6: 为通道网格设置高度约束");
SetChannelPassableHeights(channelCoverage.GridMap, scanHeight);
LogManager.Info($"【阶段2.6完成】通道高度约束设置后网格统计: {channelCoverage.GridMap.GetStatistics()}");
// 3. 应用车辆尺寸膨胀(如果需要)
if (vehicleRadius > 0 || safetyMargin > 0)
{
- LogManager.Info("【包围盒2.5D模式】步骤3: 应用车辆膨胀");
+ LogManager.Info("【生成网格地图】步骤3: 应用车辆膨胀");
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
double totalInflationRadius = (vehicleRadius + safetyMargin) * metersToModelUnits;
ApplyVehicleInflation(channelCoverage.GridMap, totalInflationRadius);
- LogManager.Info($"【包围盒2.5D模式】车辆膨胀完成,膨胀半径: {totalInflationRadius:F2}模型单位");
+ LogManager.Info($"【生成网格地图】车辆膨胀完成,膨胀半径: {totalInflationRadius:F2}模型单位");
LogManager.Info($"【阶段3完成】车辆膨胀后网格统计: {channelCoverage.GridMap.GetStatistics()}");
}
@@ -276,22 +132,22 @@ namespace NavisworksTransport.PathPlanning
if (channelRelatedItems != null && channelRelatedItems.Any())
{
channelCoverage.GridMap.ChannelItems = channelRelatedItems.ToList();
- LogManager.Info($"【包围盒2.5D模式】已将 {channelRelatedItems.Count} 个通道数据设置到GridMap中");
+ LogManager.Info($"【生成网格地图】已将 {channelRelatedItems.Count} 个通道数据设置到GridMap中");
}
else if (channelCoverage.ChannelItems != null && channelCoverage.ChannelItems.Any())
{
channelCoverage.GridMap.ChannelItems = new List(channelCoverage.ChannelItems);
- LogManager.Info($"【包围盒2.5D模式】已将 {channelCoverage.ChannelItems.Count} 个通道数据设置到GridMap中");
+ LogManager.Info($"【生成网格地图】已将 {channelCoverage.ChannelItems.Count} 个通道数据设置到GridMap中");
}
var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
- LogManager.Info($"【包围盒2.5D模式】网格地图生成完成: {channelCoverage.GridMap.GetStatistics()}");
- LogManager.Info($"【包围盒2.5D模式】总耗时: {elapsed:F1}ms");
+ LogManager.Info($"【生成网格地图】网格地图生成完成: {channelCoverage.GridMap.GetStatistics()}");
+ LogManager.Info($"【生成网格地图】总耗时: {elapsed:F1}ms");
return channelCoverage.GridMap;
}
catch (Exception ex)
{
- LogManager.Error($"【包围盒2.5D模式】生成失败: {ex.Message}");
+ LogManager.Error($"【生成网格地图】生成失败: {ex.Message}");
return null;
}
}