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

Switches: lay the pre-blade lead and the blade, not a tangent arc

A turnout's diverging track does not leave the through track tangentially. It
runs straight along the through track to the blade tip (odcinek przediglicowy),
breaks away there by the blade angle (kąt nagięcia iglicy, beta), runs straight
over the blade to its heel, and only then curves - through alfa - beta, not the
whole crossing angle - to the frog.

Give TurnoutSegment a turn_in: a signed heading break applied before the segment
is laid, which is the only way to express a track leaving by an angle rather than
a tangent. lay_turnout then places the lead, the break and the blade ahead of the
curve and hands the curve the angle that is actually left to spend; a zero blade
length keeps the break and starts the curve at the tip. Reject a blade angle that
is negative or already reaches the crossing angle.

All-zero blade figures lay exactly the old tangent arc from PR, so existing
layouts are untouched. Junction and turnout_preset carry the three new figures
through to the panel; the presets themselves still hold zeros until the Id-1
catalogue numbers are in.

Add test_turnout: the lead sits on the through track, the blade breaks by beta,
and the frog still lands on the full crossing angle and the catalogue length,
mirrored for a right-hand turnout.
This commit is contained in:
maj00r
2026-08-27 19:36:52 +02:00
parent 4ae24114ba
commit 8cd42980e6
10 changed files with 223 additions and 25 deletions

View File

@@ -52,12 +52,24 @@ struct Turnout {
DivergeSide side{DivergeSide::Left};
DivergingCurve curve;
double length{0.0}; ///< catalogue length along the through track; 0 = a tangent-length rail
/// Odcinek przediglicowy: the straight lead from the switch start to the blade
/// tip, still along the through track. Zero for a curve tangent from the start.
double pre_blade{0.0};
/// Kąt nagięcia iglicy (beta), radians: the heading break at the blade tip. The
/// diverging track leaves the through track here, not tangentially, and the
/// curve then turns through only the remaining `alfa - beta`. Zero for a
/// tangential (curved-blade) turnout.
double blade_angle{0.0};
/// The straight blade itself, from its tip to its heel where the curve begins.
/// Zero starts the curve at the tip.
double blade_length{0.0};
};
/// One laid segment of the diverging path, as the constant/linear curvature the
/// renderer and the fitter already share (see segment_layout): a straight when
/// both curvatures are zero, an arc when they are equal, a clothoid otherwise.
struct TurnoutSegment {
double turn_in{0.0}; ///< signed heading break applied before laying this segment (the blade)
double k0{0.0};
double k1{0.0};
double length{0.0};
@@ -73,12 +85,13 @@ struct TurnoutGeometry {
double diverging_length{0.0}; ///< total length of the diverging path (curve + frog rail)
};
/// Lays a turnout forward from @p start — the switch start, tangent to the through
/// track — turning toward its side until the heading has swung by the crossing
/// angle, then running straight to the catalogue length. Never throws; returns
/// Lays a turnout forward from @p start — the switch start (początek rozjazdu),
/// tangent to the through track: the pre-blade straight, the blade breaking away
/// by `blade_angle`, the curve turning through what is left of the crossing angle,
/// then the frog rail out to the catalogue length. Never throws; returns
/// `valid == false` when the parameters admit no geometry: a non-positive radius,
/// or a curve whose fixed parts already overshoot the crossing angle before the
/// closing arc.
/// a blade angle that is negative or already reaches the crossing angle, or a
/// curve whose fixed parts overshoot the remaining angle before the closing arc.
[[nodiscard]] TurnoutGeometry lay_turnout(const geometry::Pose& start,
const Turnout& turnout);

View File

@@ -99,6 +99,9 @@ struct Junction {
bool facing{true}; ///< true opens toward increasing station, false back
double crossing_n{9.0}; ///< crossing mark 1:n (skos) → leaving angle atan(1/n)
double length{0.0}; ///< catalogue length (PR→KR along the through track); 0 = just the curve
double pre_blade{0.0}; ///< odcinek przediglicowy: straight lead PR → blade tip, metres
double blade_angle{0.0}; ///< kąt nagięcia iglicy (beta), radians; 0 = curve tangent from PR
double blade_length{0.0};///< the straight blade, tip → heel where the curve starts, metres
GapFit curve; ///< the internal diverging curve: arc / compound / basket
int branch{-1}; ///< index of the branch niweleta, pinned to the frog
};