优化通行空间可视化功能,自动根据路径类型切换可视化模式,并优化相关渲染逻辑
This commit is contained in:
parent
ddf44b887f
commit
bc1ad3f4c3
26
IFLOW.md
26
IFLOW.md
@ -292,6 +292,32 @@ msiexec /i NavisworksTransport.Setup.msi /qn /l*v install.log
|
||||
|
||||
## 开发约定
|
||||
|
||||
### 代码分析方法
|
||||
|
||||
**重要教训:分析可视化功能时的错误思考方式**
|
||||
|
||||
在分析"通行空间可视化"功能时,犯了以下错误:
|
||||
|
||||
1. **错误:只看方法名,不看实现**
|
||||
- 搜索到 `UpdateGridVisualizationSettings()` 等方法名中包含"Grid",就误以为需要生成网格地图
|
||||
- 实际上这里的"网格"指的是路径规划用的网格地图,而通行空间可视化只是改变路径的渲染风格
|
||||
|
||||
2. **错误:没有深入查看渲染代码**
|
||||
- 虽然找到了 `PathPointRenderPlugin.cs`,但没有仔细看它的渲染逻辑
|
||||
- 应该先看渲染插件如何渲染路径,发现 `PathVisualizationMode.VehicleSpace` 模式
|
||||
|
||||
3. **错误:被表面信息误导**
|
||||
- 日志显示"[网格可视化] 无缓存网格地图",就以为需要生成网格地图
|
||||
- 实际上通行空间可视化不是生成新的可视化内容,而是改变现有路径的渲染方式(从圆柱体改为高高度长方体)
|
||||
|
||||
**正确的分析方法应该是**:
|
||||
|
||||
1. **先看渲染代码**:对于可视化功能,应该先看渲染插件的代码(如 `PathPointRenderPlugin.cs`)
|
||||
2. **理解本质**:问自己"这个功能是什么",而不是"怎么做"。通行空间可视化是"改变渲染风格",而不是"生成网格地图"
|
||||
3. **查看现有实现**:如果日志中已经有相关提示(如"路径可视化模式已更改: 车辆通行空间"),说明功能已经存在,只需要在合适的时机调用
|
||||
4. **不要只看方法名**:方法名可能误导,要看实际实现代码
|
||||
5. **深入查看核心代码**:对于可视化、动画等功能,应该先看对应的渲染/动画管理器的代码
|
||||
|
||||
### 架构模式
|
||||
|
||||
- **MVVM模式**: WPF UI开发使用MVVM架构
|
||||
|
||||
@ -9,7 +9,7 @@ cell_size_meters = 0.5
|
||||
max_height_diff_meters = 0.35
|
||||
|
||||
# 车辆长度(米)
|
||||
vehicle_length_meters = 1.0
|
||||
vehicle_length_meters = 1.2
|
||||
|
||||
# 车辆宽度(米)
|
||||
vehicle_width_meters = 1.0
|
||||
|
||||
@ -1244,7 +1244,7 @@ namespace NavisworksTransport
|
||||
|
||||
// 地面路径使用曲线化后的路径(Edges)
|
||||
// 空轨路径只显示控制点连线,不显示路径连线
|
||||
// 吊装路径使用控制点连线,不显示路径连线
|
||||
// 吊装路径使用控制点连线,不显示路径连线(除非启用通行空间可视化)
|
||||
if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail)
|
||||
{
|
||||
// 空轨路径:只显示控制点连线,不构建路径连线
|
||||
@ -1252,8 +1252,17 @@ namespace NavisworksTransport
|
||||
}
|
||||
else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
|
||||
{
|
||||
// 吊装路径:只显示控制点连线,不构建路径连线
|
||||
LogManager.Debug($"[路径渲染] 吊装路径只显示控制点连线,不显示路径连线");
|
||||
// 吊装路径:默认只显示控制点连线
|
||||
// 但如果启用了通行空间可视化模式,则构建路径连线以显示通行空间
|
||||
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
|
||||
{
|
||||
LogManager.Debug($"[路径渲染] 吊装路径启用通行空间可视化,构建路径连线");
|
||||
BuildPathLines(visualization, sortedPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Debug($"[路径渲染] 吊装路径只显示控制点连线,不显示路径连线");
|
||||
}
|
||||
}
|
||||
else if (visualization.PathRoute.Edges != null && visualization.PathRoute.Edges.Count > 0)
|
||||
{
|
||||
@ -1327,6 +1336,14 @@ namespace NavisworksTransport
|
||||
{
|
||||
var edges = visualization.PathRoute.Edges;
|
||||
|
||||
// 处理 Edges 为空的情况(如吊装路径未经过曲线化)
|
||||
if (edges == null || edges.Count == 0)
|
||||
{
|
||||
LogManager.Debug($"[路径渲染] Edges 为空,直接使用路径点构建直线连线");
|
||||
BuildDirectPathLines(visualization, sortedPoints);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 收集在路径上的控制点ID
|
||||
var onPathPointIds = new HashSet<string>();
|
||||
foreach (var edge in edges)
|
||||
@ -1360,8 +1377,21 @@ namespace NavisworksTransport
|
||||
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
|
||||
{
|
||||
// VehicleSpace 模式:使用车辆高度和宽度
|
||||
heightInMeters = _vehicleHeight + _safetyMargin;
|
||||
widthInMeters = Math.Max(_vehicleLength, _vehicleWidth) + 2 * _safetyMargin;
|
||||
// 根据路径类型调整参数
|
||||
if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
|
||||
{
|
||||
// 吊装路径:通行空间截面使用车辆的宽度和长度(不是高度)
|
||||
heightInMeters = _vehicleLength + _safetyMargin; // Y方向使用车辆长度
|
||||
widthInMeters = _vehicleWidth + 2 * _safetyMargin; // X方向使用车辆宽度
|
||||
LogManager.Info($"[通行空间渲染] 吊装路径: 车辆参数(长×宽×高)={_vehicleLength:F2}×{_vehicleWidth:F2}×{_vehicleHeight:F2}m, 安全间隙={_safetyMargin:F2}m, 通行空间截面(宽×高)={widthInMeters:F2}×{heightInMeters:F2}m");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 地面路径和空轨:使用最大宽度和高度
|
||||
heightInMeters = _vehicleHeight + _safetyMargin;
|
||||
widthInMeters = _vehicleWidth + 2 * _safetyMargin;
|
||||
LogManager.Info($"[通行空间渲染] {visualization.PathRoute.PathType}路径: 车辆参数(长×宽×高)={_vehicleLength:F2}×{_vehicleWidth:F2}×{_vehicleHeight:F2}m, 安全间隙={_safetyMargin:F2}m, 通行空间截面(宽×高)={widthInMeters:F2}×{heightInMeters:F2}m");
|
||||
}
|
||||
var renderStyle = GetRenderStyle(RenderStyleName.VehicleSpace);
|
||||
lineColor = renderStyle.Color;
|
||||
lineOpacity = renderStyle.Alpha;
|
||||
@ -1389,6 +1419,23 @@ namespace NavisworksTransport
|
||||
double heightInModelUnits = heightInMeters * metersToModelUnits;
|
||||
double widthInModelUnits = widthInMeters * metersToModelUnits;
|
||||
|
||||
// 计算通行空间的垂直偏移(根据路径类型)
|
||||
double verticalOffset = 0;
|
||||
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
|
||||
{
|
||||
if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Ground)
|
||||
{
|
||||
// 地面路径:路径点是地面位置,通行空间底面在地面,中心需要向上偏移半个高度
|
||||
verticalOffset = heightInModelUnits / 2.0;
|
||||
}
|
||||
else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail)
|
||||
{
|
||||
// 空轨路径:路径点是空轨下表面位置,通行空间顶面在空轨下表面,中心需要向下偏移半个高度
|
||||
verticalOffset = -heightInModelUnits / 2.0;
|
||||
}
|
||||
// 吊装路径:路径点是设备中心位置,不需要偏移
|
||||
}
|
||||
|
||||
// 3. 构建路径连线(Edges包含直线段和圆弧段)
|
||||
foreach (var edge in edges)
|
||||
{
|
||||
@ -1397,10 +1444,17 @@ namespace NavisworksTransport
|
||||
// 直线段:检查SampledPoints是否有效
|
||||
if (edge.SampledPoints != null && edge.SampledPoints.Count >= 2)
|
||||
{
|
||||
var startPoint = edge.SampledPoints.First();
|
||||
var endPoint = edge.SampledPoints.Last();
|
||||
|
||||
// 根据路径类型调整起点和终点位置
|
||||
var adjustedStartPoint = new Point3D(startPoint.X, startPoint.Y, startPoint.Z + verticalOffset);
|
||||
var adjustedEndPoint = new Point3D(endPoint.X, endPoint.Y, endPoint.Z + verticalOffset);
|
||||
|
||||
var lineMarker = new LineMarker
|
||||
{
|
||||
StartPoint = edge.SampledPoints.First(),
|
||||
EndPoint = edge.SampledPoints.Last(),
|
||||
StartPoint = adjustedStartPoint,
|
||||
EndPoint = adjustedEndPoint,
|
||||
Color = lineColor,
|
||||
Radius = GetLineRadius(),
|
||||
SegmentType = PathSegmentType.Straight,
|
||||
@ -1429,10 +1483,17 @@ namespace NavisworksTransport
|
||||
arcLineOpacity = warningStyle.Alpha;
|
||||
}
|
||||
|
||||
var startPoint = edge.Trajectory.Ts;
|
||||
var endPoint = edge.Trajectory.Te;
|
||||
|
||||
// 根据路径类型调整起点和终点位置
|
||||
var adjustedStartPoint = new Point3D(startPoint.X, startPoint.Y, startPoint.Z + verticalOffset);
|
||||
var adjustedEndPoint = new Point3D(endPoint.X, endPoint.Y, endPoint.Z + verticalOffset);
|
||||
|
||||
var arcMarker = new LineMarker
|
||||
{
|
||||
StartPoint = edge.Trajectory.Ts,
|
||||
EndPoint = edge.Trajectory.Te,
|
||||
StartPoint = adjustedStartPoint,
|
||||
EndPoint = adjustedEndPoint,
|
||||
Color = arcLineColor,
|
||||
Radius = GetLineRadius(),
|
||||
SegmentType = PathSegmentType.Arc,
|
||||
@ -1453,6 +1514,114 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 直接使用路径点构建直线连线(用于吊装路径等未曲线化的路径)
|
||||
/// </summary>
|
||||
/// <param name="visualization">路径可视化对象</param>
|
||||
/// <param name="sortedPoints">排序后的路径点列表</param>
|
||||
private void BuildDirectPathLines(PathVisualization visualization, List<PathPoint> sortedPoints)
|
||||
{
|
||||
if (sortedPoints == null || sortedPoints.Count < 2)
|
||||
return;
|
||||
|
||||
// 获取单位转换系数
|
||||
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
|
||||
|
||||
// 根据可视化模式计算高度和宽度
|
||||
double heightInMeters;
|
||||
double widthInMeters;
|
||||
Color lineColor;
|
||||
double lineOpacity;
|
||||
|
||||
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
|
||||
{
|
||||
// VehicleSpace 模式:使用车辆高度和宽度
|
||||
// 根据路径类型调整参数
|
||||
if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
|
||||
{
|
||||
// 吊装路径:通行空间截面使用车辆的宽度和长度(不是高度)
|
||||
heightInMeters = _vehicleLength + _safetyMargin; // Y方向使用车辆长度
|
||||
widthInMeters = _vehicleWidth + 2 * _safetyMargin; // X方向使用车辆宽度
|
||||
LogManager.Info($"[通行空间渲染] 吊装路径(直接连线): 车辆参数(长×宽×高)={_vehicleLength:F2}×{_vehicleWidth:F2}×{_vehicleHeight:F2}m, 安全间隙={_safetyMargin:F2}m, 通行空间截面(宽×高)={widthInMeters:F2}×{heightInMeters:F2}m");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 地面路径和空轨:使用最大宽度和高度
|
||||
heightInMeters = _vehicleHeight + _safetyMargin;
|
||||
widthInMeters = _vehicleWidth + 2 * _safetyMargin;
|
||||
LogManager.Info($"[通行空间渲染] {visualization.PathRoute.PathType}路径(直接连线): 车辆参数(长×宽×高)={_vehicleLength:F2}×{_vehicleWidth:F2}×{_vehicleHeight:F2}m, 安全间隙={_safetyMargin:F2}m, 通行空间截面(宽×高)={widthInMeters:F2}×{heightInMeters:F2}m");
|
||||
}
|
||||
var renderStyle = GetRenderStyle(RenderStyleName.VehicleSpace);
|
||||
lineColor = renderStyle.Color;
|
||||
lineOpacity = renderStyle.Alpha;
|
||||
}
|
||||
else if (_visualizationMode == PathVisualizationMode.RibbonLine)
|
||||
{
|
||||
// RibbonLine 模式:使用较低的带状高度
|
||||
heightInMeters = GetLineRadius() / metersToModelUnits * 0.1;
|
||||
widthInMeters = GetLineRadius() / metersToModelUnits * 2; // 路径宽度(转换为米)
|
||||
var renderStyle = GetRenderStyle(RenderStyleName.Line);
|
||||
lineColor = renderStyle.Color;
|
||||
lineOpacity = renderStyle.Alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
// StandardLine 模式:不需要高度和宽度(圆柱体)
|
||||
heightInMeters = 0;
|
||||
widthInMeters = 0;
|
||||
var renderStyle = GetRenderStyle(RenderStyleName.Line);
|
||||
lineColor = renderStyle.Color;
|
||||
lineOpacity = renderStyle.Alpha;
|
||||
}
|
||||
|
||||
// 转换为模型单位
|
||||
double heightInModelUnits = heightInMeters * metersToModelUnits;
|
||||
double widthInModelUnits = widthInMeters * metersToModelUnits;
|
||||
|
||||
// 计算通行空间的垂直偏移(根据路径类型)
|
||||
double verticalOffset = 0;
|
||||
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
|
||||
{
|
||||
if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Ground)
|
||||
{
|
||||
// 地面路径:路径点是地面位置,通行空间底面在地面,中心需要向上偏移半个高度
|
||||
verticalOffset = heightInModelUnits / 2.0;
|
||||
}
|
||||
else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail)
|
||||
{
|
||||
// 空轨路径:路径点是空轨下表面位置,通行空间顶面在空轨下表面,中心需要向下偏移半个高度
|
||||
verticalOffset = -heightInModelUnits / 2.0;
|
||||
}
|
||||
// 吊装路径:路径点是设备中心位置,不需要偏移
|
||||
}
|
||||
|
||||
// 直接使用路径点构建直线连线
|
||||
for (int i = 0; i < sortedPoints.Count - 1; i++)
|
||||
{
|
||||
var startPoint = sortedPoints[i];
|
||||
var endPoint = sortedPoints[i + 1];
|
||||
|
||||
// 根据路径类型调整起点和终点位置
|
||||
var adjustedStartPoint = new Point3D(startPoint.Position.X, startPoint.Position.Y, startPoint.Position.Z + verticalOffset);
|
||||
var adjustedEndPoint = new Point3D(endPoint.Position.X, endPoint.Position.Y, endPoint.Position.Z + verticalOffset);
|
||||
|
||||
var lineMarker = new LineMarker
|
||||
{
|
||||
StartPoint = adjustedStartPoint,
|
||||
EndPoint = adjustedEndPoint,
|
||||
Color = lineColor,
|
||||
Radius = GetLineRadius(),
|
||||
SegmentType = PathSegmentType.Straight,
|
||||
FromIndex = startPoint.Index,
|
||||
ToIndex = endPoint.Index,
|
||||
Height = heightInModelUnits, // 根据模式设置高度
|
||||
Width = widthInModelUnits, // 根据模式设置宽度
|
||||
Opacity = lineOpacity // 根据模式设置透明度
|
||||
};
|
||||
visualization.PathLineMarkers.Add(lineMarker);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加切点标记
|
||||
/// </summary>
|
||||
@ -2247,20 +2416,35 @@ namespace NavisworksTransport
|
||||
right = new Vector3D(right.X / rightLength, right.Y / rightLength, right.Z / rightLength);
|
||||
}
|
||||
|
||||
// 计算高度向量(垂直于方向向量和宽度向量)
|
||||
var up = new Vector3D(
|
||||
direction.Y * right.Z - direction.Z * right.Y,
|
||||
direction.Z * right.X - direction.X * right.Z,
|
||||
direction.X * right.Y - direction.Y * right.X
|
||||
);
|
||||
|
||||
// 归一化up向量
|
||||
var upLength = Math.Sqrt(up.X * up.X + up.Y * up.Y + up.Z * up.Z);
|
||||
if (upLength > 0.001)
|
||||
{
|
||||
up = new Vector3D(up.X / upLength, up.Y / upLength, up.Z / upLength);
|
||||
}
|
||||
|
||||
// 计算长方体的边界框和向量
|
||||
var halfWidth = width / 2.0;
|
||||
var halfHeight = height / 2.0;
|
||||
|
||||
// 计算立方体原点(起点左下角)
|
||||
// 计算立方体原点(使长方体中心在起点位置)
|
||||
var origin = new Point3D(
|
||||
startPoint.X - halfWidth * right.X,
|
||||
startPoint.Y - halfWidth * right.Y,
|
||||
startPoint.Z
|
||||
startPoint.X - halfWidth * right.X - halfHeight * up.X,
|
||||
startPoint.Y - halfWidth * right.Y - halfHeight * up.Y,
|
||||
startPoint.Z - halfWidth * right.Z - halfHeight * up.Z
|
||||
);
|
||||
|
||||
// 定义立方体的三个轴向量
|
||||
var xVector = new Vector3D(direction.X * length, direction.Y * length, direction.Z * length); // 长度方向
|
||||
var yVector = new Vector3D(right.X * width, right.Y * width, right.Z * width); // 宽度方向
|
||||
var zVector = new Vector3D(0, 0, height); // 高度方向
|
||||
var xVector = new Vector3D(direction.X * length, direction.Y * length, direction.Z * length); // 长度方向(沿路径)
|
||||
var yVector = new Vector3D(right.X * width, right.Y * width, right.Z * width); // 宽度方向(垂直于路径)
|
||||
var zVector = new Vector3D(up.X * height, up.Y * height, up.Z * height); // 高度方向(垂直于路径和宽度)
|
||||
|
||||
// 使用Cuboid API渲染长方体
|
||||
graphics.Cuboid(origin, xVector, yVector, zVector, true);
|
||||
@ -2333,20 +2517,35 @@ namespace NavisworksTransport
|
||||
right = new Vector3D(right.X / rightLength, right.Y / rightLength, right.Z / rightLength);
|
||||
}
|
||||
|
||||
// 计算高度向量(垂直于方向向量和宽度向量)
|
||||
var up = new Vector3D(
|
||||
direction.Y * right.Z - direction.Z * right.Y,
|
||||
direction.Z * right.X - direction.X * right.Z,
|
||||
direction.X * right.Y - direction.Y * right.X
|
||||
);
|
||||
|
||||
// 归一化up向量
|
||||
var upLength = Math.Sqrt(up.X * up.X + up.Y * up.Y + up.Z * up.Z);
|
||||
if (upLength > 0.001)
|
||||
{
|
||||
up = new Vector3D(up.X / upLength, up.Y / upLength, up.Z / upLength);
|
||||
}
|
||||
|
||||
// 计算长方体的边界框和向量
|
||||
var halfWidth = width / 2.0;
|
||||
var halfHeight = height / 2.0;
|
||||
|
||||
// 计算立方体原点(起点左下角)
|
||||
// 计算立方体原点(使长方体中心在起点位置)
|
||||
var origin = new Point3D(
|
||||
startPoint.X - halfWidth * right.X,
|
||||
startPoint.Y - halfWidth * right.Y,
|
||||
startPoint.Z
|
||||
startPoint.X - halfWidth * right.X - halfHeight * up.X,
|
||||
startPoint.Y - halfWidth * right.Y - halfHeight * up.Y,
|
||||
startPoint.Z - halfWidth * right.Z - halfHeight * up.Z
|
||||
);
|
||||
|
||||
// 定义立方体的三个轴向量
|
||||
var xVector = new Vector3D(direction.X * length, direction.Y * length, direction.Z * length); // 使用指定长度
|
||||
var yVector = new Vector3D(right.X * width, right.Y * width, right.Z * width); // 宽度方向
|
||||
var zVector = new Vector3D(0, 0, height); // 高度方向
|
||||
var xVector = new Vector3D(direction.X * length, direction.Y * length, direction.Z * length); // 使用指定长度(沿路径)
|
||||
var yVector = new Vector3D(right.X * width, right.Y * width, right.Z * width); // 宽度方向(垂直于路径)
|
||||
var zVector = new Vector3D(up.X * height, up.Y * height, up.Z * height); // 高度方向(垂直于路径和宽度)
|
||||
|
||||
// 使用Cuboid API渲染长方体
|
||||
graphics.Cuboid(origin, xVector, yVector, zVector, true);
|
||||
|
||||
@ -468,6 +468,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
// 预计算排除列表(异步)
|
||||
_ = PrecomputeCollisionExclusionsAsync(value);
|
||||
|
||||
// 当选择了物体时,根据路径类型打开通行空间可视化
|
||||
if (value != null)
|
||||
{
|
||||
UpdatePassageSpaceVisualization();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -540,6 +546,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
var points = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList();
|
||||
_pathAnimationManager?.MoveVehicleToPathStart(vModel, points);
|
||||
}
|
||||
|
||||
// 当切换到虚拟车辆模式时,根据路径类型打开通行空间可视化
|
||||
UpdatePassageSpaceVisualization();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -2386,6 +2395,211 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据路径类型更新通行空间可视化
|
||||
/// 空轨和吊装路径默认打开通行空间(车辆通行空间模式),地面路径不打开
|
||||
/// 根据选择的物体或虚拟车辆尺寸更新通行空间渲染
|
||||
/// </summary>
|
||||
private void UpdatePassageSpaceVisualization()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (CurrentPathRoute == null)
|
||||
{
|
||||
LogManager.Debug("[通行空间可视化] 没有选择路径,跳过更新");
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据路径类型决定是否打开通行空间
|
||||
bool enableVehicleSpace = false;
|
||||
|
||||
switch (CurrentPathRoute.PathType)
|
||||
{
|
||||
case NavisworksTransport.PathType.Rail:
|
||||
case NavisworksTransport.PathType.Hoisting:
|
||||
enableVehicleSpace = true;
|
||||
LogManager.Info($"[通行空间可视化] 路径类型={CurrentPathRoute.PathType},自动切换到车辆通行空间模式");
|
||||
break;
|
||||
|
||||
case NavisworksTransport.PathType.Ground:
|
||||
enableVehicleSpace = false;
|
||||
LogManager.Debug($"[通行空间可视化] 路径类型={CurrentPathRoute.PathType},不切换到车辆通行空间模式");
|
||||
break;
|
||||
|
||||
default:
|
||||
LogManager.Warning($"[通行空间可视化] 未知的路径类型: {CurrentPathRoute.PathType}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置路径可视化模式
|
||||
if (enableVehicleSpace)
|
||||
{
|
||||
var renderPlugin = PathPointRenderPlugin.Instance;
|
||||
if (renderPlugin != null)
|
||||
{
|
||||
// 获取车辆尺寸(米)
|
||||
double vehicleLength, vehicleWidth, vehicleHeight;
|
||||
|
||||
if (UseVirtualVehicle)
|
||||
|
||||
{
|
||||
|
||||
// 使用虚拟车辆尺寸,但需要根据路径类型调整
|
||||
|
||||
if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Hoisting)
|
||||
|
||||
{
|
||||
|
||||
// 吊装路径:通行空间截面使用车辆的宽度和长度(不是高度)
|
||||
|
||||
vehicleWidth = VirtualVehicleWidth; // X方向
|
||||
|
||||
vehicleHeight = VirtualVehicleLength; // Y方向(使用车辆长度)
|
||||
|
||||
// 计算路径的Z长度差
|
||||
|
||||
if (CurrentPathRoute.Points.Count >= 2)
|
||||
|
||||
{
|
||||
|
||||
var startPoint = CurrentPathRoute.Points.First();
|
||||
|
||||
var endPoint = CurrentPathRoute.Points.Last();
|
||||
|
||||
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
|
||||
|
||||
vehicleLength = Math.Abs(endPoint.Z - startPoint.Z) / metersToModelUnits;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
{
|
||||
|
||||
vehicleLength = VirtualVehicleLength; // fallback
|
||||
|
||||
}
|
||||
|
||||
LogManager.Info($"[通行空间可视化] 吊装路径使用虚拟车辆尺寸: 宽×高×长={vehicleWidth:F2}×{vehicleHeight:F2}×{vehicleLength:F2}m");
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
{
|
||||
|
||||
// 地面路径和空轨:使用虚拟车辆的宽度和高度
|
||||
|
||||
vehicleWidth = VirtualVehicleWidth; // 通行空间宽度 = 车辆宽度(垂直于路径方向)
|
||||
|
||||
vehicleHeight = VirtualVehicleHeight; // 通行空间高度 = 车辆高度
|
||||
|
||||
vehicleLength = VirtualVehicleLength; // 车辆长度(沿路径方向)
|
||||
|
||||
LogManager.Info($"[通行空间可视化] 地面/空轨路径使用虚拟车辆尺寸: 通行空间宽×高={vehicleWidth:F2}×{vehicleHeight:F2}m, 车辆长度={vehicleLength:F2}m");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else if (SelectedAnimatedObject != null)
|
||||
{
|
||||
// 使用选择物体的包围盒尺寸
|
||||
try
|
||||
{
|
||||
var bbox = SelectedAnimatedObject.BoundingBox();
|
||||
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
|
||||
|
||||
// 将模型单位转换为米
|
||||
double sizeX = (bbox.Max.X - bbox.Min.X) / metersToModelUnits;
|
||||
double sizeY = (bbox.Max.Y - bbox.Min.Y) / metersToModelUnits;
|
||||
double sizeZ = (bbox.Max.Z - bbox.Min.Z) / metersToModelUnits;
|
||||
|
||||
// 根据路径类型确定车辆的长度、宽度、高度
|
||||
if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Hoisting)
|
||||
{
|
||||
// 吊装路径(严格垂直路径):
|
||||
// - 宽度 = X方向尺寸
|
||||
// - 高度 = Y方向尺寸
|
||||
// - 长度 = 路径起点到终点的Z值差
|
||||
vehicleWidth = sizeX;
|
||||
vehicleHeight = sizeY;
|
||||
|
||||
// 计算路径的Z长度差
|
||||
if (CurrentPathRoute.Points.Count >= 2)
|
||||
{
|
||||
var startPoint = CurrentPathRoute.Points.First();
|
||||
var endPoint = CurrentPathRoute.Points.Last();
|
||||
vehicleLength = Math.Abs(endPoint.Z - startPoint.Z) / metersToModelUnits;
|
||||
}
|
||||
else
|
||||
{
|
||||
vehicleLength = sizeZ; // fallback
|
||||
}
|
||||
|
||||
LogManager.Info($"[通行空间可视化] 吊装路径使用物体XY尺寸 ({SelectedAnimatedObject.DisplayName}): 宽={vehicleWidth:F2}m, 高={vehicleHeight:F2}m, 长度(路径Z差)={vehicleLength:F2}m");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 地面路径和空轨(可能有坡度):
|
||||
// - 物体的Z轴和路径垂直
|
||||
// - 通行空间宽度 = 车辆的宽度(垂直于路径方向)
|
||||
// - 通行空间高度 = 车辆的高度(Z方向)
|
||||
// - 通行空间长度 = 由路径起点和终点决定
|
||||
vehicleLength = Math.Max(sizeX, sizeY); // 车辆沿路径方向的长度
|
||||
vehicleWidth = Math.Min(sizeX, sizeY); // 通行空间宽度 = 车辆的宽度(垂直于路径方向)
|
||||
vehicleHeight = sizeZ; // 通行空间高度 = 车辆的高度
|
||||
LogManager.Info($"[通行空间可视化] 地面/空轨路径使用物体尺寸 ({SelectedAnimatedObject.DisplayName}): 通行空间宽×高={vehicleWidth:F2}×{vehicleHeight:F2}m, 车辆长度={vehicleLength:F2}m");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[通行空间可视化] 获取物体包围盒失败: {ex.Message},使用默认尺寸");
|
||||
vehicleLength = 1.0;
|
||||
vehicleWidth = 1.0;
|
||||
vehicleHeight = 2.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 没有选择物体,使用默认尺寸
|
||||
vehicleLength = 1.0;
|
||||
vehicleWidth = 1.0;
|
||||
vehicleHeight = 2.0;
|
||||
LogManager.Info("[通行空间可视化] 使用默认车辆尺寸: 1.0×1.0×2.0m");
|
||||
}
|
||||
|
||||
// 获取安全间隙(从配置)
|
||||
var config = Core.Config.ConfigManager.Instance?.Current;
|
||||
double safetyMargin = config?.PathEditing?.SafetyMarginMeters ?? 0.05;
|
||||
|
||||
// 设置车辆参数到渲染插件
|
||||
renderPlugin.SetVehicleParameters(vehicleLength, vehicleWidth, vehicleHeight, safetyMargin);
|
||||
LogManager.Info($"[通行空间可视化] 已设置车辆参数: {vehicleLength:F2}×{vehicleWidth:F2}×{vehicleHeight:F2}m, 安全间隙: {safetyMargin:F2}m");
|
||||
|
||||
// 切换到车辆通行空间模式
|
||||
renderPlugin.VisualizationMode = PathVisualizationMode.VehicleSpace;
|
||||
LogManager.Info("[通行空间可视化] 已切换到车辆通行空间模式");
|
||||
|
||||
// 刷新路径可视化以应用新的尺寸
|
||||
var coreRoute = PathPlanningManager.Instance?.Routes?.FirstOrDefault(r => r.Id == CurrentPathRoute.Id);
|
||||
if (coreRoute != null)
|
||||
{
|
||||
PathPlanningManager.Instance.DrawRouteVisualization(coreRoute, isAutoPath: false);
|
||||
LogManager.Info("[通行空间可视化] 已刷新路径可视化");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("[通行空间可视化] 无法获取PathPointRenderPlugin实例");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[通行空间可视化] 更新失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 递归检查ModelItem是否包含几何体
|
||||
/// </summary>
|
||||
|
||||
@ -127,6 +127,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
_pathPlanningManager.SetCurrentRoute(coreRoute);
|
||||
LogManager.Info($"UI路径切换:已同步PathPlanningManager的CurrentRoute到 {value.Name}");
|
||||
|
||||
// 根据路径类型自动设置通行空间可视化
|
||||
UpdatePassageSpaceVisualizationForPathType(coreRoute.PathType);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2675,6 +2678,47 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据路径类型自动设置通行空间可视化
|
||||
/// 空轨和吊装路径自动打开通行空间,地面路径不打开
|
||||
/// </summary>
|
||||
private void UpdatePassageSpaceVisualizationForPathType(PathType pathType)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool enableVehicleSpace = false;
|
||||
|
||||
switch (pathType)
|
||||
{
|
||||
case PathType.Rail:
|
||||
case PathType.Hoisting:
|
||||
enableVehicleSpace = true;
|
||||
LogManager.Info($"[路径编辑] 路径类型={pathType},自动打开通行空间可视化");
|
||||
break;
|
||||
|
||||
case PathType.Ground:
|
||||
enableVehicleSpace = false;
|
||||
LogManager.Debug($"[路径编辑] 路径类型={pathType},不打开通行空间可视化");
|
||||
break;
|
||||
|
||||
default:
|
||||
LogManager.Warning($"[路径编辑] 未知的路径类型: {pathType}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置通行空间可视化开关
|
||||
if (enableVehicleSpace)
|
||||
{
|
||||
IsVehicleSpaceMode = true;
|
||||
LogManager.Info("[路径编辑] 已自动打开通行空间可视化开关");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[路径编辑] 设置通行空间可视化失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 路径可视化模式变更事件处理
|
||||
/// </summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user