mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-31 22:49:05 +01:00
fix(editor): the plan warns of the curved track adjoining a curve only where the curvature jumps there: a curve going on from the diverging track of a switch at its radius (R 300 after R 301 in wsd) no longer has it. The side the adjoining track turns to is taken with its radius into the chain and the design, and the curvature the design meets it with, signed by its turn, compared with it, within 5%; a design kept without the side is taken for turning its way. Unit test: R 300 from the very start after R 301 turning the same way gives no warning, turning the other way or starting with a straight does
This commit is contained in:
@@ -1088,9 +1088,37 @@ result fit_between(design const &Design)
|
||||
auto const gradeafter{(r.profile[i + 1].elevation - point.elevation) / (r.profile[i + 1].chainage - point.chainage)};
|
||||
point.tangent = point.radius * std::abs(gradeafter - gradebefore) / 2.0;
|
||||
}
|
||||
if (Design.start_radius > 0.0 && Design.start_radius < 10000.0)
|
||||
// a curved track adjoining is a jump of the curvature only where the design meets it at another one: a curve going on from
|
||||
// the diverging track of a switch at its radius isn't. The curvature of the design there is signed by the side it turns to, a
|
||||
// piece shorter than 1 cm, as a straight the fit leaves before the curve, passed over
|
||||
auto const curvature_at = [&](bool const End) {
|
||||
for (std::size_t n = 0; n < r.elements.size(); ++n)
|
||||
{
|
||||
auto const &e{r.elements[End ? r.elements.size() - 1 - n : n]};
|
||||
if (e.length < 0.01)
|
||||
continue;
|
||||
auto const arc{e.radius > 0.0 ? 1.0 / e.radius : 0.0};
|
||||
switch (e.kind)
|
||||
{
|
||||
case element_kind::arc: return arc * e.turn;
|
||||
case element_kind::transition_in: return End ? arc * e.turn : 0.0;
|
||||
case element_kind::transition_out: return End ? 0.0 : arc * e.turn;
|
||||
case element_kind::spiral: return (End ? e.curvature_end : e.curvature_start) * e.turn;
|
||||
default: return 0.0;
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
};
|
||||
auto const abrupt = [](double const Radius, int const Turn, double const Own) {
|
||||
if (Radius <= 0.0 || Radius >= 10000.0)
|
||||
return false;
|
||||
// the side not known, as of a design kept in the scenery before it was: taken for the one the design turns to
|
||||
auto const theirs{(Turn != 0 ? Turn : Own < 0.0 ? -1 : 1) / Radius};
|
||||
return std::abs(theirs - Own) > 0.05 * std::max(1.0 / Radius, std::abs(Own));
|
||||
};
|
||||
if (abrupt(Design.start_radius, Design.start_turn, curvature_at(false)))
|
||||
r.warnings.emplace_back(format(STR_C("The adjoining track at the start is curved (R %.0f m), the curvature changes abruptly"), Design.start_radius));
|
||||
if (Design.end_radius > 0.0 && Design.end_radius < 10000.0)
|
||||
if (abrupt(Design.end_radius, Design.end_turn, curvature_at(true)))
|
||||
r.warnings.emplace_back(format(STR_C("The adjoining track at the end is curved (R %.0f m), the curvature changes abruptly"), Design.end_radius));
|
||||
make_cants(Design, r);
|
||||
|
||||
|
||||
@@ -94,6 +94,10 @@ struct design
|
||||
double end_grade{0.0};
|
||||
double start_radius{0.0};
|
||||
double end_radius{0.0};
|
||||
// the side the adjoining track turns to at the start and at the end, going from the one to the other: 1 left, -1 right, 0 not
|
||||
// known; a design going on at the curvature of the adjoining track doesn't change it abruptly
|
||||
int start_turn{0};
|
||||
int end_turn{0};
|
||||
// length of the straight beyond the start and the end, which the curves can take over
|
||||
double start_reserve{0.0};
|
||||
double end_reserve{0.0};
|
||||
|
||||
@@ -97,7 +97,7 @@ double path_radius(segment_data const &Path, double const T)
|
||||
return curvature > 1e-7 ? 1.0 / curvature : 0.0;
|
||||
}
|
||||
|
||||
bool adjoining_direction(TTrack const *Neighbour, glm::dvec3 const &Joint, bool const Leaving, glm::dvec3 &Direction, double &Radius)
|
||||
bool adjoining_direction(TTrack const *Neighbour, glm::dvec3 const &Joint, bool const Leaving, glm::dvec3 &Direction, double &Radius, int &Turn)
|
||||
{
|
||||
if (Neighbour == nullptr)
|
||||
return false;
|
||||
@@ -109,8 +109,18 @@ bool adjoining_direction(TTrack const *Neighbour, glm::dvec3 const &Joint, bool
|
||||
if (glm::distance(point, Joint) > kSamePoint)
|
||||
continue;
|
||||
auto const tangent{glm::normalize(path_tangent(path, atend))};
|
||||
Direction = (Leaving != atend) ? tangent : -tangent;
|
||||
auto const along{Leaving != atend};
|
||||
Direction = along ? tangent : -tangent;
|
||||
Radius = path_radius(path, atend ? 1.0 : 0.0);
|
||||
// the side it turns to as the chain runs, the path gone against its points turning the other way
|
||||
Turn = 0;
|
||||
if (Radius > 0.0)
|
||||
{
|
||||
bezier const curve{path};
|
||||
auto const first{curve.first(atend ? 1.0 : 0.0)};
|
||||
auto const second{curve.second(atend ? 1.0 : 0.0)};
|
||||
Turn = (first.x * second.z - first.z * second.x > 0.0) == along ? 1 : -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1335,14 +1345,14 @@ bool editor_track::complete_chain(chain &Chain, std::string &Error)
|
||||
auto const firstforward{Chain.forward.front()};
|
||||
Chain.start = first.points[firstforward ? segment_data::point::start : segment_data::point::end];
|
||||
Chain.start_direction = firstforward ? path_tangent(first, false) : -path_tangent(first, true);
|
||||
adjoining_direction(firstforward ? from->trPrev : from->trNext, Chain.start, false, Chain.start_direction, Chain.start_radius);
|
||||
adjoining_direction(firstforward ? from->trPrev : from->trNext, Chain.start, false, Chain.start_direction, Chain.start_radius, Chain.start_turn);
|
||||
Chain.start_direction = glm::normalize(Chain.start_direction);
|
||||
|
||||
auto const &last{to->m_paths.front()};
|
||||
auto const lastforward{Chain.forward.back()};
|
||||
Chain.end = last.points[lastforward ? segment_data::point::end : segment_data::point::start];
|
||||
Chain.end_direction = lastforward ? path_tangent(last, true) : -path_tangent(last, false);
|
||||
adjoining_direction(lastforward ? to->trNext : to->trPrev, Chain.end, true, Chain.end_direction, Chain.end_radius);
|
||||
adjoining_direction(lastforward ? to->trNext : to->trPrev, Chain.end, true, Chain.end_direction, Chain.end_radius, Chain.end_turn);
|
||||
Chain.end_direction = glm::normalize(Chain.end_direction);
|
||||
|
||||
Error.clear();
|
||||
|
||||
@@ -272,6 +272,9 @@ class editor_track
|
||||
glm::dvec3 end_direction{0.0};
|
||||
double start_radius{0.0};
|
||||
double end_radius{0.0};
|
||||
// the side the adjoining track turns to there, going from the start to the end: 1 left, -1 right, 0 straight
|
||||
int start_turn{0};
|
||||
int end_turn{0};
|
||||
double length{0.0};
|
||||
double velocity{-1.0};
|
||||
double radius{0.0};
|
||||
|
||||
Reference in New Issue
Block a user