diff --git a/application/editormode.h b/application/editormode.h index dfcb1324..3fb5bf59 100644 --- a/application/editormode.h +++ b/application/editormode.h @@ -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 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(); diff --git a/application/editormodenmt.cpp b/application/editormodenmt.cpp index e0adf534..02992d4b 100644 --- a/application/editormodenmt.cpp +++ b/application/editormodenmt.cpp @@ -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 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(std::floor(sample.position.x / kPlanCell)), static_cast(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(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 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{}}; + auto const spans{applied ? bridges : std::vector{}}; for (auto const &stretch : spans) for (std::size_t i = 0; i < count; ++i) if (sampled[i] >= stretch.from && sampled[i] <= stretch.to) diff --git a/application/editormodeprofile.cpp b/application/editormodeprofile.cpp index d7bbab48..d14dcf70 100644 --- a/application/editormodeprofile.cpp +++ b/application/editormodeprofile.cpp @@ -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 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> states; std::vector 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) diff --git a/lang/editor_pl.po b/lang/editor_pl.po index 54968b17..4a2b9083 100644 --- a/lang/editor_pl.po +++ b/lang/editor_pl.po @@ -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:"