diff --git a/application/editormodeselftest.cpp b/application/editormodeselftest.cpp index 593ade8a..ae224e4a 100644 --- a/application/editormodeselftest.cpp +++ b/application/editormodeselftest.cpp @@ -90,6 +90,7 @@ http://mozilla.org/MPL/2.0/. // orthophoto [in scene 0|1] the imagery layer on, placed and fitted as given // 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 // joints ... the joints check over the scenery, the issues around the points logged // screenshot // save @@ -1042,6 +1043,43 @@ void editor_mode::selftest_step() if (false == created.empty()) WriteLog(format("SELFTEST %s end: %.3f m from the target", command.c_str(), geometry::plan_distance(previous, b))); } + else if (command == "layclicks") + { + int layout{0}; + words >> layout >> m_lay.radius; + m_track_layout = static_cast(std::clamp(layout, 0, 3)); + auto const active{m_lay.active}; + m_lay.active = true; + lay_cancel(); + auto const before{m_history.size()}; + for (glm::dvec3 point{0.0}; words >> point.x >> point.z;) + { + point.y = m_lay.points.empty() ? 0.0 : m_lay.points.back().y; + m_lay.mouse = point; + m_lay.mouse_snap = editor_track::find_free_end(nullptr, 1, point, 3.0, {}); + lay_click(); + WriteLog(format("SELFTEST layclicks %.1f %.1f: %s", point.x, point.z, m_lay.status.c_str())); + } + lay_cancel(); + m_lay.active = active; + glm::dvec2 heading{0.0}; + glm::dvec3 previous{0.0}; + bool first{true}; + for (auto step{before}; step < m_history.size(); ++step) + for (auto const *track : m_history[step].created) + { + auto const &path{track->m_paths.front()}; + geometry::bezier const curve{path}; + auto const begin{glm::normalize(geometry::plan_of(curve.first(0.0)))}; + auto const &a{path.points[segment_data::point::start]}; + auto const &b{path.points[segment_data::point::end]}; + WriteLog(format("SELFTEST layclicks path %s: %.2f %.2f -> %.2f %.2f, L %.2f m, R %.1f m, kink %.4f deg, step %.4f m", track->name().c_str(), a.x, a.z, b.x, b.z, curve.plan_length(), static_cast(path.radius), + first ? 0.0 : glm::degrees(std::abs(geometry::signed_angle(heading, begin))), first ? 0.0 : glm::distance(previous, a))); + heading = glm::normalize(geometry::plan_of(curve.first(1.0))); + previous = b; + first = false; + } + } else if (command == "joints") { std::vector points; diff --git a/application/editormodetrack.cpp b/application/editormodetrack.cpp index 7c021098..cdfd354a 100644 --- a/application/editormodetrack.cpp +++ b/application/editormodetrack.cpp @@ -3495,13 +3495,13 @@ std::vector editor_mode::track_key_hints(bool const All) if (m_lay.active) { if (m_lay.points.empty()) - hints = {{"LMB", "start of the new track, on the ground or at a free end"}, {"Drag from a free end", "straight along it, to another free end: a curve joining them"}, {"Parallel", "first select a straight, then a second track beside it in the panel"}, {"Esc", "stop laying"}}; + hints = {{"LMB", "start of the new track, on the ground or at a free end"}, {"Drag from a free end", "the shape chosen towards the cursor, to a free end: joins it"}, {"Parallel", "first select a straight, then a second track beside it in the panel"}, {"Esc", "stop laying"}}; else { - bool const chained{m_lay.points.size() == 1 && m_lay.start.track != nullptr}; - hints = {{"LMB", chained ? "lay the shape up to here and go on from its end" : m_lay.points.size() == 1 ? "end of the straight, or a vertex of a curve" : "next vertex of the curve"}, {"LMB on a free end", "join and lay"}, {"Ctrl+wheel", "radius"}}; + bool const chained{m_lay.start.track != nullptr}; + hints = {{"LMB", chained ? "lay the shape up to here and go on from its end" : "lay the straight up to here and go on from its end"}, {"LMB on a free end", "join and lay"}}; if (chained || m_lay.mouse_snap.track != nullptr) - hints.push_back({"Shift+wheel", "arc / straight, at a free end: another shape"}); + hints.insert(hints.end(), {{"Ctrl+wheel", "radius"}, {"Shift+wheel", "arc / straight, at a free end: another shape"}}); hints.insert(hints.end(), {{"Enter", "lay up to the cursor"}, {"Backspace", "take back the point"}, {"Esc", "cancel"}}); if (glm::dvec2 heading; lay_heading(heading)) hints.insert(hints.begin() + 1, {"Shift", "straight on in the direction of the track"}); @@ -3669,9 +3669,7 @@ std::string editor_mode::track_readout() const if (false == lay.preview_error.empty()) text += "\n" + lay.preview_error; if (lay.points.size() == 1 && (lay.start.track != nullptr || lay.mouse_snap.track != nullptr)) - text += "\n" + track_shaping(lay.mouse_snap.track != nullptr); - else if (false == lay.points.empty()) - text += "\n" + format(STR_C("R %.0f m Ctrl+wheel: radius"), lay.radius); + text += "\n" + track_shaping(lay.mouse_snap.track != nullptr && lay.start.track != nullptr); return text; } auto const &state{m_straights}; @@ -4509,7 +4507,7 @@ bool editor_mode::track_wheel(double const Offset) return false; int const step{Offset > 0.0 ? 1 : -1}; editor_track::snap_target target; - bool const joined{m_extend.active ? extend_snap(target) : m_lay.mouse_snap.track != nullptr}; + bool const joined{m_extend.active ? extend_snap(target) : m_lay.mouse_snap.track != nullptr && m_lay.start.track != nullptr}; static double const radii[]{100.0, 150.0, 190.0, 250.0, 300.0, 400.0, 500.0, 600.0, 800.0, 1000.0, 1200.0, 1500.0, 2000.0, 3000.0, 4000.0, 6000.0}; auto const next_radius = [&](double const Current) { if (step > 0) @@ -4550,7 +4548,7 @@ std::vector editor_mode::lay_pieces(std::vector const Length = 0.0; if (Points.size() < 2) return {}; - if (Points.size() == 2 && (End.track != nullptr || tool.start.track != nullptr)) + if (Points.size() == 2) { auto const leaving{tool.start.track != nullptr ? -plan_of(tool.start.direction) : plan_of(Points[1] - Points[0])}; if (glm::length(leaving) < 1e-6) @@ -4558,10 +4556,23 @@ std::vector editor_mode::lay_pieces(std::vector const Error = STR_C("Two points lie on one another"); return {}; } - if (End.track != nullptr) + if (End.track != nullptr && tool.start.track != nullptr) return join_pieces(tool.start.track, tool.start.point, Points[0], glm::normalize(leaving), End, Length, Error); m_join_last = {}; - auto const pieces{layout_pieces(Points[0], glm::normalize(leaving), -grade_of(tool.start.direction), Points[1], tool.radius)}; + std::vector pieces; + if (tool.start.track != nullptr) + pieces = layout_pieces(Points[0], glm::normalize(leaving), -grade_of(tool.start.direction), Points[1], tool.radius); + else if (End.track == nullptr) + { + auto const length{glm::length(leaving)}; + pieces = straight_piece(Points[0], glm::normalize(leaving), (Points[1].y - Points[0].y) / length, length); + } + else if (glm::length(plan_of(End.direction)) > 1e-6) + { + auto const back{layout_pieces(End.position, glm::normalize(-plan_of(End.direction)), -grade_of(End.direction), Points[0], tool.radius)}; + for (auto piece{back.rbegin()}; piece != back.rend(); ++piece) + pieces.push_back(turned_around(*piece)); + } for (auto const &piece : pieces) Length += bezier{piece}.plan_length(); if (pieces.empty()) @@ -4707,7 +4718,7 @@ void editor_mode::lay_click() if (plan_distance(point, tool.points.back()) < 1.0) return; m_typed.clear(); - if (tool.points.size() == 1 && tool.start.track != nullptr) + if (tool.points.size() == 1) { tool.points.push_back(tool.mouse); lay_finish({}); diff --git a/lang/editor_pl.po b/lang/editor_pl.po index 54e4f947..21cd94df 100644 --- a/lang/editor_pl.po +++ b/lang/editor_pl.po @@ -29,12 +29,6 @@ msgstr "Pokaż inspektor" msgid "The curve can't be read from this path, edit it as a single path" msgstr "Z tego odcinka nie da się odczytać łuku, edytuj go jako pojedynczy odcinek" -msgid "end of the straight, or a vertex of a curve" -msgstr "koniec prostej albo wierzchołek łuku" - -msgid "next vertex of the curve" -msgstr "kolejny wierzchołek łuku" - msgid "Laying track: LMB adds the points" msgstr "Układanie toru: LPM dodaje punkty" @@ -2934,9 +2928,6 @@ msgstr "Rozjazd: wybierz typ z listy" msgid "Drag from a free end" msgstr "Przeciągnij z wolnego końca" -msgid "straight along it, to another free end: a curve joining them" -msgstr "prosta wzdłuż niego, do innego wolnego końca: łuk łączący" - msgid "moves the point, level" msgstr "przesuwa punkt w poziomie" @@ -5236,9 +5227,6 @@ msgstr "Co przeciągnięcie lub kliknięcie z wolnego końca kładzie w stronę msgid "Speed limit of the new paths, and the design speed of the transition curves and of the cant; the speed of the track joined comes first, and none higher than the radius allows" msgstr "Prędkość nowych torów i prędkość projektowa krzywych przejściowych oraz przechyłki; pierwszeństwo ma prędkość toru, do którego się dołącza, i nigdy nie wyższa, niż pozwala promień" -msgid "R %.0f m Ctrl+wheel: radius" -msgstr "R %.0f m Ctrl+kółko: promień" - msgid "Ctrl+wheel: radius, Shift+wheel: arc / straight" msgstr "Ctrl+kółko: promień, Shift+kółko: łuk / prosta" @@ -5281,5 +5269,8 @@ msgstr "łuk / prosta, na wolnym końcu: inny kształt" msgid "lay the shape up to here and go on from its end" msgstr "kładzie kształt dotąd i idzie dalej od jego końca" +msgid "lay the straight up to here and go on from its end" +msgstr "kładzie prostą dotąd i idzie dalej od jej końca" + msgid "type the radius" msgstr "wpisz promień"