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:
@@ -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);
|
||||
|
||||
@@ -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)};
|
||||
|
||||
@@ -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"}};
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user