mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-05 00:45:42 +01:00
feat(editor): a switch being placed slides along its straight first, so its branch lies on the line of the track it leads into (a straight between, or an arc of the switch radius right after it with the arc ending at the track's end); only when the slide leaves the straight it stays put and reverse curves fill in; the straight between reverse curves takes the speed of the switch's branch (R<300 40, <500 50, <760 60, <1200 80, <2500 100 km/h) instead of the track's
This commit is contained in:
@@ -1132,6 +1132,7 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
double along{0.0};
|
double along{0.0};
|
||||||
int forward{1};
|
int forward{1};
|
||||||
int side{1};
|
int side{1};
|
||||||
|
double moved{0.0};
|
||||||
std::vector<segment_data> paths;
|
std::vector<segment_data> paths;
|
||||||
std::string reason;
|
std::string reason;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5884,15 +5884,33 @@ bool editor_mode::plan_switch_link(switch_link &Plan) const
|
|||||||
}
|
}
|
||||||
if (shape.length > line.length - 0.02)
|
if (shape.length > line.length - 0.02)
|
||||||
return false;
|
return false;
|
||||||
|
auto const kink{glm::radians(m_joints.angle * 0.5)};
|
||||||
|
auto const plan = [&](double const Along) {
|
||||||
|
Plan.along = Along;
|
||||||
|
Plan.paths = place(Along);
|
||||||
|
if (Plan.paths.size() < 2)
|
||||||
|
return false;
|
||||||
|
auto const radius{editor_track::branch_radius(Plan.paths[1])};
|
||||||
|
Plan.link = editor_track::link_branch(branch_start(Plan.paths[1]), radius, branch_target(Plan.target), kink,
|
||||||
|
editor_track::reverse_insert(std::min(editor_track::diverging_speed(radius), design_speed(nullptr, Plan.target.track))));
|
||||||
|
Plan.reason = link_problem(Plan.target, Plan.link);
|
||||||
|
return Plan.reason.empty();
|
||||||
|
};
|
||||||
auto const from{switch_from(line, shape.length, tool.along, Plan.forward, true)};
|
auto const from{switch_from(line, shape.length, tool.along, Plan.forward, true)};
|
||||||
Plan.along = Plan.forward > 0 ? from : from + shape.length;
|
auto const snapped{Plan.forward > 0 ? from : from + shape.length};
|
||||||
Plan.paths = place(Plan.along);
|
auto const paths{place(snapped)};
|
||||||
if (Plan.paths.size() < 2)
|
if (paths.size() < 2)
|
||||||
return false;
|
return false;
|
||||||
Plan.link = editor_track::link_branch(branch_start(Plan.paths[1]), editor_track::branch_radius(Plan.paths[1]), branch_target(Plan.target), glm::radians(m_joints.angle * 0.5),
|
if (auto const shift{editor_track::branch_shift(branch_start(paths[1]), line.direction * static_cast<double>(Plan.forward), editor_track::branch_radius(paths[1]), branch_target(Plan.target), kink)})
|
||||||
editor_track::reverse_insert(design_speed(line.tracks.front(), Plan.target.track)));
|
{
|
||||||
Plan.reason = link_problem(Plan.target, Plan.link);
|
auto const along{snapped + *shift * Plan.forward};
|
||||||
return Plan.reason.empty();
|
auto const begin{Plan.forward > 0 ? along : along - shape.length};
|
||||||
|
Plan.moved = std::abs(*shift);
|
||||||
|
if (begin >= -1e-6 && begin + shape.length <= line.length + 1e-6 && plan(along) && false == Plan.link.reverse)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Plan.moved = 0.0;
|
||||||
|
return plan(snapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_mode::insert_linked_switch(switch_link const &Plan)
|
void editor_mode::insert_linked_switch(switch_link const &Plan)
|
||||||
@@ -5908,7 +5926,10 @@ void editor_mode::insert_linked_switch(switch_link const &Plan)
|
|||||||
straight_refresh();
|
straight_refresh();
|
||||||
m_switch.status.clear();
|
m_switch.status.clear();
|
||||||
switch_placed(placed);
|
switch_placed(placed);
|
||||||
m_switch.status = link_summary(Plan.target, Plan.link, editor_track::branch_radius(Plan.paths[1])) + (m_switch.status.empty() ? std::string{} : "\n" + m_switch.status);
|
auto summary{link_summary(Plan.target, Plan.link, editor_track::branch_radius(Plan.paths[1]))};
|
||||||
|
if (Plan.moved >= 0.005)
|
||||||
|
summary += format(STR_C(", the switch moved %.2f m"), Plan.moved);
|
||||||
|
m_switch.status = summary + (m_switch.status.empty() ? std::string{} : "\n" + m_switch.status);
|
||||||
ui()->set_status(m_switch.status, false);
|
ui()->set_status(m_switch.status, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5922,7 +5943,9 @@ bool editor_mode::plan_branch_link(editor_track::branch_link &Link, std::string
|
|||||||
if (std::find(tool.line.begin(), tool.line.end(), target.track) != tool.line.end())
|
if (std::find(tool.line.begin(), tool.line.end(), target.track) != tool.line.end())
|
||||||
return false;
|
return false;
|
||||||
auto const &diverging{tool.track->m_paths[1]};
|
auto const &diverging{tool.track->m_paths[1]};
|
||||||
Link = editor_track::link_branch(branch_start(diverging), editor_track::branch_radius(diverging), branch_target(target), glm::radians(m_joints.angle * 0.5), editor_track::reverse_insert(design_speed(tool.track, target.track)));
|
auto const radius{editor_track::branch_radius(diverging)};
|
||||||
|
Link = editor_track::link_branch(branch_start(diverging), radius, branch_target(target), glm::radians(m_joints.angle * 0.5),
|
||||||
|
editor_track::reverse_insert(std::min(editor_track::diverging_speed(radius), design_speed(tool.track, target.track))));
|
||||||
Reason = link_problem(target, Link);
|
Reason = link_problem(target, Link);
|
||||||
return Reason.empty();
|
return Reason.empty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,6 +225,8 @@ class editor_track
|
|||||||
};
|
};
|
||||||
static double branch_radius(segment_data const &Diverging);
|
static double branch_radius(segment_data const &Diverging);
|
||||||
static double reverse_insert(double const Speed);
|
static double reverse_insert(double const Speed);
|
||||||
|
static double diverging_speed(double const Radius);
|
||||||
|
static std::optional<double> branch_shift(branch_end const &From, glm::dvec2 const &Slide, double const Radius, branch_end const &To, double const Kink);
|
||||||
static branch_link link_branch(branch_end const &From, double const Radius, branch_end const &To, double const Kink, double const Insert);
|
static branch_link link_branch(branch_end const &From, double const Radius, branch_end const &To, double const Kink, double const Insert);
|
||||||
|
|
||||||
struct snap_target
|
struct snap_target
|
||||||
|
|||||||
@@ -386,6 +386,19 @@ double editor_track::reverse_insert(double const Speed)
|
|||||||
return Speed <= 100.0 ? 0.15 * Speed : 0.25 * Speed;
|
return Speed <= 100.0 ? 0.15 * Speed : 0.25 * Speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double editor_track::diverging_speed(double const Radius)
|
||||||
|
{
|
||||||
|
if (Radius < 300.0)
|
||||||
|
return 40.0;
|
||||||
|
if (Radius < 500.0)
|
||||||
|
return 50.0;
|
||||||
|
if (Radius < 760.0)
|
||||||
|
return 60.0;
|
||||||
|
if (Radius < 1200.0)
|
||||||
|
return 80.0;
|
||||||
|
return Radius < 2500.0 ? 100.0 : 130.0;
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -455,6 +468,35 @@ std::optional<reverse_fit> fit_reverse(glm::dvec2 const &Offset, glm::dvec2 cons
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
std::optional<double> editor_track::branch_shift(branch_end const &From, glm::dvec2 const &Slide, double const Radius, branch_end const &To, double const Kink)
|
||||||
|
{
|
||||||
|
if (glm::length(From.direction) < 1e-9 || glm::length(To.direction) < 1e-9 || glm::length(Slide) < 1e-9)
|
||||||
|
return std::nullopt;
|
||||||
|
auto const slide{glm::normalize(Slide)};
|
||||||
|
auto const tangent{glm::normalize(From.direction)};
|
||||||
|
auto const into{glm::normalize(To.direction)};
|
||||||
|
auto const turn{signed_angle(tangent, into)};
|
||||||
|
auto const offset{plan_of(To.position) - plan_of(From.position)};
|
||||||
|
auto const across{cross(into, slide)};
|
||||||
|
if (std::abs(turn) > glm::radians(170.0))
|
||||||
|
return std::nullopt;
|
||||||
|
if (std::abs(turn) <= Kink)
|
||||||
|
{
|
||||||
|
if (std::abs(across) < 1e-6)
|
||||||
|
return std::nullopt;
|
||||||
|
return cross(into, offset) / across;
|
||||||
|
}
|
||||||
|
if (Radius < 1.0)
|
||||||
|
return std::nullopt;
|
||||||
|
auto const gap{offset - unit_chord(tangent, turn) * Radius};
|
||||||
|
if (std::abs(across) >= std::sin(glm::radians(1.0)))
|
||||||
|
return cross(into, gap) / across;
|
||||||
|
auto const determinant{cross(tangent, slide)};
|
||||||
|
if (std::abs(determinant) < 1e-6 || cross(gap, slide) / determinant < -0.01)
|
||||||
|
return std::nullopt;
|
||||||
|
return cross(tangent, gap) / determinant;
|
||||||
|
}
|
||||||
|
|
||||||
editor_track::branch_link editor_track::link_branch(branch_end const &From, double const Radius, branch_end const &To, double const Kink, double const Insert)
|
editor_track::branch_link editor_track::link_branch(branch_end const &From, double const Radius, branch_end const &To, double const Kink, double const Insert)
|
||||||
{
|
{
|
||||||
branch_link result;
|
branch_link result;
|
||||||
@@ -508,6 +550,7 @@ editor_track::branch_link editor_track::link_branch(branch_end const &From, doub
|
|||||||
}
|
}
|
||||||
else if (false == reverse())
|
else if (false == reverse())
|
||||||
{
|
{
|
||||||
|
result.radius = Radius;
|
||||||
result.shortfall = std::max(0.01, -result.before);
|
result.shortfall = std::max(0.01, -result.before);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5481,3 +5481,6 @@ msgstr ", między nimi prosta %.1f m"
|
|||||||
|
|
||||||
msgid ", sharper than the switch (R %.0f m)"
|
msgid ", sharper than the switch (R %.0f m)"
|
||||||
msgstr ", ostrzej niż rozjazd (R %.0f m)"
|
msgstr ", ostrzej niż rozjazd (R %.0f m)"
|
||||||
|
|
||||||
|
msgid ", the switch moved %.2f m"
|
||||||
|
msgstr ", rozjazd przesunięty o %.2f m"
|
||||||
|
|||||||
Reference in New Issue
Block a user