17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-31 20:29:04 +01:00

feat(editor): a slip goes only where the straights cross at the skos of its template: a Rkpd 1:9 was laid at a crossing of 1:7 or 1:14 as well, shaped for the angle of the tracks there into no slip of the catalogue. The straights crossing at a skos more than 0.14 deg off it, half of what keeps 1:9.51 and 1:10 apart, are refused with the skos they cross at and the slip of the same kind made for it, of the same rail and radius first, or none; a double slip replaced by one of another skos likewise. The panel and the hints say the slip goes at its skos. Selftest: a Rkpd 49E1-190-1:9 laid at 1:9 and 1:9.08, refused at 1:7 with no template for it and at 1:9.51 with Rkpd S42-230-1:9,51 fitting

This commit is contained in:
maj00r
2026-10-27 19:35:01 +01:00
parent f8a12107a0
commit 7f6a8736ca
5 changed files with 72 additions and 3 deletions

View File

@@ -1674,6 +1674,9 @@ class editor_mode : public application_mode, private editor_track::observer, pri
std::array<glm::dvec3, 4> points{};
};
bool plan_double_slip(editor_track::straight const &Line, glm::dvec3 const &Point, editor_track::switch_template const &Shape, slip_plan &Plan) const;
// a slip is made for its skos: where the tracks cross at another one, the refusal, which tells the template made for theirs; empty
// where it fits, and for a crossing
std::string slip_skew(editor_track::switch_template const &Shape, double const Angle) const;
// the cursor where it points at the straight, at the height of the straight there
glm::dvec3 cursor_on_straight(editor_track::straight const &Line) const;
bool insert_double_slip(editor_track::straight const &Line, glm::dvec3 const &Point, editor_track::switch_template const &Shape);

View File

@@ -44,6 +44,9 @@ http:
using namespace track_mode;
// the name of the template in the language of the editor, editormodeswitchtool.cpp
std::string switch_name_translated(std::string Title);
std::vector<segment_data> editor_mode::switch_preview() const
{
auto const &tool{m_switch};
@@ -1065,6 +1068,11 @@ bool editor_mode::plan_double_slip(editor_track::straight const &Line, glm::dvec
Plan.problem = STR_C("The straights cross at an angle unsuitable for a double slip");
return false;
}
if (auto const skew{slip_skew(Shape, angle)}; false == skew.empty())
{
Plan.problem = skew;
return false;
}
auto const alongfirst{glm::dot(crossing - plan_of(Line.start), Line.direction)};
auto const alongsecond{glm::dot(crossing - plan_of(second.start), second.direction)};
auto const available{std::min({alongfirst, Line.length - alongfirst, alongsecond, second.length - alongsecond}) - 0.5};
@@ -1110,6 +1118,33 @@ bool editor_mode::plan_double_slip(editor_track::straight const &Line, glm::dvec
return true;
}
std::string editor_mode::slip_skew(editor_track::switch_template const &Shape, double const Angle) const
{
// rad: the tracks crossing at the skos of the slip to within this, half of what keeps 1:9.51 and 1:10 of the catalogue apart
auto const tolerance{glm::radians(0.14)};
auto const fits = [&](editor_track::switch_template const &Template) { return Template.ratio > 0.0 && std::abs(Angle - std::atan(1.0 / Template.ratio)) <= tolerance; };
if (Shape.type == "Skrz" || false == Shape.double_slip || Shape.ratio <= 0.0 || fits(Shape))
return {};
// a slip of the same kind made for the skos of the tracks, of the same rail and radius before the others
editor_track::switch_template const *fitting{nullptr};
auto best{-1};
for (auto const &entry : m_switch.templates)
{
if (false == entry.double_slip || entry.type != Shape.type || false == fits(entry))
continue;
auto const rank{(entry.rail == Shape.rail ? 2 : 0) + (std::abs(entry.radius - Shape.radius) < 0.5 ? 1 : 0)};
if (rank > best)
{
best = rank;
fitting = &entry;
}
}
auto const ratio{1.0 / std::tan(Angle)};
if (fitting == nullptr)
return format(STR_C("The straights cross at 1:%.2f, %s is made for 1:%.2f and no slip template is made for that"), ratio, switch_name_translated(Shape.title()).c_str(), Shape.ratio);
return format(STR_C("The straights cross at 1:%.2f, %s is made for 1:%.2f: %s fits that crossing"), ratio, switch_name_translated(Shape.title()).c_str(), Shape.ratio, switch_name_translated(fitting->title()).c_str());
}
bool editor_mode::insert_double_slip(editor_track::straight const &Line, glm::dvec3 const &Point, editor_track::switch_template const &Shape)
{
auto &state{m_straights};
@@ -1241,6 +1276,11 @@ bool editor_mode::replace_double_slip(TTrack &Part, editor_track::switch_templat
auto const t{cross(plan_of(c.point) - plan_of(a.point), direction) / determinant};
glm::dvec2 const crossing{plan_of(a.point) + first * t};
auto const angle{std::atan2(std::abs(cross(first, direction)), glm::dot(first, direction))};
if (auto const skew{slip_skew(Shape, angle)}; false == skew.empty())
{
state.status = refused(skew);
return false;
}
auto const oldhalf{glm::distance(plan_of(a.point), crossing)};
auto const blade{switch_design::secant_blade(Shape.rail, Shape.radius, Shape.ratio)};
auto curve{editor_track::slip_of(Shape.radius, Shape.middle, angle, 0.5 * std::abs(switches[0]->fTrackWidth) + switches[0]->rail_dimensions().head + 0.002, blade.first, blade.second)};

View File

@@ -139,7 +139,10 @@ std::string template_tooltip(editor_track::switch_template const &Template)
text += "\n";
text += Template.type == "Rkp" ? STR_C("Single slip (Rkp)") : Template.type == "Rkpd" ? STR_C("Double slip (Rkpd)") : STR_C("Crossing (Skrz)");
text += "\n" + format(STR_C("a %.3f m from the middle of the crossing to the joint"), Template.a) + "\n";
text += Template.type == "Rkp" ? STR_C("Drag at a crossing of two straights, on the side of the tracks to join") : STR_C("Drag at a crossing of two straights");
if (Template.type == "Skrz")
text += STR_C("Drag at a crossing of two straights");
else
text += Template.type == "Rkp" ? STR_C("Drag at a crossing of two straights at its skos, on the side of the tracks to join") : STR_C("Drag at a crossing of two straights at its skos");
return text;
}
text += "\n" + format(STR_C("a %.3f m to the centre of the switch, b %.3f m on to its end"), Template.a, Template.b);
@@ -228,7 +231,7 @@ void editor_mode::render_switch_ui()
char const *tooltip;
};
choice const choices[] = {{switch_kind::single, "Switch", "A switch in a straight or a curve"},
{switch_kind::slip, "Slip switch", "Rkp or Rkpd at a crossing of two straights"},
{switch_kind::slip, "Slip switch", "Rkp or Rkpd at a crossing of two straights at its skos"},
{switch_kind::crossing, "Crossing", "A crossing of two straights"},
{switch_kind::connection, "Connection", "Crossover, double, scissors, ladder"}};
{
@@ -274,7 +277,7 @@ void editor_mode::render_switch_ui()
std::vector<std::pair<char const *, char const *>> how;
switch (kind)
{
case switch_kind::slip:
case switch_kind::slip: how = {{"Drag at a crossing", "of two straights at the skos of the slip: it goes there"}}; break;
case switch_kind::crossing: how = {{"Drag at a crossing", "of two straights: it goes there"}}; break;
case switch_kind::connection:
how = {{"Drag", "from a straight onto the other track"}, {"Shift+wheel", "the kind"}, {"Ctrl+wheel", "R of the aligning curve"}};

View File

@@ -1754,6 +1754,8 @@ std::vector<editor_mode::key_hint> editor_mode::track_key_hints(bool const All)
}
else if (m_track_tab == track_tab::turnout && m_switch.armed < 0)
hints = {{"List in the panel", "the type of the switch"}, {"LMB on a track", "another track"}};
else if (m_track_tab == track_tab::turnout && current_switch_kind() == switch_kind::slip)
hints = {{"Press+drag at a crossing", "of two straights at the skos of the slip"}};
else if (m_track_tab == track_tab::turnout)
hints = {{"Press+drag on the track", "along: direction, sideways: side"}, {"List in the panel", "the type of the switch"}, {"LMB on another track", "choose it"}};
else if (m_track_tab == track_tab::profile && m_profile.route.spans.empty())

View File

@@ -12366,3 +12366,24 @@ msgstr "Przeciągnij na skrzyżowaniu dwóch prostych"
msgid "Drag at a crossing of two straights, on the side of the tracks to join"
msgstr "Przeciągnij na skrzyżowaniu dwóch prostych, po stronie torów do połączenia"
msgid "The straights cross at 1:%.2f, %s is made for 1:%.2f: %s fits that crossing"
msgstr "Proste krzyżują się pod 1:%.2f, %s jest na 1:%.2f: do tego skrzyżowania pasuje %s"
msgid "The straights cross at 1:%.2f, %s is made for 1:%.2f and no slip template is made for that"
msgstr "Proste krzyżują się pod 1:%.2f, %s jest na 1:%.2f i żaden szablon rozjazdu krzyżowego nie jest na taki skos"
msgid "Drag at a crossing of two straights at its skos, on the side of the tracks to join"
msgstr "Przeciągnij na skrzyżowaniu dwóch prostych pod jego skosem, po stronie torów do połączenia"
msgid "Drag at a crossing of two straights at its skos"
msgstr "Przeciągnij na skrzyżowaniu dwóch prostych pod jego skosem"
msgid "Rkp or Rkpd at a crossing of two straights at its skos"
msgstr "Rozjazd krzyżowy pojedynczy (Rkp) albo podwójny (Rkpd) na skrzyżowaniu dwóch prostych pod jego skosem"
msgid "of two straights at the skos of the slip: it goes there"
msgstr "dwóch prostych pod skosem rozjazdu: tam stanie"
msgid "of two straights at the skos of the slip"
msgstr "dwóch prostych pod skosem rozjazdu"