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:
@@ -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 ) {
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user