mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-04 00:42:05 +01:00
Structure gauge refactor: outline ring, tilt in the sections, outline choice, shared track line
This commit is contained in:
@@ -125,8 +125,49 @@ profile installation(std::string const &Name, std::vector<std::pair<int, int>> c
|
||||
return result;
|
||||
}
|
||||
|
||||
// point of the outline on the side (+1 left, -1 right) at the section
|
||||
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 widening{wheel_zone(point) ? 0.0 : lower ? Section.lower[i] : Section.upper[i] + Section.cant[i] * point.height / 1.5};
|
||||
auto const width{Section.base + point.half_width + widening};
|
||||
place const result{Side * width, point.height};
|
||||
return lower && Section.tilt != 0.0 ? turn(Section, result, Section.tilt) : result;
|
||||
}
|
||||
|
||||
// sign of the curvature at the points, from the nearest curve along the line where it's straight
|
||||
std::vector<double> curve_sides(std::vector<double> const &Curvature)
|
||||
{
|
||||
auto const side{[](double const Curvature) { return std::abs(Curvature) > 1e-6 ? (Curvature > 0.0 ? 1.0 : -1.0) : 0.0; }};
|
||||
std::vector<double> sides(Curvature.size(), 0.0);
|
||||
double last{0.0};
|
||||
for (std::size_t i = 0; i < Curvature.size(); ++i)
|
||||
sides[i] = last = side(Curvature[i]) != 0.0 ? side(Curvature[i]) : last;
|
||||
last = 0.0;
|
||||
for (std::size_t i = Curvature.size(); i-- > 0;)
|
||||
{
|
||||
if (side(Curvature[i]) != 0.0)
|
||||
last = side(Curvature[i]);
|
||||
else if (sides[i] == 0.0)
|
||||
sides[i] = last;
|
||||
}
|
||||
return sides;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
profile const *choice::of(int const Category) const
|
||||
{
|
||||
if ((Category & 1) != 0)
|
||||
return railway;
|
||||
if ((Category & 2) != 0)
|
||||
return road;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<profile> default_profiles()
|
||||
{
|
||||
// limit installation gauge up to 1170 mm, then the outline of the unified gauge
|
||||
@@ -231,46 +272,49 @@ std::vector<section> sections(kind const Kind, std::vector<double> const &Chaina
|
||||
result[i].cant[side] = inner(fields[4]) - outer(fields[5]);
|
||||
}
|
||||
}
|
||||
auto const sides{curve_sides(Curvature)};
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
result[i].tilt = -sides[i] * std::min(1.0, Cant[i] / 1.5);
|
||||
return result;
|
||||
}
|
||||
|
||||
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 widening{wheel_zone(point) ? 0.0 : lower ? Section.lower[i] : Section.upper[i] + Section.cant[i] * point.height / 1.5};
|
||||
auto const width{Section.base + point.half_width + widening};
|
||||
place const result{Side * width, point.height};
|
||||
return lower && Section.tilt != 0.0 ? turn(Section, result, Section.tilt) : result;
|
||||
}
|
||||
|
||||
double intrusion(profile const &Profile, section const &Section, double const Lateral, double const Height)
|
||||
void ring(profile const &Profile, section const &Section, std::vector<place> &Points)
|
||||
{
|
||||
auto const count{Profile.outline.size()};
|
||||
if (count < 2)
|
||||
Points.clear();
|
||||
for (std::size_t j = 0; j < count; ++j)
|
||||
Points.push_back(outline_point(Profile, Section, j, -1));
|
||||
for (std::size_t j = count; j-- > 0;)
|
||||
Points.push_back(outline_point(Profile, Section, j, 1));
|
||||
}
|
||||
|
||||
double intrusion(std::vector<place> const &Ring, place const &Point)
|
||||
{
|
||||
if (Ring.size() < 3)
|
||||
return 0.0;
|
||||
// the outline from the bottom right up and down to the bottom left, closed across the bottom
|
||||
auto const vertex{[&](std::size_t const Index) {
|
||||
return Index < count ? outline_point(Profile, Section, Index, -1) : outline_point(Profile, Section, 2 * count - 1 - Index, 1);
|
||||
}};
|
||||
bool inside{false};
|
||||
auto nearest{std::numeric_limits<double>::max()};
|
||||
auto previous{vertex(2 * count - 1)};
|
||||
for (std::size_t i = 0; i < 2 * count; ++i)
|
||||
auto const *previous{&Ring.back()};
|
||||
for (auto const ¤t : Ring)
|
||||
{
|
||||
auto const current{vertex(i)};
|
||||
auto const lateral{current.lateral - previous.lateral};
|
||||
auto const height{current.height - previous.height};
|
||||
if ((current.height > Height) != (previous.height > Height) && Lateral < previous.lateral + lateral * (Height - previous.height) / height)
|
||||
auto const lateral{current.lateral - previous->lateral};
|
||||
auto const height{current.height - previous->height};
|
||||
if ((current.height > Point.height) != (previous->height > Point.height) && Point.lateral < previous->lateral + lateral * (Point.height - previous->height) / height)
|
||||
inside = false == inside;
|
||||
auto const length{lateral * lateral + height * height};
|
||||
auto const t{length > 0.0 ? std::clamp(((Lateral - previous.lateral) * lateral + (Height - previous.height) * height) / length, 0.0, 1.0) : 0.0};
|
||||
nearest = std::min(nearest, std::hypot(Lateral - previous.lateral - lateral * t, Height - previous.height - height * t));
|
||||
previous = current;
|
||||
auto const t{length > 0.0 ? std::clamp(((Point.lateral - previous->lateral) * lateral + (Point.height - previous->height) * height) / length, 0.0, 1.0) : 0.0};
|
||||
nearest = std::min(nearest, std::hypot(Point.lateral - previous->lateral - lateral * t, Point.height - previous->height - height * t));
|
||||
previous = ¤t;
|
||||
}
|
||||
return inside ? nearest : -nearest;
|
||||
}
|
||||
|
||||
double widest(profile const &Profile)
|
||||
{
|
||||
double result{0.0};
|
||||
for (auto const &point : Profile.outline)
|
||||
result = std::max(result, point.half_width);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace gauge
|
||||
|
||||
@@ -41,6 +41,15 @@ struct profile
|
||||
std::vector<point> outline;
|
||||
};
|
||||
|
||||
// the outlines checked along the paths: the railway one on the tracks, the road one on the roads
|
||||
struct choice
|
||||
{
|
||||
profile const *railway{nullptr};
|
||||
profile const *road{nullptr};
|
||||
// by the category flags of the path, 1 a track and 2 a road; null when there's no outline for it
|
||||
profile const *of(int Category) const;
|
||||
};
|
||||
|
||||
// GPL-1 and GPL-2 over the limit installation gauge below 1170 mm, with and without the pantograph gauge, the limit
|
||||
// and nominal installation gauges G1, G2, GA, GB, GC of the PKP PLK technical standards, and the road gauges
|
||||
std::vector<profile> default_profiles();
|
||||
@@ -70,14 +79,17 @@ struct place
|
||||
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
|
||||
// The widening begins and ends ahead of the changes of the curvature and cant, as the vehicles enter a curve;
|
||||
// the plane of the rail heads tilts with the cant, the outer rail raised
|
||||
std::vector<section> sections(kind Kind, std::vector<double> const &Chainage, std::vector<double> const &Curvature, std::vector<double> const &Cant);
|
||||
|
||||
// point of the outline on the side (+1 left, -1 right) at the section, with the widening: the cant shifts the part
|
||||
// above the lower one, the lower part turns with the plane of the rail heads instead
|
||||
place outline_point(profile const &Profile, section const &Section, std::size_t Index, int Side);
|
||||
// distance of the point from the outline in any direction, metres, positive inside and negative outside.
|
||||
// Lateral positive to the left
|
||||
double intrusion(profile const &Profile, section const &Section, double Lateral, double Height);
|
||||
// the outline across the track at the section, from the bottom right up and down to the bottom left, closed across
|
||||
// the bottom. With the widening: the cant shifts the part above the lower one, the lower part turns with the plane
|
||||
// of the rail heads instead
|
||||
void ring(profile const &Profile, section const &Section, std::vector<place> &Points);
|
||||
// distance of the point from the ring in any direction, metres, positive inside and negative outside
|
||||
double intrusion(std::vector<place> const &Ring, place const &Point);
|
||||
// largest half-width of the outline, metres
|
||||
double widest(profile const &Profile);
|
||||
|
||||
} // namespace gauge
|
||||
|
||||
Reference in New Issue
Block a user