From 0513a92bc3b44f3ee30aa8502aa22c3619509ac5 Mon Sep 17 00:00:00 2001 From: maj00r Date: Fri, 23 Oct 2026 21:19:14 +0200 Subject: [PATCH] fix(sleepers): the fastening of the rails of a frog, holding more of them than its seats, stretched under them all as the plate of the frog, its ends with the clips past the feet of the wing rails, short of the feet of the rails beside, and not narrowed then; the wing rails no longer lying off its ends with no clip --- world/SleeperFastenings.cpp | 26 ++++++++++++++++++++++++-- world/SleeperRules.h | 2 ++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/world/SleeperFastenings.cpp b/world/SleeperFastenings.cpp index 8e4f4e1b..c80b6d9e 100644 --- a/world/SleeperFastenings.cpp +++ b/world/SleeperFastenings.cpp @@ -243,7 +243,29 @@ std::vector fastened_rails::on( beam const &Beam, beam_model const &M } return; } - result.push_back( { part_check, point( origin ), axis * turn, 1.f, static_cast( 0.5 * check_seats ), 0.f, true, covered > 2 } ); + fastening part { part_check, point( origin ), axis * turn, 1.f, static_cast( 0.5 * check_seats ), 0.f, true, covered > 2 }; + if( part.whole ) { + // holding more rails than its seats, as the rails of a frog: stretched under them all, its ends with the clips past the feet + // of the outer ones, short of the feet of the rails beside + auto const last { from + covered - 1 }; + auto const a { origin + turn * reach.x }; + auto const b { origin + turn * reach.y }; + auto low { rails[ from ].at - rails[ from ].foot - fastening_clip }; + auto high { rails[ last ].at + rails[ last ].foot + fastening_clip }; + if( from > 0 ) { + low = std::max( low, rails[ from - 1 ].at + rails[ from - 1 ].foot + fastening_gap ); + } + if( last + 1 < rails.size() ) { + high = std::min( high, rails[ last + 1 ].at - rails[ last + 1 ].foot - fastening_gap ); + } + low = std::min( low, std::min( a, b ) ); + high = std::max( high, std::max( a, b ) ); + auto const scale { ( high - low ) / ( reach.y - reach.x ) }; + part.pivot = 0.f; + part.scale = static_cast( scale ); + part.shift = static_cast( turn * ( 0.5 * ( low + high ) - origin ) - scale * 0.5 * ( reach.x + reach.y ) ); + } + result.push_back( part ); if( from > First ) { crowd( First, from - 1 ); } @@ -365,7 +387,7 @@ void fastened_rails::fit( std::vector &Fastenings, beam const &Beam, switch( Fastening.part ) { case part_plate: { return plate_least; } case part_slide: { return slide_least; } - case part_check: { return Fastening.whole ? 1.0 : check_least; } + case part_check: { return Fastening.whole ? static_cast( Fastening.scale ) : check_least; } default: { return 1.0; } } }; // those of one rail together, the rails in the order along the timber diff --git a/world/SleeperRules.h b/world/SleeperRules.h index 4248b4be..bba9b833 100644 --- a/world/SleeperRules.h +++ b/world/SleeperRules.h @@ -61,6 +61,8 @@ double constexpr fastening_nose { 0.05 }; double constexpr fastening_crowd { 0.3 }; // how far apart the rails lie in the fastening of both, the check part of the model double constexpr check_seats { 0.113 }; +// how far past the edge of the foot of a rail its fastening reaches, with the clip holding it +double constexpr fastening_clip { 0.09 }; // the room left between the fastenings of rails close by, and how narrow their plates get to keep it double constexpr fastening_gap { 0.01 }; double constexpr plate_least { 0.6 };