diff --git a/application/editormode.cpp b/application/editormode.cpp index 3eef9330..a3373e73 100644 --- a/application/editormode.cpp +++ b/application/editormode.cpp @@ -3934,7 +3934,8 @@ void editor_mode::render_edit_menu() group_selection(); if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", STR_C("The selected models move together from now on; a click on one selects them all. Shift+LMB adds a model to the selection")); - if (ImGui::MenuItem(STR_C("Ungroup"), "Ctrl+Shift+G", false, selected && m_node->group() > 1)) + // Delete above may have just dropped the node, selected is from before it + if (ImGui::MenuItem(STR_C("Ungroup"), "Ctrl+Shift+G", false, m_node != nullptr && m_node->group() > 1)) ungroup_selection(); if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", STR_C("The models of the group move each by itself again")); diff --git a/application/editormodeinfra.cpp b/application/editormodeinfra.cpp index 1e18d042..46585e96 100644 --- a/application/editormodeinfra.cpp +++ b/application/editormodeinfra.cpp @@ -1545,7 +1545,7 @@ void editor_mode::render_infra_candidates() if (ImGui::IsItemHovered()) { state.hovered = i; - std::string text{format(STR_C("%s, %s\n%.2f m %s of the axis, %.2f m above the rail top\n%s"), infra::name(candidate.binding.type), anchor.at.track->name().c_str(), std::abs(candidate.offset), + std::string text{format(STR_C("%s, %s\n%.2f m %s of the axis, %.2f m above the rail top\n%s"), infra::name(candidate.binding.type), anchor.at.track != nullptr ? anchor.at.track->name().c_str() : "-", std::abs(candidate.offset), candidate.offset >= 0.0 ? "right" : "left", anchor.height, candidate.reason.c_str())}; if (candidate.reader != nullptr) text += format(STR_C("\nRead by the path %s: event %s, getvalues of the memory cell %s"), candidate.reader->name().c_str(), candidate.event.c_str(), candidate.cell.c_str()) + diff --git a/application/editormodeprofile.cpp b/application/editormodeprofile.cpp index 9c23bd56..16c024f2 100644 --- a/application/editormodeprofile.cpp +++ b/application/editormodeprofile.cpp @@ -1695,16 +1695,19 @@ void editor_mode::draw_profile_canvas(profile_view const &View, ImDrawList &Draw auto const plotbottom{View.plot_bottom()}; auto const step{nice_step(View.across * 110.0)}; - for (auto s = std::ceil((state.view_from + state.origin) / step) * step - state.origin; s <= state.view_to; s += step) + auto const firsts{std::ceil((state.view_from + state.origin) / step) * step - state.origin}; + for (int i = 0; firsts + i * step <= state.view_to; ++i) { + auto const s{firsts + i * step}; auto const x{View.x_of(s)}; Draw.AddLine(ImVec2(x, plottop), ImVec2(x, plotbottom), kGrid); Draw.AddText(ImVec2(x + 3.0f, View.corner.y + 2.0f), kLabel, profile::format_chainage(s + state.origin).c_str()); } auto const heightstep{nice_step(View.vertical * 45.0)}; - for (auto h = std::floor(View.height_of(plotbottom) / heightstep) * heightstep; h <= View.height_of(plottop); h += heightstep) + auto const firsth{std::floor(View.height_of(plotbottom) / heightstep) * heightstep}; + for (int i = 0; firsth + i * heightstep <= View.height_of(plottop); ++i) { - auto const y{View.y_of(h)}; + auto const y{View.y_of(firsth + i * heightstep)}; Draw.AddLine(ImVec2(View.corner.x, y), ImVec2(bottomright.x, y), kGrid); } for (auto const &zone : state.context.switches) @@ -1772,8 +1775,10 @@ void editor_mode::draw_profile_canvas(profile_view const &View, ImDrawList &Draw auto const from{std::max(points.front().chainage, View.chainage_of(View.corner.x))}; auto const to{std::min(points.back().chainage, View.chainage_of(bottomright.x))}; ImVec2 previous{View.x_of(from), View.y_of(profile::elevation(line, from))}; - for (auto x = previous.x + 2.0f; x <= View.x_of(to) + 2.0f; x += 2.0f) + auto const firstx{previous.x}; + for (int i = 1; firstx + 2.0f * i <= View.x_of(to) + 2.0f; ++i) { + auto const x{firstx + 2.0f * i}; auto const chainage{std::min(to, View.chainage_of(x))}; ImVec2 const next{View.x_of(chainage), View.y_of(profile::elevation(line, chainage))}; Draw.AddLine(previous, next, kGradeLine, 2.5f); @@ -1827,8 +1832,8 @@ void editor_mode::draw_profile_canvas(profile_view const &View, ImDrawList &Draw plot_label(Draw, ImVec2(at.x + 8.0f, at.y - 22.0f), overlay_color::marked, text); } // heights along the left edge, over everything else - for (auto h = std::floor(View.height_of(plotbottom) / heightstep) * heightstep; h <= View.height_of(plottop); h += heightstep) - plot_label(Draw, ImVec2(View.corner.x + 4.0f, View.y_of(h) - 8.0f), kLabel, format("%.1f", h)); + for (int i = 0; firsth + i * heightstep <= View.height_of(plottop); ++i) + plot_label(Draw, ImVec2(View.corner.x + 4.0f, View.y_of(firsth + i * heightstep) - 8.0f), kLabel, format("%.1f", firsth + i * heightstep)); for (auto const &issue : state.issues) { auto const x{View.x_of(issue.chainage)}; diff --git a/application/editormodeselftest.cpp b/application/editormodeselftest.cpp index a2281e6c..c44fd133 100644 --- a/application/editormodeselftest.cpp +++ b/application/editormodeselftest.cpp @@ -321,8 +321,9 @@ void editor_mode::selftest_step() geometry::bezier const main{track->m_paths[0]}; geometry::bezier const other{track->m_paths[1]}; std::string text; - for (double t = 0.125; t < 1.01; t += 0.125) + for (int i = 1; i <= 8; ++i) { + auto const t{i * 0.125}; auto const point{other.point(t)}; double best{std::numeric_limits::max()}, along{0.0}; for (int k = 0; k <= 2000; ++k) @@ -350,8 +351,11 @@ void editor_mode::selftest_step() if (sweep == nullptr) continue; auto const side{sweep->definition().lateral >= 0.0 ? 1 : 0}; - for (double station = from; station <= to + 1e-9; station += step) + if (step <= 0.0) + continue; + for (int i = 0; from + i * step <= to + 1e-9; ++i) { + auto const station{from + i * step}; auto const at{sweep->frame_at(station)}; WriteLog(format("SELFTEST frame %s %.2f: %.3f %.3f %.3f widening %.4f cant %.4f setback %.4f", name.c_str(), station, at.position.x, at.position.y, at.position.z, at.widening[side], at.cant[side], sweep->setback(at))); } diff --git a/application/editormodeturntable.cpp b/application/editormodeturntable.cpp index 4cd20a8f..e6b78d9e 100644 --- a/application/editormodeturntable.cpp +++ b/application/editormodeturntable.cpp @@ -402,8 +402,8 @@ bool editor_mode::turntable_fit_end(editor_track::snap_target const &End, turnta for (auto const heading : {line, line + 180.0}) { auto const radial{heading_vector(heading)}; - for (auto radius{static_cast(tool.radius)}; radius >= kMinimumRadius; radius *= 0.9) - if (auto const candidate{connect(radial, radius)}) + for (int i = 0; tool.radius * std::pow(0.9, i) >= kMinimumRadius; ++i) + if (auto const candidate{connect(radial, tool.radius * std::pow(0.9, i))}) { if (better(*candidate)) best = candidate; @@ -419,8 +419,9 @@ bool editor_mode::turntable_fit_end(editor_track::snap_target const &End, turnta } else { - for (auto radius{static_cast(tool.radius)}; radius >= kMinimumRadius && false == best.has_value(); radius *= 0.9) + for (int r = 0; tool.radius * std::pow(0.9, r) >= kMinimumRadius && false == best.has_value(); ++r) { + auto const radius{tool.radius * std::pow(0.9, r)}; auto const gap = [&](double const S) { auto const vertex{e - t * S}; auto const radial{vertex - c}; @@ -432,8 +433,9 @@ bool editor_mode::turntable_fit_end(editor_track::snap_target const &End, turnta auto const limit{plan_distance(End.position, centre) + 400.0}; double low{0.0}; std::optional high; - for (double s = 0.25; s <= limit; s += 0.25) + for (int i = 1; i * 0.25 <= limit; ++i) { + auto const s{i * 0.25}; if (gap(s) >= 0.0) { high = s; diff --git a/editor/editorSpeed.cpp b/editor/editorSpeed.cpp index bf98e79e..9f4a449e 100644 --- a/editor/editorSpeed.cpp +++ b/editor/editorSpeed.cpp @@ -52,8 +52,9 @@ double jerk_limit(double const Curvature, double const Cant, double const Gauge, if (rate(Top) <= Jerk) return Top; double low{0.0}; - for (double speed = 10.0; speed <= Top; speed += 10.0) + for (int i = 1; i * 10.0 <= Top; ++i) { + auto const speed{i * 10.0}; if (rate(speed) > Jerk) { double high{speed};