修改通行空间样式

This commit is contained in:
tian 2026-01-04 17:12:51 +08:00
parent 0702cc879a
commit 174749e287
3 changed files with 235 additions and 128 deletions

View File

@ -506,6 +506,13 @@ namespace NavisworksTransport
{
LogManager.Info($"*** RaiseRouteGenerated被调用: {route?.Name}, Method: {generationMethod}, GridSize: {gridSize} ***");
// 在触发事件前,进行曲线化计算和保存
if (route != null && route.Points.Count >= 2)
{
// 使用统一的曲线化和保存方法
RecalculateAndSaveRoute(route, $"RouteGenerated({generationMethod})");
}
var eventArgs = new RouteGeneratedEventArgs(route, generationMethod, gridSize, _managerId);
// 检查是否有订阅者
@ -587,6 +594,41 @@ namespace NavisworksTransport
{
try
{
// 在触发事件前,检查是否需要重新计算曲线化路径
// 根据 updateReason 判断:
// - "编辑完成":需要重新计算(刚完成编辑)
// - "路径点修改完成":需要重新计算(位置变化)
// - "添加路径点":需要重新计算(新增点)
// - "确认添加预览点":需要重新计算(新增点)
// - "删除路径点":需要重新计算(删除点)
bool needRecalculate = false;
if (route != null && route.Points.Count >= 2)
{
// 检查 Edges 是否为空
if (route.Edges == null || route.Edges.Count == 0)
{
needRecalculate = true;
LogManager.Info($"路径 Edges 为空,需要重新计算: {route.Name}");
}
// 根据更新原因判断
else if (updateReason == "编辑完成" ||
updateReason == "路径点修改完成" ||
updateReason == "添加路径点" ||
updateReason == "确认添加预览点" ||
updateReason == "删除路径点并重新分配类型")
{
needRecalculate = true;
LogManager.Info($"根据更新原因需要重新计算曲线化: {route.Name}, 原因: {updateReason}");
}
}
if (needRecalculate)
{
// 使用统一的曲线化和保存方法
RecalculateAndSaveRoute(route, $"PathPointsListUpdated({updateReason})");
}
var eventArgs = new PathPointsListUpdatedEventArgs(route, updateReason, _managerId);
if (_uiStateManager != null)
@ -1045,8 +1087,6 @@ namespace NavisworksTransport
if (!_routes.Contains(autoRoute))
{
_routes.Add(autoRoute);
// 保存自动生成的路径到数据库
SavePathToDatabase(autoRoute);
}
SetCurrentRouteInternal(autoRoute, triggerEvent: true);
@ -1465,18 +1505,6 @@ namespace NavisworksTransport
}
}
// === 应用曲线化 ===
if (CurrentRoute != null)
{
double samplingStep = ConfigManager.Instance.Current.PathEditing.ArcSamplingStep;
// 使用配置文件中的默认转弯半径
CurrentRoute.TurnRadius = ConfigManager.Instance.Current.PathEditing.DefaultPathTurnRadius;
PathCurveEngine.ApplyCurvatureToRoute(CurrentRoute, samplingStep);
LogManager.Info($"路径曲线化完成: {CurrentRoute.Name}, 转弯半径: {CurrentRoute.TurnRadius:F2}m, 边数: {CurrentRoute.Edges.Count}");
}
// 如果是创建模式,将当前路径添加到路径集合
if (_pathEditState == PathEditState.Creating && CurrentRoute != null)
{
@ -1484,9 +1512,6 @@ namespace NavisworksTransport
{
_routes.Add(CurrentRoute);
// 保存到数据库
SavePathToDatabase(CurrentRoute);
// 添加历史记录
var historyEntry = new PathHistoryEntry(
CurrentRoute.Id,
@ -1500,9 +1525,6 @@ namespace NavisworksTransport
// 如果是编辑模式,保存编辑历史
if (_pathEditState == PathEditState.Editing && EditingRoute != null)
{
// 更新数据库
SavePathToDatabase(EditingRoute);
var historyEntry = new PathHistoryEntry(
EditingRoute.Id,
PathHistoryOperationType.Edited,
@ -1652,9 +1674,6 @@ namespace NavisworksTransport
// 触发路径点列表更新事件
RaisePathPointsListUpdated(CurrentRoute, "路径点修改完成");
// 保存到数据库
SavePathToDatabase(CurrentRoute);
RaiseStatusChanged($"路径点 {pointToUpdate.Name} 修改完成", PathPlanningStatusType.Success);
LogManager.Info($"路径点修改完成: {pointToUpdate.Name}");
@ -2027,9 +2046,6 @@ namespace NavisworksTransport
// 触发路径列表更新事件
RaisePathPointsListUpdated(CurrentRoute, "确认添加预览点");
// 保存到数据库
SavePathToDatabase(CurrentRoute);
return confirmPoint;
}
catch (Exception ex)
@ -2876,6 +2892,40 @@ namespace NavisworksTransport
#endregion
#region
/// <summary>
/// 重新计算曲线化路径并保存到数据库
/// </summary>
/// <param name="route">要计算的路径</param>
/// <param name="context">上下文信息(用于日志)</param>
private void RecalculateAndSaveRoute(PathRoute route, string context)
{
if (route == null || route.Points.Count < 2)
{
LogManager.Info($"跳过曲线化计算(路径点不足): {context}");
return;
}
try
{
double samplingStep = ConfigManager.Instance.Current.PathEditing.ArcSamplingStep;
route.TurnRadius = ConfigManager.Instance.Current.PathEditing.DefaultPathTurnRadius;
PathCurveEngine.ApplyCurvatureToRoute(route, samplingStep);
LogManager.Info($"路径曲线化完成({context}: {route.Name}, 转弯半径: {route.TurnRadius:F2}m, 边数: {route.Edges.Count}");
// 曲线化计算完成后,立即保存数据库
SavePathToDatabase(route);
LogManager.Info($"路径曲线化后已保存到数据库: {route.Name}");
}
catch (Exception ex)
{
LogManager.Error($"路径曲线化和保存失败({context}: {ex.Message}", ex);
}
}
#endregion
#region 访
/// <summary>
@ -2892,7 +2942,9 @@ namespace NavisworksTransport
public void UpdateRoute(PathRoute route)
{
if (route == null) return;
SavePathToDatabase(route);
// 使用统一的曲线化和保存方法
RecalculateAndSaveRoute(route, "UpdateRoute");
}
#endregion

View File

@ -250,10 +250,20 @@ namespace NavisworksTransport
public List<Point3D> SampledPoints { get; set; }
/// <summary>
/// 带状连线高度(仅用于 RibbonLine 模式)
/// 带状连线高度(仅用于 RibbonLine 和 VehicleSpace 模式)
/// </summary>
public double Height { get; set; }
/// <summary>
/// 带状连线宽度(仅用于 VehicleSpace 模式)
/// </summary>
public double Width { get; set; }
/// <summary>
/// 透明度0.0=完全透明1.0=完全不透明)
/// </summary>
public double Opacity { get; set; } = 1.0;
public override string ToString()
{
return $"LineMarker[{FromIndex}->{ToIndex}, 类型={SegmentType}, 起点=({StartPoint.X:F2},{StartPoint.Y:F2},{StartPoint.Z:F2}), 终点=({EndPoint.X:F2},{EndPoint.Y:F2},{EndPoint.Z:F2})]";
@ -507,39 +517,50 @@ namespace NavisworksTransport
// 渲染控制点连线(半透明)
foreach (var controlLineMarker in visualization.ControlLineMarkers)
{
graphics.Color(controlLineMarker.Color, 0.3); // 30%透明度
var style = GetRenderStyle(RenderStyleName.PreviewLine);
graphics.Color(style.Color, style.Alpha); // 完全使用PreviewLine的颜色和透明度
graphics.Cylinder(controlLineMarker.StartPoint, controlLineMarker.EndPoint, controlLineMarker.Radius);
}
}
// 渲染真实路径可视化Edges + 切点)
// 先渲染切点(在底层)
foreach (var tangentMarker in visualization.TangentMarkers)
// 渲染真实路径可视化(根据模式选择)
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
{
graphics.Color(tangentMarker.Color, tangentMarker.Alpha);
RenderSquareMarker(graphics, tangentMarker);
}
// 再渲染路径连线(直线段和圆弧段)
foreach (var pathLineMarker in visualization.PathLineMarkers)
{
// 圆弧段使用半透明灰色,直线段使用正常颜色
if (pathLineMarker.SegmentType == PathSegmentType.Arc)
// VehicleSpace 模式:使用车辆通行空间渲染(高高度长方体)
foreach (var pathLineMarker in visualization.PathLineMarkers)
{
graphics.Color(GetRenderStyle(RenderStyleName.PreviewLine).Color, 0.5); // 半透明灰色
RenderRibbonLineMarker(graphics, pathLineMarker);
}
else
{
graphics.Color(pathLineMarker.Color, 1.0); // 不透明
}
RenderLineMarker(graphics, pathLineMarker);
}
// 渲染车辆通行空间(矩形通道)
foreach (var vehicleSpaceMarker in visualization.VehicleSpaceMarkers)
else if (_visualizationMode == PathVisualizationMode.RibbonLine)
{
graphics.Color(vehicleSpaceMarker.Color, vehicleSpaceMarker.Alpha);
RenderVehicleSpace(graphics, vehicleSpaceMarker);
// RibbonLine 模式:使用带状连线渲染(低高度长方体)
// 先渲染切点(在底层)
foreach (var tangentMarker in visualization.TangentMarkers)
{
RenderSquareMarker(graphics, tangentMarker);
}
// 再渲染路径连线
foreach (var pathLineMarker in visualization.PathLineMarkers)
{
RenderRibbonLineMarker(graphics, pathLineMarker);
}
}
else
{
// StandardLine 模式:使用圆柱体渲染
// 先渲染切点(在底层)
foreach (var tangentMarker in visualization.TangentMarkers)
{
RenderSquareMarker(graphics, tangentMarker);
}
// 再渲染路径连线
foreach (var pathLineMarker in visualization.PathLineMarkers)
{
RenderLineMarker(graphics, pathLineMarker);
}
}
}
@ -910,23 +931,11 @@ namespace NavisworksTransport
// 构建控制点连线(用户意图,半透明)
BuildControlLines(visualization, sortedPoints);
// 构建路径连线真实路径不透明仅当Edges存在时
// 所有模式都使用曲线化后的路径Edges
if (visualization.PathRoute.Edges != null && visualization.PathRoute.Edges.Count > 0)
{
BuildPathLines(visualization, sortedPoints);
}
else if (_visualizationMode == PathVisualizationMode.VehicleSpace)
{
// 构建车辆通行空间标记
for (int i = 0; i < sortedPoints.Count - 1; i++)
{
var currentPoint = sortedPoints[i];
var nextPoint = sortedPoints[i + 1];
var vehicleSpaceMarker = CreateVehicleSpaceMarker(currentPoint, nextPoint);
visualization.VehicleSpaceMarkers.Add(vehicleSpaceMarker);
}
}
// 如果路径未完成,添加灰色的原始终点标记
if (!visualization.PathRoute.IsComplete && visualization.PathRoute.OriginalEndPoint != null)
@ -968,7 +977,7 @@ namespace NavisworksTransport
{
StartPoint = currentPoint.Position,
EndPoint = nextPoint.Position,
Color = GetRenderStyle(RenderStyleName.Line).Color,
Color = GetRenderStyle(RenderStyleName.PreviewLine).Color,
Radius = GetLineRadius() * 0.5, // 比实际路径细
SegmentType = PathSegmentType.Straight,
FromIndex = currentPoint.Index,
@ -1008,8 +1017,46 @@ namespace NavisworksTransport
}
}
// 计算带状连线的高度比切点标记低GetLineRadius() * 0.2
double ribbonHeight = GetLineRadius() * 0.2;
// 获取单位转换系数
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
// 根据可视化模式计算高度和宽度
double heightInMeters;
double widthInMeters;
Color lineColor;
double lineOpacity;
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
{
// VehicleSpace 模式:使用车辆高度和宽度
heightInMeters = _vehicleHeight + _safetyMargin;
widthInMeters = Math.Max(_vehicleLength, _vehicleWidth) + 2 * _safetyMargin;
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;
// 3. 构建路径连线Edges包含直线段和圆弧段
foreach (var edge in edges)
@ -1023,11 +1070,13 @@ namespace NavisworksTransport
{
StartPoint = edge.SampledPoints.First(),
EndPoint = edge.SampledPoints.Last(),
Color = GetRenderStyle(RenderStyleName.Line).Color,
Color = lineColor,
Radius = GetLineRadius(),
SegmentType = PathSegmentType.Straight,
SampledPoints = edge.SampledPoints,
Height = ribbonHeight // 设置带状连线高度
Height = heightInModelUnits, // 根据模式设置高度
Width = widthInModelUnits, // 根据模式设置宽度
Opacity = lineOpacity // 根据模式设置透明度
};
visualization.PathLineMarkers.Add(lineMarker);
}
@ -1039,17 +1088,22 @@ namespace NavisworksTransport
{
StartPoint = edge.Trajectory.Ts,
EndPoint = edge.Trajectory.Te,
Color = GetRenderStyle(RenderStyleName.Line).Color,
Color = lineColor,
Radius = GetLineRadius(),
SegmentType = PathSegmentType.Arc,
Trajectory = edge.Trajectory,
SampledPoints = edge.SampledPoints,
Height = ribbonHeight // 设置带状连线高度
Height = heightInModelUnits, // 根据模式设置高度
Width = widthInModelUnits, // 根据模式设置宽度
Opacity = lineOpacity // 根据模式设置透明度
};
visualization.PathLineMarkers.Add(arcMarker);
// 添加切点标记
AddTangentMarkers(visualization, edge);
// 添加切点标记StandardLine 和 RibbonLine 模式才添加)
if (_visualizationMode != PathVisualizationMode.VehicleSpace)
{
AddTangentMarkers(visualization, edge);
}
}
}
}
@ -1263,7 +1317,7 @@ namespace NavisworksTransport
return new RenderStyle(Color.FromByteRGB(33, 150, 243), 0.9); // Material Blue路径点10%透明
case RenderStyleName.Line:
return new RenderStyle(Color.FromByteRGB(255, 152, 0), 0.85); // Material Orange连线15%透明
return new RenderStyle(Color.FromByteRGB(255, 152, 0), 0.8); // Material Orange连线20%透明
case RenderStyleName.VehicleSpace:
return new RenderStyle(Color.FromByteRGB(158, 158, 158), 0.4); // Material Grey车辆空间60%透明
@ -1272,7 +1326,7 @@ namespace NavisworksTransport
return new RenderStyle(Color.White, 0.7); // 白色预览点30%透明
case RenderStyleName.PreviewLine:
return new RenderStyle(Color.FromByteRGB(128, 128, 128), 0.7); // 灰色预览连线30%透明
return new RenderStyle(Color.FromByteRGB(128, 128, 128), 0.5); // 灰色预览连线50%透明
case RenderStyleName.UnreachedEndPoint:
return new RenderStyle(Color.FromByteRGB(139, 0, 0), 0.7); // 深红色未到达终点30%透明
@ -1749,13 +1803,13 @@ namespace NavisworksTransport
double baseRadiusInMeters;
if (pointType == PathPointType.WayPoint)
{
// 路径点为标准尺寸的80%
baseRadiusInMeters = standardRadiusInMeters * 0.8;
// 路径点为标准尺寸的1/4
baseRadiusInMeters = standardRadiusInMeters * 0.25;
}
else
{
// 起点/终点使用标准尺寸100%
baseRadiusInMeters = standardRadiusInMeters * 1.0;
// 起点/终点使用标准尺寸的1/2
baseRadiusInMeters = standardRadiusInMeters * 0.5;
}
// 获取真实文档单位转换系数
@ -1803,9 +1857,7 @@ namespace NavisworksTransport
/// <param name="endPoint">终点</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <param name="color">颜色</param>
/// <param name="alpha">透明度</param>
private void RenderCuboidMarker(Graphics graphics, Point3D startPoint, Point3D endPoint, double width, double height, Color color, double alpha)
private void RenderCuboidMarker(Graphics graphics, Point3D startPoint, Point3D endPoint, double width, double height)
{
try
{
@ -1856,9 +1908,6 @@ namespace NavisworksTransport
var yVector = new Vector3D(right.X * width, right.Y * width, right.Z * width); // 宽度方向
var zVector = new Vector3D(0, 0, height); // 高度方向
// 设置颜色和透明度
graphics.Color(color, alpha);
// 使用Cuboid API渲染长方体
graphics.Cuboid(origin, xVector, yVector, zVector, true);
}
@ -1876,14 +1925,14 @@ namespace NavisworksTransport
private void RenderVehicleSpace(Graphics graphics, VehicleSpaceMarker vehicleSpace)
{
var style = GetRenderStyle(RenderStyleName.VehicleSpace);
// 设置颜色和透明度
graphics.Color(vehicleSpace.Color, vehicleSpace.Alpha);
RenderCuboidMarker(
graphics,
vehicleSpace.StartPoint,
vehicleSpace.EndPoint,
vehicleSpace.Width,
vehicleSpace.Height,
vehicleSpace.Color,
vehicleSpace.Alpha
vehicleSpace.Height
);
}
@ -1894,17 +1943,41 @@ namespace NavisworksTransport
/// <param name="lineMarker">连线标记</param>
private void RenderRibbonLineMarker(Graphics graphics, LineMarker lineMarker)
{
// 计算带状连线的宽度(直径)
var width = lineMarker.Radius * 2;
RenderCuboidMarker(
graphics,
lineMarker.StartPoint,
lineMarker.EndPoint,
width,
lineMarker.Height,
lineMarker.Color,
1.0 // 带状连线使用不透明
);
// 使用 LineMarker 的 Width 属性(如果没有设置则使用 Radius * 2
var width = lineMarker.Width > 0 ? lineMarker.Width : lineMarker.Radius * 2;
// 检查是否是圆弧段且有多段采样点
if (lineMarker.SegmentType == PathSegmentType.Arc &&
lineMarker.SampledPoints != null &&
lineMarker.SampledPoints.Count >= 2)
{
// 圆弧段:多段长方体拼接
for (int i = 0; i < lineMarker.SampledPoints.Count - 1; i++)
{
// 设置颜色和透明度
graphics.Color(lineMarker.Color, lineMarker.Opacity);
RenderCuboidMarker(
graphics,
lineMarker.SampledPoints[i],
lineMarker.SampledPoints[i + 1],
width,
lineMarker.Height
);
}
}
else
{
// 直线段:单个长方体
// 设置颜色和透明度
graphics.Color(lineMarker.Color, lineMarker.Opacity);
RenderCuboidMarker(
graphics,
lineMarker.StartPoint,
lineMarker.EndPoint,
width,
lineMarker.Height
);
}
}
@ -2005,8 +2078,7 @@ namespace NavisworksTransport
);
// 使用统一样式
var style = GetRenderStyle(RenderStyleName.TangentPoint);
graphics.Color(style.Color, marker.Alpha);
graphics.Color(marker.Color, marker.Alpha);
// 使用Cone API渲染圆锥体底部半径 = radius顶部半径 = 0
graphics.Cone(startPoint, endPoint, radius, 0);
@ -2024,36 +2096,16 @@ namespace NavisworksTransport
/// <param name="lineMarker">连线标记</param>
private void RenderLineMarker(Graphics graphics, LineMarker lineMarker)
{
if (_visualizationMode == PathVisualizationMode.RibbonLine)
if (_visualizationMode == PathVisualizationMode.VehicleSpace || _visualizationMode == PathVisualizationMode.RibbonLine)
{
// 带状连线模式:使用长方体渲染
if (lineMarker.SegmentType == PathSegmentType.Arc &&
lineMarker.SampledPoints != null &&
lineMarker.SampledPoints.Count >= 2)
{
// 圆弧段:多段长方体拼接
for (int i = 0; i < lineMarker.SampledPoints.Count - 1; i++)
{
var segmentMarker = new LineMarker
{
StartPoint = lineMarker.SampledPoints[i],
EndPoint = lineMarker.SampledPoints[i + 1],
Radius = lineMarker.Radius,
Height = lineMarker.Height,
Color = lineMarker.Color
};
RenderRibbonLineMarker(graphics, segmentMarker);
}
}
else
{
// 直线段:单个长方体
RenderRibbonLineMarker(graphics, lineMarker);
}
// VehicleSpace 或 RibbonLine 模式:使用长方体渲染
RenderRibbonLineMarker(graphics, lineMarker);
}
else
{
// 标准连线模式:使用圆柱体渲染
// StandardLine 模式:使用圆柱体渲染
var style = GetRenderStyle(RenderStyleName.Line);
graphics.Color(lineMarker.Color, style.Alpha);
if (lineMarker.SegmentType == PathSegmentType.Arc &&
lineMarker.SampledPoints != null &&
lineMarker.SampledPoints.Count >= 2)

View File

@ -2735,6 +2735,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
pathViewModel.Points.Add(pointViewModel);
}
LogManager.Info($"已更新路径点列表,当前点数: {pathViewModel.Points.Count}");
// 更新真实路径可视化
UpdatePathVisualization();
}
else
{