修补了路径可视化中出现的缝隙
This commit is contained in:
parent
3bae0f0274
commit
409b39ce78
@ -366,7 +366,7 @@ namespace NavisworksTransport
|
||||
private double _currentGridSizeInMeters;
|
||||
|
||||
// 路径可视化模式配置
|
||||
private PathVisualizationMode _visualizationMode = PathVisualizationMode.StandardLine;
|
||||
private PathVisualizationMode _visualizationMode = PathVisualizationMode.RibbonLine;
|
||||
|
||||
// 网格点类型配置
|
||||
private GridPointType _gridPointType = GridPointType.Rectangle;
|
||||
@ -528,11 +528,7 @@ namespace NavisworksTransport
|
||||
graphics.Cylinder(controlLineMarker.StartPoint, controlLineMarker.EndPoint, controlLineMarker.Radius);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Debug($"[Render] 路径 {visualization.PathId} 的 ShowControlVisualization 为 false,跳过控制点渲染");
|
||||
}
|
||||
|
||||
|
||||
// 渲染真实路径可视化(根据模式选择)
|
||||
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
|
||||
{
|
||||
@ -1946,6 +1942,73 @@ namespace NavisworksTransport
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 渲染长方体标记(指定长度)
|
||||
/// </summary>
|
||||
/// <param name="graphics">图形上下文</param>
|
||||
/// <param name="startPoint">起点</param>
|
||||
/// <param name="endPoint">终点</param>
|
||||
/// <param name="width">宽度</param>
|
||||
/// <param name="height">高度</param>
|
||||
/// <param name="length">指定长度(覆盖默认计算值)</param>
|
||||
private void RenderCuboidMarkerWithLength(Graphics graphics, Point3D startPoint, Point3D endPoint, double width, double height, double length)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 计算方向向量
|
||||
var direction = new Vector3D(
|
||||
endPoint.X - startPoint.X,
|
||||
endPoint.Y - startPoint.Y,
|
||||
endPoint.Z - startPoint.Z
|
||||
);
|
||||
|
||||
// 归一化方向向量
|
||||
var directionLength = Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y + direction.Z * direction.Z);
|
||||
if (directionLength < 0.001) // 避免零长度线段
|
||||
return;
|
||||
|
||||
direction = new Vector3D(direction.X / directionLength, direction.Y / directionLength, direction.Z / directionLength);
|
||||
|
||||
// 计算垂直向量(在XY平面内垂直于方向向量)
|
||||
var right = new Vector3D(-direction.Y, direction.X, 0);
|
||||
|
||||
// 如果方向向量垂直于XY平面,则使用不同的right向量
|
||||
if (Math.Abs(direction.Z) > 0.9)
|
||||
{
|
||||
right = new Vector3D(1, 0, 0);
|
||||
}
|
||||
|
||||
// 归一化right向量
|
||||
var rightLength = Math.Sqrt(right.X * right.X + right.Y * right.Y + right.Z * right.Z);
|
||||
if (rightLength > 0.001)
|
||||
{
|
||||
right = new Vector3D(right.X / rightLength, right.Y / rightLength, right.Z / rightLength);
|
||||
}
|
||||
|
||||
// 计算长方体的边界框和向量
|
||||
var halfWidth = width / 2.0;
|
||||
|
||||
// 计算立方体原点(起点左下角)
|
||||
var origin = new Point3D(
|
||||
startPoint.X - halfWidth * right.X,
|
||||
startPoint.Y - halfWidth * right.Y,
|
||||
startPoint.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); // 高度方向
|
||||
|
||||
// 使用Cuboid API渲染长方体
|
||||
graphics.Cuboid(origin, xVector, yVector, zVector, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[长方体渲染] 渲染长方体失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 渲染带状连线(长方体)
|
||||
/// </summary>
|
||||
@ -1955,23 +2018,93 @@ namespace NavisworksTransport
|
||||
{
|
||||
// 使用 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)
|
||||
{
|
||||
// 圆弧段:多段长方体拼接
|
||||
// 为了避免外侧出现缝隙,需要根据外侧弧线长度调整每个长方体的长度(厚度)
|
||||
|
||||
// 计算外侧弧线长度 = (圆弧半径 + 宽度/2) * 偏转角
|
||||
// 注意:宽度是长方体的总宽度,所以半径是 width/2
|
||||
double outerArcRadius = width / 2.0; // 长方体的半径(宽度的一半)
|
||||
double outerArcLength = 0;
|
||||
double centerArcRadius = 0;
|
||||
|
||||
if (lineMarker.Trajectory != null)
|
||||
{
|
||||
centerArcRadius = lineMarker.Trajectory.ActualRadius;
|
||||
outerArcLength = (centerArcRadius + outerArcRadius) * lineMarker.Trajectory.DeflectionAngle;
|
||||
}
|
||||
|
||||
// 计算每个长方体在外侧应该覆盖的长度
|
||||
int segmentCount = lineMarker.SampledPoints.Count - 1;
|
||||
double outerSegmentLength = outerArcLength / segmentCount;
|
||||
|
||||
// 提前计算比例因子,避免在循环中重复计算
|
||||
double lengthScaleFactor = (centerArcRadius + outerArcRadius) / centerArcRadius;
|
||||
|
||||
// 设置颜色和透明度
|
||||
graphics.Color(lineMarker.Color, lineMarker.Opacity);
|
||||
|
||||
// 添加过渡切片(在第一个切片前)
|
||||
// 从第一个切片反向画一个切片,填补外侧缝隙
|
||||
// 计算第一个切片的方向(从 Ts 到 SampledPoints[1],跳过第一个点因为它就是Ts)
|
||||
var firstSliceDirection = new Vector3D(
|
||||
lineMarker.SampledPoints[1].X - lineMarker.Trajectory.Ts.X,
|
||||
lineMarker.SampledPoints[1].Y - lineMarker.Trajectory.Ts.Y,
|
||||
lineMarker.SampledPoints[1].Z - lineMarker.Trajectory.Ts.Z
|
||||
);
|
||||
var firstSliceLength = Math.Sqrt(
|
||||
firstSliceDirection.X * firstSliceDirection.X +
|
||||
firstSliceDirection.Y * firstSliceDirection.Y +
|
||||
firstSliceDirection.Z * firstSliceDirection.Z
|
||||
);
|
||||
|
||||
firstSliceDirection = new Vector3D(
|
||||
firstSliceDirection.X / firstSliceLength,
|
||||
firstSliceDirection.Y / firstSliceLength,
|
||||
firstSliceDirection.Z / firstSliceLength
|
||||
);
|
||||
|
||||
// 反向切片:从 Ts 沿第一个切片的反方向延伸
|
||||
// 使用完整的 outerSegmentLength 作为长度
|
||||
var reverseSliceEndPoint = new Point3D(
|
||||
lineMarker.Trajectory.Ts.X - firstSliceDirection.X * outerSegmentLength,
|
||||
lineMarker.Trajectory.Ts.Y - firstSliceDirection.Y * outerSegmentLength,
|
||||
lineMarker.Trajectory.Ts.Z - firstSliceDirection.Z * outerSegmentLength
|
||||
);
|
||||
|
||||
RenderCuboidMarkerWithLength(
|
||||
graphics,
|
||||
reverseSliceEndPoint,
|
||||
lineMarker.Trajectory.Ts,
|
||||
width,
|
||||
lineMarker.Height,
|
||||
outerSegmentLength
|
||||
);
|
||||
|
||||
for (int i = 0; i < lineMarker.SampledPoints.Count - 1; i++)
|
||||
{
|
||||
// 设置颜色和透明度
|
||||
graphics.Color(lineMarker.Color, lineMarker.Opacity);
|
||||
RenderCuboidMarker(
|
||||
// 计算当前段的中心线长度
|
||||
double centerSegmentLength = GeometryHelper.CalculatePointDistance(
|
||||
lineMarker.SampledPoints[i],
|
||||
lineMarker.SampledPoints[i + 1]
|
||||
);
|
||||
|
||||
// 计算长方体应该使用的长度(基于外侧弧线)
|
||||
double cuboidLength = centerSegmentLength * lengthScaleFactor;
|
||||
|
||||
// 渲染长方体,使用调整后的长度
|
||||
RenderCuboidMarkerWithLength(
|
||||
graphics,
|
||||
lineMarker.SampledPoints[i],
|
||||
lineMarker.SampledPoints[i + 1],
|
||||
width,
|
||||
lineMarker.Height
|
||||
lineMarker.Height,
|
||||
cuboidLength
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2121,9 +2254,26 @@ namespace NavisworksTransport
|
||||
lineMarker.SampledPoints.Count >= 2)
|
||||
{
|
||||
// 圆弧段:多段圆柱体
|
||||
// 为了避免外侧出现缝隙,需要根据外侧弧线长度调整每个圆柱体的厚度(半径)
|
||||
double cylinderRadius = lineMarker.Radius; // 默认使用原始半径
|
||||
|
||||
if (lineMarker.Trajectory != null)
|
||||
{
|
||||
// 计算外侧弧线长度 = (圆弧半径 + 连线半径) * 偏转角
|
||||
double outerArcLength = (lineMarker.Trajectory.ActualRadius + lineMarker.Radius) * lineMarker.Trajectory.DeflectionAngle;
|
||||
|
||||
// 计算每个圆柱体在外侧应该覆盖的长度
|
||||
int segmentCount = lineMarker.SampledPoints.Count - 1;
|
||||
double outerSegmentLength = outerArcLength / segmentCount;
|
||||
|
||||
// 圆柱体的半径(厚度)应该等于外侧段长度的一半
|
||||
// 这样圆柱体在外侧的覆盖长度 = 2 * radius = outerSegmentLength,正好填满外侧弧线
|
||||
cylinderRadius = outerSegmentLength / 2.0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < lineMarker.SampledPoints.Count - 1; i++)
|
||||
{
|
||||
graphics.Cylinder(lineMarker.SampledPoints[i], lineMarker.SampledPoints[i + 1], lineMarker.Radius);
|
||||
graphics.Cylinder(lineMarker.SampledPoints[i], lineMarker.SampledPoints[i + 1], cylinderRadius);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@ -449,18 +449,12 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管
|
||||
VerticalAlignment="Center"
|
||||
Margin="5,0,0,0">
|
||||
<!-- 可视化模式选择 -->
|
||||
<RadioButton Content="柱形连线"
|
||||
GroupName="PathVisualizationMode"
|
||||
IsChecked="{Binding IsStandardLineMode}"
|
||||
Margin="0,0,20,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="显示柱形连线(圆柱体)"/>
|
||||
<RadioButton Content="带状连线"
|
||||
<RadioButton Content="地面连线"
|
||||
GroupName="PathVisualizationMode"
|
||||
IsChecked="{Binding IsRibbonLineMode}"
|
||||
Margin="0,0,20,0"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="显示带状连线(长方体)"/>
|
||||
ToolTip="显示地表连线(长方体)"/>
|
||||
<RadioButton Content="通行空间"
|
||||
GroupName="PathVisualizationMode"
|
||||
IsChecked="{Binding IsVehicleSpaceMode}"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user