17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-20 23:23:30 +02:00

fix(track): the tip of a blade is where the diverging track of the switch is broken into pieces near the start, as a template lays it from the scheme of the switch, so blades of 60E1 and 49E1 switches keep the cut tips of their tables at 1.248, 1.500, 2.165, 2.633 and 3.335 m and blades of S42 switches start at the end of their pre-blade stretch; without such a break a blade is told angled or tangent by its angle to the stock rail taken back to where it touches it, read from the nearest point of the other rail instead of its nearest sample, which took the blade of the main track of an S42-190-1:6,6 for a tangent one

This commit is contained in:
maj00r
2026-10-17 09:59:06 +02:00
parent 2c3ab90db5
commit 21eca4d9a6
3 changed files with 47 additions and 15 deletions

View File

@@ -710,9 +710,6 @@ track_rails::switch_blade const &TTrack::blade( int const Path ) const {
glm::dvec3 point, tangent;
ours.at( 0.0, point, tangent );
auto otherat { nearest_distance( theirs, point ) };
glm::dvec3 start, along;
theirs.at( otherat, start, along );
auto const tangential { std::abs( glm::cross( glm::normalize( glm::dvec3 { tangent.x, 0.0, tangent.z } ), glm::normalize( glm::dvec3 { along.x, 0.0, along.z } ) ).y ) < blade_tangent };
for( int i = 0; i <= count; ++i ) {
auto const distance { length * i / count };
ours.at( distance, point, tangent );
@@ -736,9 +733,48 @@ track_rails::switch_blade const &TTrack::blade( int const Path ) const {
}
}
return -1.0; };
result.tip = reach( blade_point );
if( auto const nose { reach( blade_nose ) }; tangential && nose >= 0.0 ) {
result.tip = std::max( result.tip, nose - blade_planed );
auto const level = [&]( double const Distance ) {
for( std::size_t i = 1; i < gauge.size(); ++i ) {
if( gauge[ i ].x >= Distance ) {
auto const &a { gauge[ i - 1 ] };
auto const &b { gauge[ i ] };
return glm::mix( a.y, b.y, std::clamp( ( Distance - a.x ) / std::max( b.x - a.x, 1e-9 ), 0.0, 1.0 ) );
}
}
return gauge.back().y; };
auto const turn = [&]( double const Distance ) {
glm::dvec3 here, heading, line, along;
ours.at( Distance, here, heading );
auto there { nearest_distance( theirs, here ) };
lateral( theirs, side, here, there );
theirs.at( there, line, along );
return std::abs( glm::cross( glm::normalize( glm::dvec3 { heading.x, 0.0, heading.z } ), glm::normalize( glm::dvec3 { along.x, 0.0, along.z } ) ).y ); };
auto const thin { reach( blade_point ) };
auto const thick { reach( blade_nose ) };
auto angled { false };
if( thin >= 0.0 && thick > thin ) {
auto const at { turn( thin ) };
auto const bending { ( turn( thick ) - at ) / ( thick - thin ) };
angled = std::sqrt( std::max( 0.0, at * at - 2.0 * bending * blade_point ) ) >= blade_tangent;
}
result.tip = ( angled || thick < 0.0 ? thin : std::max( thin, thick - blade_planed ) );
for( auto const path : { Path, 1 - Path } ) {
auto const &segment { *SwitchExtension->Segments[ path ] };
auto mark { -1.0 };
for( std::size_t piece = 1; piece < segment.PieceCount(); ++piece ) {
auto const at { segment.PieceStart( piece ) };
auto const apart { level( at ) };
if( apart > blade_mark ) {
break;
}
if( angled || apart >= blade_gap ) {
mark = at;
}
}
if( mark >= 0.0 ) {
result.tip = std::max( mark, reach( blade_gap ) );
break;
}
}
result.full = reach( size.head + blade_gap );
auto const clear { reach( size.head + blade_clearance ) };
@@ -790,15 +826,6 @@ track_rails::switch_blade const &TTrack::blade( int const Path ) const {
bladetop = std::max( bladetop, static_cast<double>( profile[ i ].position.y ) );
}
result.drop = ( half > 0 ? std::max( 0.0, size.crest - bladetop ) : 0.0 );
auto const level = [&]( double const Distance ) {
for( std::size_t i = 1; i < gauge.size(); ++i ) {
if( gauge[ i ].x >= Distance ) {
auto const &a { gauge[ i - 1 ] };
auto const &b { gauge[ i ] };
return glm::mix( a.y, b.y, std::clamp( ( Distance - a.x ) / std::max( b.x - a.x, 1e-9 ), 0.0, 1.0 ) );
}
}
return gauge.back().y; };
auto const lowered { reach( blade_lowered + blade_gap ) };
auto const cutto { std::min( result.heel, foot >= 0.0 ? foot + blade_spacing : result.heel ) };
for( auto distance { result.tip }; distance < cutto + 0.5 * blade_spacing; distance += blade_spacing ) {

View File

@@ -41,6 +41,7 @@ double constexpr blade_point { 0.003 };
double constexpr blade_nose { 0.005 };
double constexpr blade_planed { 0.125 };
double constexpr blade_tangent { 0.00175 };
double constexpr blade_mark { 0.010 };
double constexpr blade_gap { 0.0005 };
double constexpr blade_lowered { 0.050 };
double constexpr blade_spacing { 0.5 };

View File

@@ -123,6 +123,10 @@ public:
std::size_t
PieceCount() const {
return m_pieces.size(); };
inline
double
PieceStart( std::size_t const Piece ) const {
return m_starts[ Piece ]; };
double
ComputeLength() const; // McZapkie-150503
// finds point on segment closest to specified point in 3d space. returns: point on segment as value in range 0-1