From 9fedbaf6a843bd9e1d2d6b96cb63d70ef0b0747a Mon Sep 17 00:00:00 2001 From: maj00r Date: Wed, 21 Oct 2026 20:28:34 +0200 Subject: [PATCH] feat(editor): the design speed the norms lay for is shown by the cursor with the track it comes from, and can be the one set for the laying Laid to the norms, the readout says the design speed of the transition curves and of the cant: that of the track the laying goes on from or joins, or the one set for the laying. A new option takes the set speed also on from a track with its own, the new tracks get it; Ctrl+Shift+wheel steps it while laying and turns the option on. The panel shows the speed the laying under way is designed for. --- application/editormode.h | 7 +++ application/editormodelay.cpp | 72 ++++++++++++++++++++++---- application/editormodeselftest.cpp | 1 + application/editormodeselftestjoin.cpp | 8 +++ application/editormodetrack.cpp | 11 +++- lang/editor_pl.po | 18 +++++++ 6 files changed, 105 insertions(+), 12 deletions(-) diff --git a/application/editormode.h b/application/editormode.h index 2ca12cac..d68ef2fd 100644 --- a/application/editormode.h +++ b/application/editormode.h @@ -1341,6 +1341,7 @@ class editor_mode : public application_mode, private editor_track::observer, pri double piece_length{100.0}; bool copy_selected{false}; editor_track::path_style style; + bool own_speed{false}; // the speed of the style also where the track goes on from one with its own, the new tracks given it std::string status; double status_time{-100.0}; std::string skew; // what Alt turned the straight to @@ -1501,6 +1502,12 @@ class editor_mode : public application_mode, private editor_track::observer, pri std::string track_shaping(bool const Joined) const; void render_layout_combo(); double design_speed(TTrack const *From, TTrack const *To) const; + // the track whose speed the design takes, none where it's the one set for the laying + TTrack const *speed_track(TTrack const *From, TTrack const *To) const; + // the tracks the laying under way goes on from and to + std::pair laying_ends() const; + std::string design_speed_of(TTrack const *From, TTrack const *To) const; + void give_own_speed(std::vector const &Created) const; std::vector join_pieces(TTrack const *From, editor_track::point_ref const &Frompoint, glm::dvec3 const &Start, glm::dvec2 const &Direction, editor_track::snap_target const &End, double &Length, std::string &Error) const; double m_extend_length{25.0}; diff --git a/application/editormodelay.cpp b/application/editormodelay.cpp index f0e7081b..dc173cdd 100644 --- a/application/editormodelay.cpp +++ b/application/editormodelay.cpp @@ -490,20 +490,50 @@ std::vector editor_mode::extend_pieces() const return pieces; } +TTrack const *editor_mode::speed_track(TTrack const *From, TTrack const *To) const +{ + if (m_lay.own_speed && m_lay.style.velocity > 0.0) + return nullptr; + TTrack const *result{nullptr}; + for (auto const *track : {From, To}) + if (track != nullptr && editor_track::velocity(*track) > 0.0 && (result == nullptr || editor_track::velocity(*track) < editor_track::velocity(*result))) + result = track; + return result; +} + double editor_mode::design_speed(TTrack const *From, TTrack const *To) const { - double speed{0.0}; - for (auto const *track : {From, To}) + if (auto const *track{speed_track(From, To)}; track != nullptr) + return editor_track::velocity(*track); + return m_lay.style.velocity > 0.0 ? m_lay.style.velocity : 100.0; +} + +std::pair editor_mode::laying_ends() const +{ + if (m_extend.active) { - if (track == nullptr) - continue; - auto const velocity{editor_track::velocity(*track)}; - if (velocity > 0.0) - speed = speed > 0.0 ? std::min(speed, velocity) : velocity; + editor_track::snap_target target; + return {m_extend.track, extend_snap(target) ? target.track : nullptr}; } - if (speed <= 0.0) - speed = m_lay.style.velocity > 0.0 ? m_lay.style.velocity : 100.0; - return speed; + if (m_lay.active && false == m_lay.points.empty()) + return {m_lay.start.track, m_lay.points.size() == 1 ? m_lay.mouse_snap.track : nullptr}; + return {nullptr, nullptr}; +} + +std::string editor_mode::design_speed_of(TTrack const *From, TTrack const *To) const +{ + auto const speed{design_speed(From, To)}; + if (auto const *track{speed_track(From, To)}; track != nullptr) + return format(STR_C("design speed %.0f km/h, that of the track %s"), speed, name_of(*track).c_str()); + return format(STR_C("design speed %.0f km/h, set for the laying"), speed); +} + +void editor_mode::give_own_speed(std::vector const &Created) const +{ + if (false == m_lay.own_speed || m_lay.style.velocity <= 0.0) + return; + for (auto *track : Created) + editor_track::velocity(*track, m_lay.style.velocity); } std::vector editor_mode::join_pieces(TTrack const *From, editor_track::point_ref const &Frompoint, glm::dvec3 const &Start, glm::dvec2 const &Direction, editor_track::snap_target const &End, double &Length, @@ -601,6 +631,7 @@ void editor_mode::finish_extend() std::vector created; for (auto const &piece : pieces) created.push_back(editor_track::create_path(*style, piece)); + give_own_speed(created); editor_track::commit(created); digitize_drawn(created); push_track_snapshot({}, created); @@ -817,6 +848,21 @@ bool editor_mode::track_wheel(double const Offset) return radii[0]; }; first_step_done(io.KeyCtrl ? first_step::wheel : first_step::shape); + if (io.KeyCtrl && io.KeyShift) + { + static double const speeds[]{20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 120.0, 140.0, 160.0, 200.0, 250.0}; + auto const [from, to]{laying_ends()}; + auto const current{design_speed(from, to)}; + int index{0}; + for (int i = 0; i < static_cast(std::size(speeds)); ++i) + if (speeds[i] <= current + 1e-6) + index = i; + if (step < 0 && speeds[index] < current - 1e-6) + ++index; + m_lay.style.velocity = speeds[std::clamp(index + step, 0, static_cast(std::size(speeds)) - 1)]; + m_lay.own_speed = true; + return true; + } if (io.KeyCtrl) { if (false == joined) @@ -1073,6 +1119,7 @@ void editor_mode::lay_finish(editor_track::snap_target const &End) std::vector created; for (auto const &piece : pieces) created.push_back(style != nullptr ? editor_track::create_path(*style, piece) : editor_track::create_path(tool.style, piece)); + give_own_speed(created); editor_track::commit(created); digitize_drawn(created); push_track_snapshot({}, created); @@ -1470,6 +1517,11 @@ void editor_mode::render_lay_ui() value_chips("speeds", tool.style.velocity, {40.0, 60.0, 80.0, 100.0, 120.0, 160.0}, "%.0f"); tool.style.velocity = std::clamp(tool.style.velocity, 0.0, 400.0); ImGui::PopItemWidth(); + ImGui::Checkbox(STR_C("This speed also on from a track with its own"), &tool.own_speed); + item_tooltip(m_norms_free ? "Off: a track laid on from another one, or joined to it, takes the speed of that track.\nOn: the new tracks get the speed above" + : "Off: a track laid on from another one, or joined to it, is designed for the speed of that track and takes it.\nOn: it's designed for the speed above and the new tracks get it.\nWhile laying: Ctrl+Shift+wheel"); + if (auto const [from, to]{laying_ends()}; false == m_norms_free && (from != nullptr || to != nullptr)) + ImGui::TextDisabled("%s", design_speed_of(from, to).c_str()); if (auto *track{selected_track()}; track != nullptr) { std::string reason; diff --git a/application/editormodeselftest.cpp b/application/editormodeselftest.cpp index 146ff6c9..3617b307 100644 --- a/application/editormodeselftest.cpp +++ b/application/editormodeselftest.cpp @@ -122,6 +122,7 @@ editor_mode::selftest_result editor_mode::selftest_dispatch(std::string const &c // join [radius] [variant] [transitions 0|1] the free ends at the points joined, as a drag from one to the other // layto from the free end at the first point towards the second, as a drag in the layout // layclicks ... clicks of the lay tool at the points, a free end within 3 m joined +// layspeed the speed set for the laying, and whether it goes also on from a track with its own // joints ... the joints check over the scenery, the issues around the points logged, every issue with free ends without points // route the route design of the path nearest the point, a curve or the whole line // routevertex , routearc , routeshare , routekm diff --git a/application/editormodeselftestjoin.cpp b/application/editormodeselftestjoin.cpp index 46a2f94e..892e301b 100644 --- a/application/editormodeselftestjoin.cpp +++ b/application/editormodeselftestjoin.cpp @@ -130,6 +130,14 @@ editor_mode::selftest_result editor_mode::selftest_join(std::string const &comma WriteLog(std::string{"SELFTEST norms: "} + (m_norms_free ? "free" : "plk")); return selftest_result::handled; } + if (command == "layspeed") + { + int own{0}; + words >> m_lay.style.velocity >> own; + m_lay.own_speed = own != 0; + WriteLog(format("SELFTEST layspeed: %.0f km/h, own %d", m_lay.style.velocity, m_lay.own_speed ? 1 : 0)); + return selftest_result::handled; + } if (command == "tracktab") { std::string key; diff --git a/application/editormodetrack.cpp b/application/editormodetrack.cpp index 1cbc072e..bdb4d216 100644 --- a/application/editormodetrack.cpp +++ b/application/editormodetrack.cpp @@ -1795,6 +1795,8 @@ std::string editor_mode::track_readout() const auto text{radius > 0.0 ? format("L %.2f m R %.0f m", length, radius) + speed_of(radius, laying_norms()) : format("L %.2f m %s", length, STR_C("straight"))}; if (auto const eased{eased_of(m_eased_last)}; false == eased.empty()) text += "\n" + eased; + if (false == m_norms_free) + text += "\n" + design_speed_of(m_extend.track, snapped ? target.track : nullptr); if (auto const vertical{vertical_of(pieces)}; false == vertical.empty()) text += "\n" + vertical; if (snapped) @@ -1829,6 +1831,11 @@ std::string editor_mode::track_readout() const text = format("L %.1f m %s", lay.preview_length, STR_C("straight")); if (auto const eased{eased_of(m_eased_last)}; false == eased.empty()) text += "\n" + eased; + if (false == m_norms_free) + { + auto const [from, to]{laying_ends()}; + text += "\n" + design_speed_of(from, to); + } if (auto const vertical{vertical_of(lay.preview)}; false == vertical.empty()) text += "\n" + vertical; } @@ -1943,7 +1950,7 @@ std::string editor_mode::track_shaping(bool const Joined) const auto text{std::string{STR_C(names[static_cast(m_track_layout)])}}; if (m_track_layout == track_layout::arc_straight || m_track_layout == track_layout::straight_arc) text += format(" R %.0f m", m_lay.radius); - return text + "\n" + STR("Ctrl+wheel: radius, Shift+wheel: arc / straight"); + return text + "\n" + STR("Ctrl+wheel: radius, Shift+wheel: arc / straight") + (m_norms_free ? std::string{} : STR(", Ctrl+Shift+wheel: speed")); } auto const &join{m_join_last}; char const *const kinds[]{"", "straight", "arc", "curve", "reverse curve", "free curve"}; @@ -1958,7 +1965,7 @@ std::string editor_mode::track_shaping(bool const Joined) const text += format(" V %.0f km/h", join.speed); if (join.variants > 1) text += format(" %d/%d", (m_join_variant % join.variants + join.variants) % join.variants + 1, join.variants); - return text + "\n" + STR("Ctrl+wheel: radius, Shift+wheel: another shape"); + return text + "\n" + STR("Ctrl+wheel: radius, Shift+wheel: another shape") + (m_norms_free ? std::string{} : STR(", Ctrl+Shift+wheel: speed")); } void editor_mode::draw_empty_scenery_hint() diff --git a/lang/editor_pl.po b/lang/editor_pl.po index 5043132f..5b6cb1e2 100644 --- a/lang/editor_pl.po +++ b/lang/editor_pl.po @@ -10243,3 +10243,21 @@ msgstr "Krzywe przejściowe skrócone do %.0f%% długości wg norm, nie ma na wi msgid "The cant is lowered to %.0f mm, what the transition curves ramp" msgstr "Przechyłka obniżona do %.0f mm, tyle zdążą podnieść krzywe przejściowe" + +msgid "design speed %.0f km/h, that of the track %s" +msgstr "prędkość projektowa %.0f km/h, jak tor %s" + +msgid "design speed %.0f km/h, set for the laying" +msgstr "prędkość projektowa %.0f km/h, ustawiona do kładzenia" + +msgid ", Ctrl+Shift+wheel: speed" +msgstr ", Ctrl+Shift+kółko: prędkość" + +msgid "This speed also on from a track with its own" +msgstr "Ta prędkość także od toru z własną" + +msgid "Off: a track laid on from another one, or joined to it, takes the speed of that track.\nOn: the new tracks get the speed above" +msgstr "Wyłączone: tor kładziony od innego toru albo dołączany do niego bierze prędkość tamtego toru.\nWłączone: nowe tory dostają prędkość z pola powyżej" + +msgid "Off: a track laid on from another one, or joined to it, is designed for the speed of that track and takes it.\nOn: it's designed for the speed above and the new tracks get it.\nWhile laying: Ctrl+Shift+wheel" +msgstr "Wyłączone: tor kładziony od innego toru albo dołączany do niego jest projektowany na prędkość tamtego toru i ją dostaje.\nWłączone: jest projektowany na prędkość z pola powyżej i nowe tory ją dostają.\nW trakcie kładzenia: Ctrl+Shift+kółko"