17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-26 21:44:53 +01:00

feat(editor): the whole-scenery grade fit sets the tracks over a bridge or a viaduct to the bridge environment

Where the terrain model falls away under a fitted line by the abutments, the paths are cut off at the ends of the stretch as the line is applied and set to the bridge, in the same step of the history: they sound as on a bridge, get no formation and the terrain under them stays as the model has it, also after the scenery is saved and opened again. Tunnels and tracks set to the bridge already are left as they are. The status says how many paths went on a bridge.
This commit is contained in:
maj00r
2026-10-22 02:45:19 +02:00
parent f361bc406b
commit 0d9fa6337d
4 changed files with 37 additions and 13 deletions

View File

@@ -2288,8 +2288,9 @@ class editor_mode : public application_mode, private editor_track::observer, pri
void profile_restore_ground();
void render_profile_earthworks();
void profile_check();
// Terrain: the heightmap terrain follows the tracks changed
void profile_apply(bool const Terrain = false);
// Terrain: the heightmap terrain follows the tracks changed. Bridges: stretches of the route over a bridge or a viaduct, the
// paths over them cut off at their ends and set to the bridge environment
void profile_apply(bool const Terrain = false, std::vector<profile::departure> const &Bridges = {});
// the terrain under the tracks changed by the last Edits steps of the history which changed tracks
void profile_follow_terrain(std::size_t const Edits);
void profile_fit_view();

View File

@@ -2069,7 +2069,15 @@ bool editor_mode::nmt_fit_line(TTrack &Track)
profile_check();
auto const fitted_line{profile.line};
auto const authored{profile.samples};
profile_apply();
// where the model falls away under the line by the abutments, the line goes over on a bridge or a viaduct: its paths there
// are cut off and set to the bridge, the formation is laid up to it, the ground under it stays as the model has it
double constexpr kBridged{1.0}; // m
double constexpr kAbutment{100.0}; // per mille
std::vector<double> heights(count);
for (std::size_t i = 0; i < count; ++i)
heights[i] = profile::elevation(fitted_line, sampled[i]);
auto const bridges{profile::bridged(sampled, heights, model, kBridged, kAbutment)};
profile_apply(false, bridges);
auto const applied{profile.error.empty()};
// where the line parts from the model: under it a gap, a bridge or a viaduct, over it a wall or a structure above the track
auto const parted{profile::departures(fitted_line, sampled, model, 2.0 * kModel)};
@@ -2125,14 +2133,7 @@ bool editor_mode::nmt_fit_line(TTrack &Track)
m_nmt_state.laid[{static_cast<int>(std::floor(sample.position.x / kPlanCell)), static_cast<int>(std::floor(sample.position.z / kPlanCell))}].push_back(
{sample.position, sample.direction, sample.grade, editor_track::sampled_elevation(authored, sample.chainage), track != nullptr ? static_cast<double>(track->rail_height()) : 0.0, track});
}
// where the model falls away under the line by the abutments, the line goes over on a bridge or a viaduct: the formation
// is laid up to it, the ground under it stays as the model has it
double constexpr kBridged{1.0}; // m
double constexpr kAbutment{100.0}; // per mille
std::vector<double> heights(count);
for (std::size_t i = 0; i < count; ++i)
heights[i] = profile::elevation(fitted_line, sampled[i]);
auto const spans{applied ? profile::bridged(sampled, heights, model, kBridged, kAbutment) : std::vector<profile::departure>{}};
auto const spans{applied ? bridges : std::vector<profile::departure>{}};
for (auto const &stretch : spans)
for (std::size_t i = 0; i < count; ++i)
if (sampled[i] >= stretch.from && sampled[i] <= stretch.to)

View File

@@ -1450,7 +1450,7 @@ void editor_mode::profile_frame_view()
fly_to(centre - right * (shift.x * pixel) + above * (shift.y * pixel), look, distance, 0.35);
}
void editor_mode::profile_apply(bool const Terrain)
void editor_mode::profile_apply(bool const Terrain, std::vector<profile::departure> const &Bridges)
{
auto &state{m_profile};
state.status.clear();
@@ -1475,8 +1475,22 @@ void editor_mode::profile_apply(bool const Terrain)
auto const before{state.samples};
std::vector<std::pair<TTrack *, editor_track::state>> states;
std::vector<TTrack *> created;
auto cuts{profile::breaks(line)};
for (auto const &bridge : Bridges)
cuts.insert(cuts.end(), {bridge.from, bridge.to});
std::sort(cuts.begin(), cuts.end());
auto const gaps{editor_track::apply_profile(
state.route, [&](double const Chainage) { return profile::elevation(line, Chainage); }, [&](double const Chainage) { return profile::grade(line, Chainage); }, profile::breaks(line), states, created)};
state.route, [&](double const Chainage) { return profile::elevation(line, Chainage); }, [&](double const Chainage) { return profile::grade(line, Chainage); }, cuts, states, created)};
// the paths over a bridge sound and light as on one, and get no formation; within what a cut too near an end leaves on
double constexpr kBridgeEnd{0.5}; // m
std::size_t bridged{0};
for (auto const &span : state.route.spans)
if (span.track->eEnvironment != e_bridge && span.track->eEnvironment != e_tunnel
&& std::any_of(Bridges.begin(), Bridges.end(), [&](profile::departure const &Bridge) { return span.from >= Bridge.from - kBridgeEnd && span.to <= Bridge.to + kBridgeEnd; }))
{
span.track->eEnvironment = e_bridge;
++bridged;
}
auto const changed{states.size()};
auto const added{created.size()};
state.created = created;
@@ -1499,6 +1513,8 @@ void editor_mode::profile_apply(bool const Terrain)
state.status = format(STR_P("Grade line applied: %zu path changed, %zu added, largest departure %.3f m", "Grade line applied: %zu paths changed, %zu added, largest departure %.3f m", changed), changed, added, state.departure);
if (false == scene::Layers.empty())
state.status += STR_C("\nThe paths and the design (//$p lines) go to the scenery files on save");
if (bridged > 0)
state.status += format(STR_P("\nOver a bridge or a viaduct: %zu path", "\nOver a bridge or a viaduct: %zu paths", bridged), bridged);
auto const name = [](TTrack const *Track) { return name_of(*Track); };
auto const closed{std::count_if(gaps.begin(), gaps.end(), [](auto const &Gap) { return Gap.closed; })};
if (closed > 0)

View File

@@ -8960,6 +8960,12 @@ msgstr "Serwis nie zwrócił modelu terenu"
msgid "\nThe paths and the design (//$p lines) go to the scenery files on save"
msgstr "\nTory i projekt (wiersze //$p) trafią do plików scenerii przy zapisie"
msgid "\nOver a bridge or a viaduct: %zu path"
msgid_plural "\nOver a bridge or a viaduct: %zu paths"
msgstr[0] "\nNa moście lub wiadukcie: %zu tor"
msgstr[1] "\nNa moście lub wiadukcie: %zu tory"
msgstr[2] "\nNa moście lub wiadukcie: %zu torów"
msgid "\nPaths off the route brought to the height of the switches:"
msgstr "\nTory spoza trasy dociągnięte do wysokości rozjazdów:"