17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 02:49:19 +02:00

Structure gauge: the lower part turns with the plane of the rail heads on cant

This commit is contained in:
maj00r
2026-10-04 02:12:14 +02:00
parent 0b5b69d76e
commit 7e78ca8714
3 changed files with 62 additions and 7 deletions

View File

@@ -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<double> 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<glm::dvec3> &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;
}};

View File

@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h"
#include "editor/editorGauge.hpp"
#include <cmath>
#include <fstream>
#include <sstream>
@@ -87,6 +88,18 @@ private:
std::vector<double> 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<section> sections(kind const Kind, std::vector<double> 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

View File

@@ -61,13 +61,23 @@ struct section
std::array<double, 2> upper{}; // from the radius, above the lower part
std::array<double, 2> lower{}; // from the radius, in the lower part
std::array<double, 2> 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<section> sections(kind Kind, std::vector<double> const &Chainage, std::vector<double> const &Curvature, std::vector<double> 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