17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-08 23:07:38 +01:00

feat(editor): the track laid on the terrain gets its grade line from the profile solver

In place of a line bent every ten metres to keep within 0.1 m of every bump,
the grades and the vertical curves are fitted to the ground the way the
profile fits them. Where the formation is made in the terrain model the line
keeps to the radius of the norms and cuts and fills; over the ground left as
it is it bends as sharply as it has to. The joints keep the height and the
grade of the track joined, no grade is capped and no piece is under 5 m.
This commit is contained in:
maj00r
2026-10-21 13:20:47 +02:00
parent eea0900928
commit d2d06817bc
5 changed files with 120 additions and 48 deletions

View File

@@ -25,6 +25,11 @@ namespace
using geometry::plan_distance;
using geometry::plan_of;
double constexpr kSteepest{1000.0}; // per mille: the grades of the user's own track aren't capped
double constexpr kFormed{0.5}; // m, how closely the line keeps to the ground the formation is made in
double constexpr kBare{0.1}; // m, to the ground left as it is
double constexpr kBareRadius{300.0}; // m, the vertical curves over it
} // namespace
glm::dvec3 editor_mode::cursor_terrain(double const Height)
@@ -124,7 +129,30 @@ double editor_mode::bed_height(glm::dvec3 const &Point, glm::dvec2 const &Direct
void editor_mode::follow_ground(std::vector<segment_data> &Pieces, double const Height0, double const Grade0, double const Height1, double const Grade1, TTrack const *Style) const
{
ground_follow::follow(Pieces, {Height0, Grade0, Height1, Grade1}, [&](std::vector<glm::dvec3> const &Points, std::vector<glm::dvec2> const &Directions) { return bed_heights(Points, Directions, Style); });
std::vector<glm::dvec2> points;
for (auto const &piece : Pieces)
{
geometry::bezier const curve{piece};
auto const count{std::max(6, static_cast<int>(std::ceil(curve.plan_length() / 10.0)))};
for (int i = 0; i <= count; ++i)
points.push_back(plan_of(curve.point(static_cast<double>(i) / count)));
}
// the ground the formation is made in lets the line keep to the norms of the profile, cutting and filling; the ground left as
// it is the line follows, bending as sharply as it has to
auto const formed{nmt_formed(points)};
ground_follow::grading grading;
grading.settings.norms = m_profile.line.norms;
grading.settings.norms.grade_max = kSteepest;
grading.settings.norms.curve_threshold = 0.0;
if (false == formed)
{
grading.settings.norms.radius_factor = 0.0;
grading.settings.norms.radius_min = kBareRadius;
}
grading.settings.speed = design_speed(Style, nullptr);
grading.fit.grade_max = kSteepest;
grading.fit.tolerance = formed ? kFormed : kBare;
ground_follow::follow(Pieces, {Height0, Grade0, Height1, Grade1}, [&](std::vector<glm::dvec3> const &Points, std::vector<glm::dvec2> const &Directions) { return bed_heights(Points, Directions, Style); }, grading);
}
glm::dvec3 editor_mode::lay_bed(glm::dvec3 const &Point)