From 99d26908005f3ea1dfb31ed2514d8311283d3fcc Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Mon, 12 Jan 2026 18:47:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9F=BA=E7=BA=BF=E4=B8=8D?= =?UTF-8?q?=E8=B4=B4=E5=90=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PathPlanning/RailGeometryHelper.cs | 85 ++++++++++++++------------ 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/src/PathPlanning/RailGeometryHelper.cs b/src/PathPlanning/RailGeometryHelper.cs index 60c10c6..2eab161 100644 --- a/src/PathPlanning/RailGeometryHelper.cs +++ b/src/PathPlanning/RailGeometryHelper.cs @@ -523,55 +523,64 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"[空轨] 下表面轴索引: {downAxisIndex}, 方向: ({downAxisVector.X:F3}, {downAxisVector.Y:F3}, {downAxisVector.Z:F3})"); - // 计算下表面偏移(使用投影范围的 minZ) - var downOffsetZ = obb.ProjectedMinZ; + // 计算下表面偏移(使用半长度) + var downHalfLength = obb.GetAxisLength(downAxisIndex) / 2; + var downOffset = downAxisVector * downHalfLength; - LogManager.Info($"[空轨] 下表面偏移(投影 minZ): {downOffsetZ:F3}"); + LogManager.Info($"[空轨] 下表面偏移向量: ({downOffset.X:F3}, {downOffset.Y:F3}, {downOffset.Z:F3})"); - // 在主轴坐标系中,起点和终点的下表面位置 - // 起点:Axis0 = minX, Axis1 = 0, Axis2 = minZ - // 终点:Axis0 = maxX, Axis1 = 0, Axis2 = minZ - var axis0Min = -obb.GetAxisLength(0) / 2; - var axis0Max = obb.GetAxisLength(0) / 2; - - // 将主轴坐标系中的下表面点转换回世界坐标系 - var obbAxes = obb.Axes; - - var startProjected = new Point3D( - axis0Min, - 0, - downOffsetZ - ); - - var endProjected = new Point3D( - axis0Max, - 0, - downOffsetZ - ); - - LogManager.Info($"[空轨] 主轴坐标系起点: ({startProjected.X:F2}, {startProjected.Y:F2}, {startProjected.Z:F2})"); - LogManager.Info($"[空轨] 主轴坐标系终点: ({endProjected.X:F2}, {endProjected.Y:F2}, {endProjected.Z:F2})"); - - var startCenter = new Point3D( - center.X + startProjected.X * obbAxes[0].X + startProjected.Y * obbAxes[1].X + startProjected.Z * obbAxes[2].X, - center.Y + startProjected.X * obbAxes[0].Y + startProjected.Y * obbAxes[1].Y + startProjected.Z * obbAxes[2].Y, - center.Z + startProjected.X * obbAxes[0].Z + startProjected.Y * obbAxes[1].Z + startProjected.Z * obbAxes[2].Z - ); - - var endCenter = new Point3D( - center.X + endProjected.X * obbAxes[0].X + endProjected.Y * obbAxes[1].X + endProjected.Z * obbAxes[2].X, - center.Y + endProjected.X * obbAxes[0].Y + endProjected.Y * obbAxes[1].Y + endProjected.Z * obbAxes[2].Y, - center.Z + endProjected.X * obbAxes[0].Z + endProjected.Y * obbAxes[1].Z + endProjected.Z * obbAxes[2].Z - ); + // 中心线起点和终点 + var startCenter = center - direction * (axisLength / 2) + downOffset; + var endCenter = center + direction * (axisLength / 2) + downOffset; LogManager.Info($"[空轨] 中心线起点: ({startCenter.X:F2}, {startCenter.Y:F2}, {startCenter.Z:F2})"); LogManager.Info($"[空轨] 中心线终点: ({endCenter.X:F2}, {endCenter.Y:F2}, {endCenter.Z:F2})"); // 4. 沿中心线采样 + var aabb = railModel.BoundingBox(); var baseline = SampleLine(startCenter, endCenter, samplingInterval); LogManager.Info($"[空轨] OBB 方法完成,生成 {baseline.Count} 个采样点"); + // 5. 使用射线投射获取下表面的精确高度(处理不平整的下表面) + var triangles = GeometryHelper.ExtractTriangles(new[] { railModel }); + var bottomTriangles = FilterBottomTriangles(triangles); + + if (bottomTriangles.Count > 0) + { + var adjustedBaseline = new List(); + int successCount = 0; + + foreach (var point in baseline) + { + try + { + double bottomZ = GetBottomHeightByRaycast( + point, + bottomTriangles, + aabb.Min.Z); + + if (bottomZ > aabb.Min.Z - 1000) + { + adjustedBaseline.Add(new Point3D(point.X, point.Y, bottomZ)); + successCount++; + } + } + catch (Exception ex) + { + LogManager.Warning($"[空轨] 射线投射失败: {ex.Message}"); + adjustedBaseline.Add(point); // 使用原始点作为后备 + } + } + + LogManager.Info($"[空轨] 射线投射调整: {successCount}/{baseline.Count} 个点已调整"); + + if (adjustedBaseline.Count >= 2) + { + return adjustedBaseline; + } + } + return baseline; } catch (Exception ex)