17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-23 12:26:06 +02:00

feat(editor): the vertical profile shows the terrain model, the terrain follows it, the camera follows the plot

- The plot draws the ground of the terrain model (NMT) as measured, before any earthworks. The squares under the route are fetched in the background. The tooltip gives the grade line's distance from the model.
- Applying a profile lays the formation of the changed tracks anew, or reshapes the route's earthworks when there are any, so the heightmap terrain follows the new grade line. The terrain step is joined to the track step: one undo takes both back.
- In 3D and in the top view, the camera shows the part of the route the plot shows once the plot stops moving. It keeps clear of the floating plot window. A toggle turns this off.
- nmt_shape_tracks can shape only the given tracks, removing the modifiers of their paths that are gone.
This commit is contained in:
maj00r
2026-10-19 17:10:20 +02:00
parent fe2cd6a09a
commit 97be54e688
5 changed files with 322 additions and 15 deletions

View File

@@ -330,6 +330,24 @@ editor_mode::selftest_result editor_mode::selftest_track(std::string const &comm
}
return selftest_result::handled;
}
if (command == "vprofilemodel")
{
// the ground of the terrain model along the open route, and where the camera is
auto const &state{m_profile};
std::size_t known{0};
double low{std::numeric_limits<double>::max()};
double high{std::numeric_limits<double>::lowest()};
for (std::size_t i = 0; i < state.model.size() && i < state.samples.size(); ++i)
if (false == std::isnan(state.model[i]))
{
++known;
low = std::min(low, state.samples[i].position.y - state.model[i]);
high = std::max(high, state.samples[i].position.y - state.model[i]);
}
WriteLog(format("SELFTEST vprofilemodel: %zu of %zu samples known%s, the track %.2f..%.2f m from the model; view %.1f..%.1f, camera %.1f %.1f %.1f angle %.3f %.3f, ortho %d extent %.0f", known, state.samples.size(), state.model_waiting ? " (waiting)" : "", known > 0 ? low : 0.0, known > 0 ? high : 0.0,
state.view_from, state.view_to, Camera.Pos.x, Camera.Pos.y, Camera.Pos.z, Camera.Angle.x, Camera.Angle.y, Global.EditorOrtho ? 1 : 0, Global.EditorOrthoExtent));
return selftest_result::handled;
}
if (command == "vprofilezoom")
{
// the plot of the open profile from one chainage to another, the heights exaggerated as given (0: fitted)
@@ -382,7 +400,8 @@ editor_mode::selftest_result editor_mode::selftest_track(std::string const &comm
{
// a plain grade line from the height of the start of the open route, applied to it
double grade{0.0};
words >> grade;
std::string option;
words >> grade >> option;
auto &state{m_profile};
if (state.samples.empty())
{
@@ -394,7 +413,7 @@ editor_mode::selftest_result editor_mode::selftest_track(std::string const &comm
state.line.join_start = false;
state.line.join_end = false;
profile_check();
profile_apply();
profile_apply(option == "terrain");
WriteLog("SELFTEST vprofileapply: " + state.status + " " + state.error);
for (auto const &span : state.route.spans)
{