支持多层可视化,并解决楼梯下高度不足的区域网格可视化的问题
This commit is contained in:
parent
59ecebebc4
commit
a4eaf46723
@ -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
|
||||
/// 在每个可通行网格的中心绘制一个绿色小球
|
||||
/// </summary>
|
||||
/// <param name="gridMap">要可视化的网格地图</param>
|
||||
public void VisualizeGridCells(GridMap gridMap)
|
||||
/// <param name="vehicleHeight">车辆高度(米),用于判断层高是否足够</param>
|
||||
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)
|
||||
{
|
||||
|
||||
@ -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} 个(使用实际可通行高度)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user