From 7e78ca8714a7c31b5060fef611e953bbb5a9ba07 Mon Sep 17 00:00:00 2001 From: maj00r Date: Sun, 4 Oct 2026 02:12:14 +0200 Subject: [PATCH] Structure gauge: the lower part turns with the plane of the rail heads on cant --- application/editormodegauge.cpp | 23 +++++++++++++++++++--- editor/editorGauge.cpp | 34 ++++++++++++++++++++++++++++++--- editor/editorGauge.hpp | 12 +++++++++++- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/application/editormodegauge.cpp b/application/editormodegauge.cpp index d08b91ba..2d6c7b41 100644 --- a/application/editormodegauge.cpp +++ b/application/editormodegauge.cpp @@ -95,6 +95,24 @@ gauge_line make_line(editor_track::route &Route, gauge::profile const &Profile) cant.push_back(sample.cant); } line.sections = gauge::sections(Profile.kind, chainage, curvature, cant); + if (false == road) + { + // the outer rail is raised: the side from the nearest curve along the line + std::vector sides(curvature.size(), 0.0); + double side{0.0}; + for (std::size_t i = 0; i < curvature.size(); ++i) + sides[i] = side = std::abs(curvature[i]) > 1e-6 ? (curvature[i] > 0.0 ? 1.0 : -1.0) : side; + side = 0.0; + for (std::size_t i = curvature.size(); i-- > 0;) + { + if (std::abs(curvature[i]) > 1e-6) + side = curvature[i] > 0.0 ? 1.0 : -1.0; + else if (sides[i] == 0.0) + sides[i] = side; + } + for (std::size_t i = 0; i < curvature.size(); ++i) + line.sections[i].tilt = -sides[i] * std::min(1.0, cant[i] / 1.5); + } if (road) for (std::size_t i = 0; i < line.samples.size(); ++i) line.sections[i].base = carriageway(line.route.spans[line.samples[i].span], line.samples[i].chainage); @@ -350,9 +368,8 @@ void build_tunnel(gauge_line const &Line, std::vector &Surface, std: for (int side : {-1, 1}) for (std::size_t j = 0; j < profile.outline.size(); ++j) { - auto const &point{profile.outline[side < 0 ? j : profile.outline.size() - 1 - j]}; - auto const width{Line.sections[Index].base + point.half_width + gauge::widening(Line.sections[Index], point.height, side)}; - points.push_back(lift(Line.samples[Index], side * width, point.height)); + auto const point{gauge::outline_point(profile, Line.sections[Index], side < 0 ? j : profile.outline.size() - 1 - j, side)}; + points.push_back(lift(Line.samples[Index], point.lateral, point.height)); } return points; }}; diff --git a/editor/editorGauge.cpp b/editor/editorGauge.cpp index 9ba12e9b..8674521f 100644 --- a/editor/editorGauge.cpp +++ b/editor/editorGauge.cpp @@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/. #include "stdafx.h" #include "editor/editorGauge.hpp" +#include #include #include @@ -87,6 +88,18 @@ private: std::vector m_integral; }; +// half of the distance between the heads of the rails +double constexpr rail_spread{0.75}; + +// the point turned by the angle of the sine about the head of the lower rail +place turn(section const &Section, place const &Point, double const Sine) +{ + auto const pivot{Section.tilt > 0.0 ? -rail_spread : rail_spread}; + auto const cosine{std::sqrt(std::max(0.0, 1.0 - Sine * Sine))}; + auto const lateral{Point.lateral - pivot}; + return {pivot + lateral * cosine - Point.height * Sine, lateral * Sine + Point.height * cosine}; +} + // names of the kinds in the file char const *const kind_names[]{"unified", "installation", "road"}; @@ -210,7 +223,18 @@ std::vector
sections(kind const Kind, std::vector const &Chaina double widening(section const &Section, double const Height, int const Side) { auto const i{Side > 0 ? 1 : 0}; - return (Height < lower_part ? Section.lower[i] : Section.upper[i]) + Section.cant[i] * Height / 1.5; + return Height < lower_part ? Section.lower[i] : Section.upper[i] + Section.cant[i] * Height / 1.5; +} + +place outline_point(profile const &Profile, section const &Section, std::size_t const Index, int const Side) +{ + auto const &point{Profile.outline[Index]}; + // the step at the top of the lower part belongs to it from below + bool const lower{point.height < lower_part - 1e-9 || (point.height < lower_part + 1e-9 && Index > 0 && Profile.outline[Index - 1].height < lower_part - 1e-9)}; + auto const i{Side > 0 ? 1 : 0}; + auto const width{Section.base + point.half_width + (lower ? Section.lower[i] : Section.upper[i] + Section.cant[i] * point.height / 1.5)}; + place const result{Side * width, point.height}; + return lower && Section.tilt != 0.0 ? turn(Section, result, Section.tilt) : result; } double half_width(profile const &Profile, section const &Section, double const Height, int const Side) @@ -232,10 +256,14 @@ double half_width(profile const &Profile, section const &Section, double const H double intrusion(profile const &Profile, section const &Section, double const Lateral, double const Height) { - auto const width{half_width(Profile, Section, Height, Lateral >= 0.0 ? 1 : -1)}; + // the point in the plane of the rail heads, for the lower part + auto const local{Section.tilt != 0.0 ? turn(Section, {Lateral, Height}, -Section.tilt) : place{Lateral, Height}}; + auto const lower{local.height < lower_part}; + auto const point{lower ? local : place{Lateral, std::max(Height, lower_part)}}; + auto const width{half_width(Profile, Section, point.height, point.lateral >= 0.0 ? 1 : -1)}; if (width < 0.0) return 0.0; - return width - std::abs(Lateral); + return width - std::abs(point.lateral); } } // namespace gauge diff --git a/editor/editorGauge.hpp b/editor/editorGauge.hpp index d7e94cf9..609462ff 100644 --- a/editor/editorGauge.hpp +++ b/editor/editorGauge.hpp @@ -61,13 +61,23 @@ struct section std::array upper{}; // from the radius, above the lower part std::array lower{}; // from the radius, in the lower part std::array cant{}; // cant in metres, positive on the inner side of the curve and negative on the outer one + double tilt{0.0}; // sine of the slope of the plane of the rail heads, positive with the left rail raised +}; +// point of the cross-section, metres: lateral positive to the left, height above the rail top +struct place +{ + double lateral{0.0}; + double height{0.0}; }; // sections at the points of a route, from their chainage, curvature (1/m, positive turning left) and cant (m). // The widening begins and ends ahead of the changes of the curvature and cant, as the vehicles enter a curve std::vector
sections(kind Kind, std::vector const &Chainage, std::vector const &Curvature, std::vector const &Cant); -// widening of the side (+1 left, -1 right) at the height +// widening of the side (+1 left, -1 right) at the height; the cant shifts only the part above the lower one, +// the lower part turns with the plane of the rail heads instead double widening(section const &Section, double Height, int Side); +// point of the outline on the side at the section, with the widening and the turn of the lower part +place outline_point(profile const &Profile, section const &Section, std::size_t Index, int Side); // half-width of the gauge at the height on the side, negative above or below the outline double half_width(profile const &Profile, section const &Section, double Height, int Side); // depth of the point inside the gauge, metres, not positive outside of it. Lateral positive to the left