diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs index 1b0eb88..9f42b3e 100644 --- a/src/Core/PathPlanningManager.cs +++ b/src/Core/PathPlanningManager.cs @@ -58,6 +58,7 @@ namespace NavisworksTransport private bool _showUnknownGrid = false; private bool _showDoorGrid = false; private GridMap _currentGridMap = null; // 保存当前网格地图用于刷新 + private double _currentVehicleHeight = 2.0; // 保存当前车辆高度(米)用于网格刷新 private bool _isPreviewMode = false; private int _previewInsertIndex = -1; // 保存预览点应该插入的索引位置 @@ -955,7 +956,7 @@ namespace NavisworksTransport if (_showWalkableGrid || _showObstacleGrid || _showUnknownGrid || _showDoorGrid) { LogManager.Info("开始网格可视化,显示所有可通行网格单元"); - VisualizeGridCells(gridMap); + VisualizeGridCells(gridMap, vehicleHeight); } // 3. 获取通道高度数据 @@ -3336,7 +3337,7 @@ namespace NavisworksTransport if (_currentGridMap != null && IsAnyGridVisualizationEnabled) { LogManager.Info("[网格可视化] 使用缓存的网格地图重新渲染"); - VisualizeGridCells(_currentGridMap); + VisualizeGridCells(_currentGridMap, _currentVehicleHeight); } else if (_currentGridMap == null) { @@ -3358,7 +3359,8 @@ namespace NavisworksTransport /// 在每个可通行网格的中心绘制一个绿色小球 /// /// 要可视化的网格地图 - public void VisualizeGridCells(GridMap gridMap) + /// 车辆高度(米),用于判断层高是否足够 + public void VisualizeGridCells(GridMap gridMap, double vehicleHeight = 2.0) { if (gridMap == null) { @@ -3368,9 +3370,10 @@ namespace NavisworksTransport try { - // 保存当前网格地图用于后续刷新 + // 保存当前网格地图和车辆高度用于后续刷新 _currentGridMap = gridMap; - LogManager.Info($"[网格可视化] 开始可视化网格:{gridMap.Width}x{gridMap.Height}"); + _currentVehicleHeight = vehicleHeight; + LogManager.Info($"[网格可视化] 开始可视化网格:{gridMap.Width}x{gridMap.Height}, 车辆高度:{vehicleHeight}m"); // 获取渲染插件 var renderPlugin = PathPointRenderPlugin.Instance; @@ -3416,6 +3419,15 @@ namespace NavisworksTransport int openSpaceCells = 0; int doorCells = 0; int totalVisualized = 0; + int multiLayerCells = 0; + int totalLayersVisualized = 0; + int heightInsufficientLayers = 0; + + // 获取车辆高度(模型单位)用于判断层高是否足够 + double vehicleHeightInModelUnits = vehicleHeight * + UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); + + LogManager.Info($"[网格可视化] 车辆高度: {vehicleHeight}m = {vehicleHeightInModelUnits:F2}模型单位"); // 遍历所有网格单元格,根据类型分别收集 for (int x = 0; x < gridMap.Width; x++) @@ -3424,79 +3436,168 @@ namespace NavisworksTransport { var cell = gridMap.Cells[x, y]; - // 计算网格单元格的世界中心位置 + // 计算网格单元格的XY中心位置(Z坐标在多层逻辑中单独处理) var gridPos = new NavisworksTransport.PathPlanning.GridPoint2D(x, y); var gridCorner = gridMap.GridToWorld3D(gridPos); - var gridCenter = new Point3D( - gridCorner.X + gridMap.CellSize / 2, - gridCorner.Y + gridMap.CellSize / 2, - gridCorner.Z - ); + double centerX = gridCorner.X + gridMap.CellSize / 2; + double centerY = gridCorner.Y + gridMap.CellSize / 2; - PathRoute targetRoute = null; - string gridTypeName = ""; + // 检查是否有多个高度层 + if (cell.HeightLayers != null && cell.HeightLayers.Count > 0) + { + // 多层逻辑:遍历每一层,根据PassableHeight判断是否可通行 + multiLayerCells++; - // 根据网格类型和用户设置确定目标路径和名称 - if (cell.IsWalkable && cell.CellType == CategoryAttributeManager.LogisticsElementType.通道) - { - if (_showWalkableGrid) // 检查可通行网格开关 + foreach (var layer in cell.HeightLayers) { - targetRoute = channelRoute; - gridTypeName = "通道"; - channelCells++; - } - } - else if (cell.IsWalkable && cell.CellType == CategoryAttributeManager.LogisticsElementType.门) - { - if (_showDoorGrid) // 检查门网格独立开关 - { - targetRoute = doorRoute; - gridTypeName = "门"; - doorCells++; - } - } - else if (cell.IsWalkable && cell.CellType == CategoryAttributeManager.LogisticsElementType.楼板) - { - if (_showWalkableGrid) // 检查可通行网格开关 - { - targetRoute = channelRoute; // 开放空间也用绿色显示 - gridTypeName = "开放"; - openSpaceCells++; - } - } - else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.Unknown) - { - if (_showUnknownGrid) // 检查未知网格开关 - { - targetRoute = unknownRoute; - gridTypeName = "空洞"; - unknownCells++; - } - } - else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.障碍物) - { - if (_showObstacleGrid) // 检查障碍物网格开关 - { - targetRoute = obstacleRoute; - gridTypeName = "障碍"; - obstacleCells++; - } - } + double layerZ = layer.Z; + double passableHeight = layer.PassableHeight.GetSpan(); - // 如果有对应的路径,创建并添加网格点 - if (targetRoute != null) - { - var gridPoint = new PathPoint - { - Position = gridCenter, - Name = $"网格_{gridTypeName}({x},{y})", - Type = PathPointType.WayPoint, - Index = totalVisualized, - Notes = $"GridType:{cell.CellType}" - }; + // 判断高度是否足够车辆通行 + bool isHeightSufficient = passableHeight >= vehicleHeightInModelUnits; - targetRoute.Points.Add(gridPoint); - totalVisualized++; + // 调试:输出高度不足的层 + if (!isHeightSufficient && multiLayerCells < 5) // 只输出前5个网格的详情 + { + LogManager.Debug($"[高度判断] 网格({x},{y}) Layer Z={layerZ:F2}, PassableH={passableHeight:F2}, 车辆H={vehicleHeightInModelUnits:F2}, 高度足够={isHeightSufficient}"); + } + + PathRoute targetRoute = null; + string gridTypeName = ""; + + // 根据高度是否足够和网格类型决定渲染方式 + if (isHeightSufficient) + { + // 高度足够 - 按原类型渲染 + if (cell.CellType == CategoryAttributeManager.LogisticsElementType.通道) + { + if (_showWalkableGrid) + { + targetRoute = channelRoute; + gridTypeName = "通道"; + channelCells++; + } + } + else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.门) + { + if (_showDoorGrid) + { + targetRoute = doorRoute; + gridTypeName = "门"; + doorCells++; + } + } + else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.楼板) + { + if (_showWalkableGrid) + { + targetRoute = channelRoute; + gridTypeName = "开放"; + openSpaceCells++; + } + } + } + else + { + // 高度不足 - 渲染为障碍物(灰色) + if (_showObstacleGrid) + { + targetRoute = obstacleRoute; + gridTypeName = "障碍_高度不足"; // 必须包含"障碍"关键词才能渲染为灰色 + heightInsufficientLayers++; + } + } + + // 创建该层的可视化点 + if (targetRoute != null) + { + var gridCenter = new Point3D(centerX, centerY, layerZ); + + var gridPoint = new PathPoint + { + Position = gridCenter, + Name = $"网格_{gridTypeName}({x},{y})_Z{layerZ:F2}", + Type = PathPointType.WayPoint, + Index = totalVisualized, + Notes = $"GridType:{cell.CellType}, LayerZ={layerZ:F2}, PassableH={passableHeight:F2}m" + }; + + targetRoute.Points.Add(gridPoint); + totalVisualized++; + totalLayersVisualized++; + } + } + } + else + { + // 单层逻辑:保持原有逻辑不变 + var gridCenter = new Point3D(centerX, centerY, gridCorner.Z); + + PathRoute targetRoute = null; + string gridTypeName = ""; + + // 根据网格类型和用户设置确定目标路径和名称 + if (cell.IsWalkable && cell.CellType == CategoryAttributeManager.LogisticsElementType.通道) + { + if (_showWalkableGrid) + { + targetRoute = channelRoute; + gridTypeName = "通道"; + channelCells++; + } + } + else if (cell.IsWalkable && cell.CellType == CategoryAttributeManager.LogisticsElementType.门) + { + if (_showDoorGrid) + { + targetRoute = doorRoute; + gridTypeName = "门"; + doorCells++; + } + } + else if (cell.IsWalkable && cell.CellType == CategoryAttributeManager.LogisticsElementType.楼板) + { + if (_showWalkableGrid) + { + targetRoute = channelRoute; + gridTypeName = "开放"; + openSpaceCells++; + } + } + else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.Unknown) + { + if (_showUnknownGrid) + { + targetRoute = unknownRoute; + gridTypeName = "空洞"; + unknownCells++; + } + } + else if (cell.CellType == CategoryAttributeManager.LogisticsElementType.障碍物) + { + if (_showObstacleGrid) + { + targetRoute = obstacleRoute; + gridTypeName = "障碍"; + obstacleCells++; + } + } + + // 如果有对应的路径,创建并添加网格点 + if (targetRoute != null) + { + var gridPoint = new PathPoint + { + Position = gridCenter, + Name = $"网格_{gridTypeName}({x},{y})", + Type = PathPointType.WayPoint, + Index = totalVisualized, + Notes = $"GridType:{cell.CellType}" + }; + + targetRoute.Points.Add(gridPoint); + totalVisualized++; + } } } } @@ -3529,14 +3630,17 @@ namespace NavisworksTransport // 输出统计信息 LogManager.Info($"[网格可视化] 可视化完成:"); LogManager.Info($" - 总网格单元格数:{gridMap.Width * gridMap.Height}"); + LogManager.Info($" - 多层网格数:{multiLayerCells}"); LogManager.Info($" - 通道单元格数:{channelCells}"); LogManager.Info($" - 门单元格数:{doorCells}"); LogManager.Info($" - 开放空间单元格数:{openSpaceCells}"); LogManager.Info($" - Unknown单元格数:{unknownCells}"); LogManager.Info($" - 障碍物单元格数:{obstacleCells}"); + LogManager.Info($" - 高度不足层数:{heightInsufficientLayers}"); LogManager.Info($" - 已可视化单元格数:{totalVisualized}"); + LogManager.Info($" - 已可视化层数:{totalLayersVisualized}"); - RaiseStatusChanged($"网格可视化完成:显示了 {totalVisualized} 个网格单元 (通道:{channelCells}, 门:{doorCells}[50%透明], Unknown:{unknownCells}, 障碍:{obstacleCells})", PathPlanningStatusType.Success); + RaiseStatusChanged($"网格可视化完成:显示了 {totalVisualized} 个网格单元 (多层网格:{multiLayerCells}, 通道:{channelCells}, 门:{doorCells}[50%透明], Unknown:{unknownCells}, 障碍:{obstacleCells}, 高度不足:{heightInsufficientLayers})", PathPlanningStatusType.Success); } catch (Exception ex) { diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs index 3e50ca2..ab0c8f3 100644 --- a/src/PathPlanning/GridMapGenerator.cs +++ b/src/PathPlanning/GridMapGenerator.cs @@ -346,6 +346,7 @@ namespace NavisworksTransport.PathPlanning int processedCount = 0; int layerCount = 0; + int stairBottomLayersProcessed = 0; for (int x = 0; x < gridMap.Width; x++) { @@ -354,11 +355,47 @@ namespace NavisworksTransport.PathPlanning var cell = gridMap.Cells[x, y]; if (cell.IsWalkable && cell.HeightLayers != null && cell.HeightLayers.Count > 0) { + // 检查是否是楼梯或电梯网格(有多层且包含楼梯/电梯层) + bool hasStairsOrElevator = cell.HeightLayers.Any(layer => + layer.Type == CategoryAttributeManager.LogisticsElementType.楼梯 || + layer.Type == CategoryAttributeManager.LogisticsElementType.电梯); + // 为每个高度层设置PassableHeight for (int i = 0; i < cell.HeightLayers.Count; i++) { var layer = cell.HeightLayers[i]; - layer.PassableHeight = new HeightInterval(0, scanHeightInModelUnits); + + // 特殊处理:楼梯/电梯的第0层(下方通道层) + if (hasStairsOrElevator && i == 0 && cell.HeightLayers.Count >= 2) + { + // Layer 0是楼梯下方的通道层 + // PassableHeight应该是从层顶到上方楼梯底面的距离 + var upperLayer = cell.HeightLayers[1]; // 楼梯层 + double bottomLayerTop = layer.Z; // 下层顶部 + double upperLayerBottom = upperLayer.Z; // 上层底部 + + // 计算实际可通行高度 + double actualPassableHeight = upperLayerBottom - bottomLayerTop; + + if (actualPassableHeight > 0) + { + layer.PassableHeight = new HeightInterval(0, actualPassableHeight); + stairBottomLayersProcessed++; + LogManager.Debug($"【楼梯下方高度】网格({x},{y}) Layer{i} Z={layer.Z:F2}, 上层Z={upperLayer.Z:F2}, PassableHeight={actualPassableHeight:F2}模型单位"); + } + else + { + // 如果计算出负值或0,使用默认值 + layer.PassableHeight = new HeightInterval(0, scanHeightInModelUnits); + LogManager.Warning($"【楼梯下方高度】网格({x},{y}) Layer{i} 计算高度异常: {actualPassableHeight:F2},使用默认值"); + } + } + else + { + // 普通层或楼梯层本身,使用标准扫描高度 + layer.PassableHeight = new HeightInterval(0, scanHeightInModelUnits); + } + cell.HeightLayers[i] = layer; layerCount++; } @@ -370,6 +407,7 @@ namespace NavisworksTransport.PathPlanning } LogManager.Info($"【高度约束设置】完成,已处理 {processedCount} 个网格,{layerCount} 个高度层"); + LogManager.Info($"【高度约束设置】其中楼梯/电梯下方层: {stairBottomLayersProcessed} 个(使用实际可通行高度)"); } ///