增加了网格大小设置,修复了子对象被设成障碍物的bug

This commit is contained in:
tian 2025-08-20 20:52:26 +08:00
parent 9c83af59ca
commit 7a5aa413bc
6 changed files with 154 additions and 19 deletions

View File

@ -209,13 +209,11 @@ namespace NavisworksTransport
graphics.Sphere(pointMarker.Center, pointMarker.Radius);
}
// 渲染所有连线
LogManager.WriteLog($"[渲染连线] 路径 {visualization.PathId} 有 {visualization.LineMarkers.Count} 条连线");
// 渲染所有连线(删除频繁的调试日志以避免日志泛滥)
foreach (var lineMarker in visualization.LineMarkers)
{
graphics.Color(lineMarker.Color, 1.0);
graphics.Cylinder(lineMarker.StartPoint, lineMarker.EndPoint, lineMarker.Radius);
LogManager.WriteLog($"[渲染连线] 绘制连线 {lineMarker.FromIndex}->{lineMarker.ToIndex}, 半径={lineMarker.Radius:F3}");
}
}
}

View File

@ -84,12 +84,10 @@ namespace NavisworksTransport.PathPlanning
/// <param name="cellSize">网格单元格大小</param>
public GridMap(BoundingBox3D bounds, double cellSize)
{
if (bounds == null)
throw new ArgumentNullException(nameof(bounds));
if (cellSize <= 0)
throw new ArgumentException("网格单元格大小必须大于0", nameof(cellSize));
Bounds = bounds;
Bounds = bounds ?? throw new ArgumentNullException(nameof(bounds));
CellSize = cellSize;
// 计算网格尺寸

View File

@ -77,24 +77,34 @@ namespace NavisworksTransport.PathPlanning
LogManager.Info($"调整后网格尺寸: {gridWidth}x{gridHeight} = {totalCells}个单元格");
}
// 步骤1先进行楼层过滤获取目标楼层的所有模型项
LogManager.Info("[步骤1] 开始楼层过滤...");
var floorFilteredItems = GetFloorFilteredModelItems(document, planningStartPoint, planningEndPoint);
LogManager.Info($"[步骤1] 楼层过滤完成,共 {floorFilteredItems.Count} 个模型项");
// 步骤1: 获取所有模型项(暂时注释楼层过滤功能)
LogManager.Info("[步骤1] 获取所有模型项(楼层过滤已暂时禁用)...");
var allModelItems = new List<ModelItem>();
foreach (var model in document.Models)
{
if (model.RootItem != null)
{
CollectAllItemsRecursively(model.RootItem, allModelItems);
}
}
LogManager.Info($"[步骤1] 获取到 {allModelItems.Count} 个模型项");
// 步骤2基于楼层过滤结果重新计算工作区域边界
// TODO: 楼层过滤功能已暂时注释,需要时可重新启用
// var floorFilteredItems = GetFloorFilteredModelItems(document, planningStartPoint, planningEndPoint);
var modelItems = allModelItems; // 直接使用所有模型项,不进行楼层过滤
// 步骤2: 基于工作区域重新计算边界(使用所有模型项)
LogManager.Info("[步骤2] 重新计算路径规划工作区域...");
var workingBounds = CalculateWorkingBounds(floorFilteredItems, bounds, planningStartPoint, planningEndPoint);
var workingBounds = CalculateWorkingBounds(modelItems, bounds, planningStartPoint, planningEndPoint);
LogManager.Info($"[步骤2] 工作区域边界: {workingBounds}");
// 步骤3基于工作区域创建网格地图
// 步骤3: 基于工作区域创建网格地图
LogManager.Info("[步骤3] 创建网格地图...");
var gridMap = new GridMap(workingBounds, cellSizeInModelUnits);
LogManager.Info($"[步骤3] 创建网格地图: {gridMap.Width}x{gridMap.Height} = {gridMap.Width * gridMap.Height}个单元格");
// 步骤4只使用楼层过滤后的模型项所有项目都已经在楼层内
var modelItems = floorFilteredItems;
LogManager.Info($"[步骤4] 使用楼层过滤后的 {modelItems.Count} 个模型项进行网格化");
// 步骤4: 使用所有模型项进行网格化(楼层过滤已禁用)
LogManager.Info($"[步骤4] 使用 {modelItems.Count} 个模型项进行网格化(楼层过滤已禁用)");
// 识别障碍物
LogManager.Info("开始识别障碍物...");
@ -283,11 +293,29 @@ namespace NavisworksTransport.PathPlanning
{
try
{
// 1. 检查当前项是否有物流属性
bool hasLogisticsProperty = HasLogisticsProperty(item);
if (hasLogisticsProperty)
{
// 如果当前项有物流属性,将其作为一个整体处理
if (item.HasGeometry)
{
result.Add(item);
LogManager.WriteLog($"[组合模型过滤] 发现有物流属性的模型: {item.DisplayName},作为整体处理,跳过其子项");
}
// 重要:不再递归处理其子项,避免父子属性冲突
// 这样通道的子模型就不会被单独判断为障碍了
return;
}
// 2. 如果当前项没有物流属性,检查其几何体
if (item.HasGeometry)
{
result.Add(item);
}
// 3. 递归处理子项(只有在父项没有物流属性时才递归)
foreach (var child in item.Children)
{
CollectAllItemsRecursively(child, result);

View File

@ -53,6 +53,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private double _vehicleHeight = 2.0; // 车辆高度(米)
private double _safetyMargin = 0.5; // 安全间隙(米)
// 网格大小参数
private bool _isGridSizeManuallyEnabled = false; // 是否启用手动网格大小设置
private double _gridSize = 1.0; // 网格大小(米)
// 路径文件管理
private string _pathFileStatus = "未保存";
@ -156,6 +160,30 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
public bool IsGridSizeManuallyEnabled
{
get => _isGridSizeManuallyEnabled;
set
{
if (SetProperty(ref _isGridSizeManuallyEnabled, value))
{
OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
}
}
}
public double GridSize
{
get => _gridSize;
set
{
if (SetProperty(ref _gridSize, value))
{
OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
}
}
}
public bool IsSelectingStartPoint
{
get => _isSelectingStartPoint;
@ -559,6 +587,15 @@ namespace NavisworksTransport.UI.WPF.ViewModels
_pathPlanningManager.StopClickTool();
}
// 清理所有临时路径,确保干净的起始状态
LogManager.WriteLog("[自动路径规划] 清理所有临时路径和历史渲染对象");
ClearTemporaryAutoPathMarkers();
if (PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.ClearAllPaths(); // 清理所有可能的历史路径
LogManager.WriteLog("[自动路径规划] 已清理所有历史路径对象");
}
// 调用PathPlanningManager的自动路径规划功能
var startPathPoint = new PathPoint
{
@ -576,11 +613,19 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info($"起点: ({_startPoint3D.X:F2}, {_startPoint3D.Y:F2}, {_startPoint3D.Z:F2})");
LogManager.Info($"终点: ({_endPoint3D.X:F2}, {_endPoint3D.Y:F2}, {_endPoint3D.Z:F2})");
// 使用三个车辆尺寸参数的最大值作为vehicleSize以及安全间隙
var vehicleSize = Math.Max(Math.Max(VehicleLength, VehicleWidth), VehicleHeight);
// 计算车辆半径:基于长度和宽度的较大值的一半,高度暂时不参与半径计算
var vehicleRadius = Math.Max(VehicleLength, VehicleWidth) / 2.0;
LogManager.Info($"车辆参数: 长{VehicleLength:F1}m × 宽{VehicleWidth:F1}m × 高{VehicleHeight:F1}m");
LogManager.Info($"计算得出车辆半径: {vehicleRadius:F2}m (基于长宽较大值的一半)");
// 确定网格大小:如果启用手动设置则使用用户设置的值,否则使用-1自动选择
var gridSize = IsGridSizeManuallyEnabled ? GridSize : -1;
LogManager.Info($"网格大小设置: {(IsGridSizeManuallyEnabled ? $" {GridSize:F1}" : "")}");
// 在STA线程中执行Navisworks API调用
var pathRoute = await _pathPlanningManager?.AutoPlanPath(startPathPoint, endPathPoint, vehicleSize, SafetyMargin);
var pathRoute = await _pathPlanningManager?.AutoPlanPath(startPathPoint, endPathPoint, vehicleRadius, SafetyMargin, gridSize);
if (pathRoute != null && pathRoute.Points.Count > 0)
{
@ -619,6 +664,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
// 失败情况下也要清理事件订阅和临时标记
LogManager.WriteLog("[自动路径规划] 规划失败后清理所有状态");
CleanupAutoPathEventSubscriptions();
if (_pathPlanningManager != null)
{
@ -627,6 +673,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 清理临时的起点和终点标记
ClearTemporaryAutoPathMarkers();
// 确保失败后也清理所有可能的残留路径对象
if (PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.ClearAllPaths();
LogManager.WriteLog("[自动路径规划] 规划失败后已清理所有渲染对象");
}
}
}, "自动路径规划");
}

View File

@ -26,6 +26,12 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
<!-- 转换器资源 -->
<converters:BoolToVisibilityConverter x:Key="BoolToVisConverter"/>
<!-- 滑块样式 -->
<Style x:Key="SliderStyle" TargetType="Slider">
<Setter Property="Foreground" Value="{StaticResource NavisworksSecondaryBrush}"/>
<Setter Property="Height" Value="20"/>
</Style>
</ResourceDictionary>
</UserControl.Resources>
@ -112,6 +118,58 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
<Label Grid.Row="1" Grid.Column="5" Content="米" Style="{StaticResource UnitLabelStyle}"/>
</Grid>
<!-- 高级设置区域 -->
<Expander Header="高级设置" IsExpanded="False" Margin="0,10,0,5">
<StackPanel Margin="10">
<!-- 网格大小设置 -->
<Grid Margin="0,5,0,15">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 启用选项 -->
<CheckBox Grid.Row="0"
Content="手动设置网格大小"
IsChecked="{Binding IsGridSizeManuallyEnabled}"
Margin="0,0,0,10"
ToolTip="启用后可手动设置路径规划的网格精度,否则系统根据模型大小自动选择"/>
<!-- 滑块控制 -->
<StackPanel Grid.Row="1" IsEnabled="{Binding IsGridSizeManuallyEnabled}">
<Label Content="网格大小(米)" Style="{StaticResource ParameterLabelStyle}"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Slider Grid.Column="0"
Value="{Binding GridSize}"
Minimum="0.1"
Maximum="5.0"
TickFrequency="0.1"
Style="{StaticResource SliderStyle}"/>
<TextBlock Grid.Column="1"
Text="{Binding GridSize, StringFormat={}{0:F1}}"
VerticalAlignment="Center"
Margin="10,0,0,0"
Width="40"/>
</Grid>
</StackPanel>
<!-- 建议信息 -->
<TextBlock Grid.Row="2"
Text="建议:大型厂区(&gt;1000m)用5米中型建筑(500-1000m)用2米小型建筑(100-500m)用1米精细规划(&lt;100m)用0.5米"
Style="{StaticResource StatusTextStyle}"
TextWrapping="Wrap"
Foreground="#FF666666"
FontStyle="Italic"
Margin="0,5,0,0"/>
</Grid>
</StackPanel>
</Expander>
<!-- 规划操作按钮 -->
<StackPanel Orientation="Horizontal" Margin="0,10,0,5">
<Button Content="自动规划路径"