17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-04 03:02:05 +01:00

feat(editor): platform edge put 1.725, 1.675 or 1.650 m from the axis of the track as chosen, kept in the editor settings; models along a track set back by the gauge of the other path of each switch whose points their line passes, also when they stand by the plain track ahead of the switch or by its straight path, the widening led in from the tracks beyond the diverging path; the line beyond the ends of a sweep goes on along the straightest path

This commit is contained in:
maj00r
2026-10-08 01:12:30 +02:00
parent d4791f6a29
commit ee3833fdba
7 changed files with 163 additions and 102 deletions

View File

@@ -9,6 +9,7 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h" #include "stdafx.h"
#include "application/editormode.h" #include "application/editormode.h"
#include "editor/editorSettings.hpp"
#include "application/application.h" #include "application/application.h"
#include "application/editoruilayer.h" #include "application/editoruilayer.h"
#include "application/editorprojection.h" #include "application/editorprojection.h"
@@ -161,6 +162,8 @@ void editor_mode::selftest_step()
tool.length_mode = length == "original" ? 0 : length == "all" ? 2 : 1; tool.length_mode = length == "original" ? 0 : length == "all" ? 2 : 1;
if (tool.length_mode == 1) if (tool.length_mode == 1)
tool.length = std::stod(length); tool.length = std::stod(length);
if (values.count("edge"))
EditorSettings.platform_edge(std::stod(values["edge"]));
tool.measured.clear(); tool.measured.clear();
tool.open = true; tool.open = true;
sweep_curve(); sweep_curve();
@@ -193,7 +196,10 @@ void editor_mode::selftest_step()
{ {
// edge of the last laid model as it was made: its distance from the axis and the height of its top over the rail head // edge of the last laid model as it was made: its distance from the axis and the height of its top over the rail head
std::string name; std::string name;
words >> name; double step{20.0};
words >> name >> step;
if (name == "-")
name.clear();
auto *sweep{name.empty() ? m_sweep.edited : simulation::Sweeps.find(name)}; auto *sweep{name.empty() ? m_sweep.edited : simulation::Sweeps.find(name)};
if (sweep == nullptr) if (sweep == nullptr)
{ {
@@ -216,14 +222,14 @@ void editor_mode::selftest_step()
if (lateral * sign <= 0.0) if (lateral * sign <= 0.0)
continue; continue;
auto const axis{sweep->frame_at(station)}; auto const axis{sweep->frame_at(station)};
auto &entry{bins[static_cast<int>(station / 20.0)]}; auto &entry{bins[static_cast<int>(std::floor(station / step))]};
entry.edge = std::min(entry.edge, std::abs(lateral)); entry.edge = std::min(entry.edge, std::abs(lateral));
entry.points.emplace_back(std::abs(lateral), vertex.position.y - axis.position.y); entry.points.emplace_back(std::abs(lateral), vertex.position.y - axis.position.y);
} }
WriteLog(format("SELFTEST probe %s: %zu stretches with the model, %.1f - %.1f m of %.1f m", sweep->name().c_str(), bins.size(), sweep->start(), sweep->end(), sweep->length())); WriteLog(format("SELFTEST probe %s: %zu stretches with the model, %.1f - %.1f m of %.1f m", sweep->name().c_str(), bins.size(), sweep->start(), sweep->end(), sweep->length()));
for (auto const &[index, entry] : bins) for (auto const &[index, entry] : bins)
{ {
auto const station{index * 20.0 + 10.0}; auto const station{(index + 0.5) * step};
if (station < sweep->start() || station > sweep->end()) if (station < sweep->start() || station > sweep->end())
continue; continue;
double top{-1000.0}; double top{-1000.0};

View File

@@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/.
#include "editor/editorFormat.hpp" #include "editor/editorFormat.hpp"
#include "editor/editorGeometry.hpp" #include "editor/editorGeometry.hpp"
#include "editor/editorIncludeInfo.hpp" #include "editor/editorIncludeInfo.hpp"
#include "editor/editorSettings.hpp"
#include "rendering/renderer.h" #include "rendering/renderer.h"
#include "scene/scenelayers.h" #include "scene/scenelayers.h"
@@ -87,7 +88,7 @@ bool platform_model(std::string const &File)
// the edge of the platform 1.725 m from the axis on the side it stands, set back further by the widening of the gauge // the edge of the platform 1.725 m from the axis on the side it stands, set back further by the widening of the gauge
void platform_edge(sweep_node::state &State, std::string const &Model, double const Base) void platform_edge(sweep_node::state &State, std::string const &Model, double const Base)
{ {
State.lateral = std::copysign(1.725, State.lateral == 0.0 ? 1.0 : State.lateral); State.lateral = std::copysign(EditorSettings.platform_edge(), State.lateral == 0.0 ? 1.0 : State.lateral);
State.side_anchor = 1; State.side_anchor = 1;
State.height_anchor = 3; State.height_anchor = 3;
if (auto const height{platform_height(Model)}; height > 0.0) if (auto const height{platform_height(Model)}; height > 0.0)
@@ -96,6 +97,23 @@ void platform_edge(sweep_node::state &State, std::string const &Model, double co
State.platform = true; State.platform = true;
} }
bool platform_distance()
{
double const distances[]{1.725, 1.675, 1.650};
char const *labels[]{STR_C("1.725 m: lines of out-of-gauge loads, older platforms"), STR_C("1.675 m: nominal by the 0.55 and 0.76 m platforms"), STR_C("1.650 m: the least allowed in service")};
auto const current{EditorSettings.platform_edge()};
int chosen{0};
for (int i = 0; i < IM_ARRAYSIZE(distances); ++i)
if (std::abs(current - distances[i]) < std::abs(current - distances[chosen]))
chosen = i;
ImGui::SetNextItemWidth(300.0f);
if (false == ImGui::Combo(STR_C("edge of the platform from the axis"), &chosen, labels, IM_ARRAYSIZE(labels)))
return false;
EditorSettings.platform_edge(distances[chosen]);
EditorSettings.save();
return true;
}
segment_data reversed(segment_data const &Path) segment_data reversed(segment_data const &Path)
{ {
segment_data result{Path}; segment_data result{Path};
@@ -864,7 +882,12 @@ void editor_mode::render_sweep_ui()
changed = true; changed = true;
} }
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("The edge of the platform 1.725 m from the axis of the track, its top this high over the rail top")); ImGui::SetTooltip(STR_C("The edge of the platform %.3f m from the axis of the track, its top this high over the rail top"), EditorSettings.platform_edge());
}
if (platform_distance() && settings.platform)
{
settings.lateral = std::copysign(EditorSettings.platform_edge(), settings.lateral == 0.0 ? 1.0 : settings.lateral);
changed = true;
} }
ImGui::TextDisabled(STR_C("%.2f m %s of the axis, %.2f m over the rail top"), std::abs(settings.lateral), settings.lateral >= 0.0 ? STR_C("right") : STR_C("left"), settings.height); ImGui::TextDisabled(STR_C("%.2f m %s of the axis, %.2f m over the rail top"), std::abs(settings.lateral), settings.lateral >= 0.0 ? STR_C("right") : STR_C("left"), settings.height);
if (false == tool.curve.empty() && tool.model_length > 0.0 && ImGui::Button(STR_C("Lay it along the selected path"))) if (false == tool.curve.empty() && tool.model_length > 0.0 && ImGui::Button(STR_C("Lay it along the selected path")))
@@ -921,7 +944,7 @@ void editor_mode::render_sweep_ui()
changed = true; changed = true;
} }
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("Puts the edge facing the track 1.725 m from its axis, set back by the widening of the gauge in the curves.\n" ImGui::SetTooltip("%s", STR_C("Puts the edge facing the track at the distance chosen from its axis, set back by the widening of the gauge in the curves.\n"
"Stands on the plane of the rail heads carried on to its edge: lower on the inner side of a canted curve,\n" "Stands on the plane of the rail heads carried on to its edge: lower on the inner side of a canted curve,\n"
"higher on the outer one; on the inner side also set back by the cant times the height of the edge / 1.5")); "higher on the outer one; on the inner side also set back by the cant times the height of the edge / 1.5"));
ImGui::TextDisabled("%s", STR_C("Length")); ImGui::TextDisabled("%s", STR_C("Length"));
@@ -1676,8 +1699,13 @@ void editor_mode::render_bend()
} }
changed = true; changed = true;
} }
if (state.platform && platform_distance())
{
state.lateral = std::copysign(EditorSettings.platform_edge(), state.lateral);
changed = true;
}
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("Puts the edge facing the track 1.725 m from its axis, set back by the widening of the gauge in the curves.\n" ImGui::SetTooltip("%s", STR_C("Puts the edge facing the track at the distance chosen from its axis, set back by the widening of the gauge in the curves.\n"
"Stands on the plane of the rail heads carried on to its edge: lower on the inner side of a canted curve,\n" "Stands on the plane of the rail heads carried on to its edge: lower on the inner side of a canted curve,\n"
"higher on the outer one; on the inner side also set back by the cant times the height of the edge / 1.5")); "higher on the outer one; on the inner side also set back by the cant times the height of the edge / 1.5"));
if (changed) if (changed)
@@ -1717,9 +1745,11 @@ void editor_mode::render_bend()
ImGui::SetNextItemWidth(170.0f); ImGui::SetNextItemWidth(170.0f);
ImGui::Combo(STR_C("axis of the model along the track"), &tool.axis, axes, IM_ARRAYSIZE(axes)); ImGui::Combo(STR_C("axis of the model along the track"), &tool.axis, axes, IM_ARRAYSIZE(axes));
ImGui::Checkbox(STR_C("Turned around"), &tool.turned); ImGui::Checkbox(STR_C("Turned around"), &tool.turned);
if (platform_model(source.file))
platform_distance();
bool anchored{false}; bool anchored{false};
anchors(anchored); anchors(anchored);
auto const signature{format("%p %d %d %d %d %d %d %.4f %.4f %.4f", key, tool.track, tool.axis, tool.turned ? 1 : 0, tool.along_anchor, tool.side_anchor, tool.height_anchor, tool.point.x, tool.point.y, tool.point.z)}; auto const signature{format("%p %d %d %d %d %d %d %.4f %.4f %.4f %.3f", key, tool.track, tool.axis, tool.turned ? 1 : 0, tool.along_anchor, tool.side_anchor, tool.height_anchor, tool.point.x, tool.point.y, tool.point.z, EditorSettings.platform_edge())};
if (signature != tool.signature) if (signature != tool.signature)
{ {
tool.signature = signature; tool.signature = signature;

View File

@@ -92,6 +92,8 @@ bool editorSettings::load()
parse(value, m_orthophoto.lift); parse(value, m_orthophoto.lift);
else if (key == "ortho_in_scene") else if (key == "ortho_in_scene")
m_orthophoto.in_scene = (value == "1"); m_orthophoto.in_scene = (value == "1");
else if (key == "platform_edge")
parse(value, m_platform_edge);
else if (key.rfind(origin_prefix, 0) == 0) else if (key.rfind(origin_prefix, 0) == 0)
{ {
// northing;easting // northing;easting
@@ -130,6 +132,7 @@ bool editorSettings::save()
stream << "ortho_drape " << (m_orthophoto.drape ? 1 : 0) << "\n"; stream << "ortho_drape " << (m_orthophoto.drape ? 1 : 0) << "\n";
stream << "ortho_lift " << m_orthophoto.lift << "\n"; stream << "ortho_lift " << m_orthophoto.lift << "\n";
stream << "ortho_in_scene " << (m_orthophoto.in_scene ? 1 : 0) << "\n"; stream << "ortho_in_scene " << (m_orthophoto.in_scene ? 1 : 0) << "\n";
stream << "platform_edge " << m_platform_edge << "\n";
stream << std::fixed << std::setprecision(3); stream << std::fixed << std::setprecision(3);
for (auto const &origin : m_orthophoto_origins) for (auto const &origin : m_orthophoto_origins)
stream << origin.first << " " << origin.second.first << ";" << origin.second.second << "\n"; stream << origin.first << " " << origin.second.first << ";" << origin.second.second << "\n";

View File

@@ -39,10 +39,14 @@ public:
bool orthophoto_origin(std::string const &Scenery, double &North, double &East) const; bool orthophoto_origin(std::string const &Scenery, double &North, double &East) const;
void orthophoto_origin(std::string const &Scenery, double North, double East); void orthophoto_origin(std::string const &Scenery, double North, double East);
double platform_edge() const { return m_platform_edge; }
void platform_edge(double Distance) { m_platform_edge = Distance; }
private: private:
movement_scheme m_movement{movement_scheme::wsad}; movement_scheme m_movement{movement_scheme::wsad};
orthophoto_settings m_orthophoto; orthophoto_settings m_orthophoto;
std::map<std::string, std::pair<double, double>> m_orthophoto_origins; std::map<std::string, std::pair<double, double>> m_orthophoto_origins;
double m_platform_edge{1.725};
}; };
// global editor settings instance // global editor settings instance

View File

@@ -2599,8 +2599,8 @@ msgstr "wierzch"
msgid "Platform edge:" msgid "Platform edge:"
msgstr "Krawędź peronu:" msgstr "Krawędź peronu:"
msgid "The edge of the platform 1.725 m from the axis of the track, its top this high over the rail top" msgid "The edge of the platform %.3f m from the axis of the track, its top this high over the rail top"
msgstr "Krawędź peronu 1,725 m od osi toru, wierzch tyle nad główką szyny" msgstr "Krawędź peronu %.3f m od osi toru, wierzch tyle nad główką szyny"
msgid "Parameters of the template" msgid "Parameters of the template"
msgstr "Parametry szablonu" msgstr "Parametry szablonu"
@@ -4389,5 +4389,17 @@ msgstr "LPM na torze: tam stanie pojazd"
msgid "Platform" msgid "Platform"
msgstr "Peron" msgstr "Peron"
msgid "Puts the edge facing the track 1.725 m from its axis, set back by the widening of the gauge in the curves.\nStands on the plane of the rail heads carried on to its edge: lower on the inner side of a canted curve,\nhigher on the outer one; on the inner side also set back by the cant times the height of the edge / 1.5" msgid "Puts the edge facing the track at the distance chosen from its axis, set back by the widening of the gauge in the curves.\nStands on the plane of the rail heads carried on to its edge: lower on the inner side of a canted curve,\nhigher on the outer one; on the inner side also set back by the cant times the height of the edge / 1.5"
msgstr "Ustawia krawędź od strony toru 1,725 m od jego osi, odsuniętą o poszerzenie skrajni na łukach.\nStoi na płaszczyźnie główek szyn przedłużonej do krawędzi: niżej po wewnętrznej stronie łuku z przechyłką,\nwyżej po zewnętrznej; po wewnętrznej dodatkowo odsunięty o przechyłkę razy wysokość krawędzi / 1,5" msgstr "Ustawia krawędź od strony toru w wybranej odległości od jego osi, odsuniętą o poszerzenie skrajni na łukach.\nStoi na płaszczyźnie główek szyn przedłużonej do krawędzi: niżej po wewnętrznej stronie łuku z przechyłką,\nwyżej po zewnętrznej; po wewnętrznej dodatkowo odsunięty o przechyłkę razy wysokość krawędzi / 1,5"
msgid "1.725 m: lines of out-of-gauge loads, older platforms"
msgstr "1,725 m: linie przesyłek z przekroczoną skrajnią, starsze perony"
msgid "1.675 m: nominal by the 0.55 and 0.76 m platforms"
msgstr "1,675 m: nominalnie przy peronach 0,55 i 0,76 m"
msgid "1.650 m: the least allowed in service"
msgstr "1,650 m: najmniej dopuszczalne w eksploatacji"
msgid "edge of the platform from the axis"
msgstr "krawędź peronu od osi toru"

View File

@@ -129,12 +129,14 @@ std::vector<segment_data> paths_beyond(segment_data Last, std::vector<segment_da
for (auto const forward : {true, false}) for (auto const forward : {true, false})
{ {
auto const candidate{forward ? path : turned_piece(path)}; auto const candidate{forward ? path : turned_piece(path)};
if (next.has_value() || glm::distance(candidate.points[segment_data::point::start], at) > 0.01 || if (glm::distance(candidate.points[segment_data::point::start], at) > 0.01 || glm::dot(plan_heading(Last, 1.0), plan_heading(candidate, 0.0)) < 0.9)
glm::dot(plan_heading(Last, 1.0), plan_heading(candidate, 0.0)) < 0.9)
continue; continue;
auto const known = [&](segment_data const &Piece) { return same_points(Piece, candidate) || same_points(turned_piece(Piece), candidate); }; auto const known = [&](segment_data const &Piece) { return same_points(Piece, candidate) || same_points(turned_piece(Piece), candidate); };
if (std::any_of(Own.begin(), Own.end(), known) || std::any_of(result.begin(), result.end(), known)) if (std::any_of(Own.begin(), Own.end(), known) || std::any_of(result.begin(), result.end(), known))
continue; continue;
auto const straight{glm::dot(plan_heading(candidate, 0.0), plan_heading(candidate, 1.0))};
if (next.has_value() && straight <= glm::dot(plan_heading(*next, 0.0), plan_heading(*next, 1.0)))
continue;
next = candidate; next = candidate;
} }
} }
@@ -557,97 +559,108 @@ void sweep_node::gauge_along(std::vector<sample> &Samples)
} }
} }
void sweep_node::beside_switches(std::vector<std::pair<double, double>> const &Spans) void sweep_node::beside_switches(std::vector<sample> &Samples)
{ {
if (Samples.size() < 3)
return;
auto const side{m_state.lateral >= 0.0 ? 1 : 0}; auto const side{m_state.lateral >= 0.0 ? 1 : 0};
auto const sign{m_state.lateral >= 0.0 ? 1.0 : -1.0}; auto const sign{m_state.lateral >= 0.0 ? 1.0 : -1.0};
auto const edgeheight{std::max(0.0, m_state.height - gauge::rail_height)}; auto const edgeheight{std::max(0.0, m_state.height - gauge::rail_height)};
auto const total = [&](sample const &Sample) { return Sample.widening[side] + std::max(0.0, Sample.cant[side]) * edgeheight / 1.5; }; auto const total = [&](sample const &Sample) { return Sample.widening[side] + std::max(0.0, Sample.cant[side]) * edgeheight / 1.5; };
auto const matches = [](segment_data const &A, segment_data const &B) { auto const plan = [](glm::dvec3 const &Vector) {
for (int i = 0; i < 4; ++i) glm::dvec3 const flat{Vector.x, 0.0, Vector.z};
if (glm::distance(A.points[i], B.points[i]) > 1e-3) return glm::length(flat) > 1e-9 ? glm::normalize(flat) : glm::dvec3{0.0, 0.0, 1.0};
return false;
return true;
}; };
auto const turned = [](segment_data const &Path) { glm::dvec3 low{std::numeric_limits<double>::max()}, high{-std::numeric_limits<double>::max()};
segment_data result{Path}; for (auto const &sample : Samples)
result.points[segment_data::point::start] = Path.points[segment_data::point::end];
result.points[segment_data::point::end] = Path.points[segment_data::point::start];
result.points[segment_data::point::control1] = Path.points[segment_data::point::control2];
result.points[segment_data::point::control2] = Path.points[segment_data::point::control1];
result.rolls = {-Path.rolls[1], -Path.rolls[0]};
return result;
};
for (std::size_t piece = 0; piece < m_state.pieces.size() && piece < Spans.size(); ++piece)
{ {
auto const &own{m_state.pieces[piece]}; low = glm::min(low, sample.position);
for (auto *track : simulation::Paths.sequence()) high = glm::max(high, sample.position);
{ }
if (track == nullptr || track->eType != tt_Switch || track->m_paths.size() < 2 || for (auto *track : simulation::Paths.sequence())
plan_distance(track->m_paths.front().points[segment_data::point::start], own.points[segment_data::point::start]) > 300.0) {
continue; if (track == nullptr || track->m_editorremoved || track->eType != tt_Switch || track->m_paths.size() < 2)
for (std::size_t path = 0; path < track->m_paths.size(); ++path) continue;
auto const points{track->m_paths.front().points[segment_data::point::start]};
if (points.x < low.x - 1.0 || points.x > high.x + 1.0 || points.z < low.z - 1.0 || points.z > high.z + 1.0)
continue;
std::size_t at{0};
auto best{std::numeric_limits<double>::max()};
for (std::size_t i = 0; i < Samples.size(); ++i)
if (auto const distance{plan_distance(Samples[i].position, points)}; distance < best)
{ {
auto const forward{matches(own, track->m_paths[path])}; best = distance;
if (false == forward && false == matches(own, turned(track->m_paths[path]))) at = i;
}
if (best > sample_spacing)
continue;
auto const &near{Samples[at]};
auto const along{plan(near.tangent)};
glm::dvec3 const toward{points.x - near.position.x, 0.0, points.z - near.position.z};
if (std::abs(glm::dot(toward, glm::dvec3{-along.z, 0.0, along.x})) > 0.05)
continue;
auto const s0{near.station + glm::dot(toward, along)};
for (auto const &path : track->m_paths)
{
auto const heading{glm::dot(plan_heading(path, 0.0), along)};
if (std::abs(heading) < 0.9)
continue;
auto const beyond{paths_beyond(path, {path})};
std::vector<sample> chain;
double station{0.0};
if (heading > 0.0)
{
for (auto const &sample : Samples)
if (sample.station >= s0 - outer_reach && sample.station < s0 - 1e-3)
{
station = sample.station;
chain.push_back(sample);
}
sample_piece(path, chain, station);
for (auto const &piece : beyond)
sample_piece(piece, chain, station);
}
else
{
for (auto piece = beyond.rbegin(); piece != beyond.rend(); ++piece)
sample_piece(turned_piece(*piece), chain, station);
sample_piece(turned_piece(path), chain, station);
auto const shift{station - s0};
for (auto const &sample : Samples)
if (sample.station > s0 + 1e-3 && sample.station <= s0 + outer_reach)
{
chain.push_back(sample);
chain.back().station += shift;
}
}
gauge_along(chain);
for (auto &here : Samples)
{
if (plan_distance(here.position, points) > outer_reach + 2.0 * lead_reach + 100.0)
continue; continue;
for (std::size_t other = 0; other < track->m_paths.size(); ++other) auto const forward{plan(here.tangent)};
sample const *nearest{nullptr};
auto closest{std::numeric_limits<double>::max()};
for (auto const &point : chain)
{ {
if (other == path) auto const gap{std::abs(glm::dot(glm::dvec3{point.position.x - here.position.x, 0.0, point.position.z - here.position.z}, forward))};
continue; if (gap < closest)
std::vector<sample> chain;
double station{0.0};
if (forward)
{ {
for (auto const &sample : m_samples) closest = gap;
if (sample.station >= Spans[piece].first - outer_reach && sample.station < Spans[piece].first) nearest = &point;
{
station = sample.station;
chain.push_back(sample);
}
sample_piece(track->m_paths[other], chain, station);
}
else
{
sample_piece(turned(track->m_paths[other]), chain, station);
auto const shift{station - Spans[piece].second};
for (auto const &sample : m_samples)
if (sample.station > Spans[piece].second && sample.station <= Spans[piece].second + outer_reach)
{
chain.push_back(sample);
chain.back().station += shift;
}
}
gauge_along(chain);
for (auto &here : m_samples)
{
if (here.station < Spans[piece].first - outer_reach || here.station > Spans[piece].second + outer_reach)
continue;
glm::dvec3 const left{-here.tangent.z, 0.0, here.tangent.x};
sample const *nearest{nullptr};
auto best{std::numeric_limits<double>::max()};
for (auto const &point : chain)
{
auto const along{std::abs(glm::dot(glm::dvec3{point.position.x - here.position.x, 0.0, point.position.z - here.position.z}, here.tangent))};
if (along < best)
{
best = along;
nearest = &point;
}
}
if (nearest == nullptr || best > sample_spacing)
continue;
auto const offset{sign * glm::dot(glm::dvec3{nearest->position.x - here.position.x, 0.0, nearest->position.z - here.position.z}, glm::length(left) > 1e-9 ? glm::normalize(left) : left)};
if (offset > 0.05)
continue;
auto const needed{offset + total(*nearest)};
if (needed > total(here))
{
here.widening[side] = needed;
here.cant[side] = 0.0;
}
} }
} }
if (nearest == nullptr || closest > sample_spacing)
continue;
auto const offset{sign * glm::dot(glm::dvec3{nearest->position.x - here.position.x, 0.0, nearest->position.z - here.position.z}, glm::dvec3{-forward.z, 0.0, forward.x})};
if (offset > 0.05)
continue;
auto const needed{offset + total(*nearest)};
if (needed > total(here))
{
here.widening[side] = needed;
here.cant[side] = 0.0;
}
} }
} }
} }
@@ -759,7 +772,6 @@ void sweep_node::rebuild_samples()
{ {
m_boundsvalid = false; m_boundsvalid = false;
m_samples.clear(); m_samples.clear();
std::vector<std::pair<double, double>> spans;
std::vector<segment_data> before, after; std::vector<segment_data> before, after;
if ((m_state.widen || m_state.platform) && false == m_state.pieces.empty()) if ((m_state.widen || m_state.platform) && false == m_state.pieces.empty())
{ {
@@ -772,24 +784,18 @@ void sweep_node::rebuild_samples()
auto const head{station}; auto const head{station};
auto const first{m_samples.empty() ? std::size_t{0} : m_samples.size() - 1}; auto const first{m_samples.empty() ? std::size_t{0} : m_samples.size() - 1};
for (auto const &piece : m_state.pieces) for (auto const &piece : m_state.pieces)
{
auto const begin{station};
sample_piece(piece, m_samples, station); sample_piece(piece, m_samples, station);
spans.emplace_back(begin - head, station - head);
}
auto const last{m_samples.size()}; auto const last{m_samples.size()};
for (auto const &piece : after) for (auto const &piece : after)
sample_piece(piece, m_samples, station); sample_piece(piece, m_samples, station);
gauge_along(m_samples); gauge_along(m_samples);
if (m_state.widen || m_state.platform)
beside_switches(m_samples);
// the paths beyond the ends only lead the gauge in, the copies stay on the pieces // the paths beyond the ends only lead the gauge in, the copies stay on the pieces
m_samples.erase(m_samples.begin() + last, m_samples.end()); m_samples.erase(m_samples.begin() + last, m_samples.end());
m_samples.erase(m_samples.begin(), m_samples.begin() + first); m_samples.erase(m_samples.begin(), m_samples.begin() + first);
for (auto &sample : m_samples) for (auto &sample : m_samples)
sample.station -= head; sample.station -= head;
if ((m_state.widen || m_state.platform) && m_samples.size() > 2)
{
beside_switches(spans);
}
m_distances.clear(); m_distances.clear();
glm::dvec3 previous{0.0}; glm::dvec3 previous{0.0};
for (auto const &sample : m_samples) for (auto const &sample : m_samples)

View File

@@ -161,7 +161,7 @@ class sweep_node : public scene::basic_node
}; };
static void sample_piece(segment_data const &Piece, std::vector<sample> &Samples, double &Station); static void sample_piece(segment_data const &Piece, std::vector<sample> &Samples, double &Station);
static void gauge_along(std::vector<sample> &Samples); static void gauge_along(std::vector<sample> &Samples);
void beside_switches(std::vector<std::pair<double, double>> const &Spans); void beside_switches(std::vector<sample> &Samples);
state m_state; state m_state;
std::vector<sample> m_samples; std::vector<sample> m_samples;
std::vector<double> m_distances; std::vector<double> m_distances;