mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 23:49:19 +02:00
refactor(track): the rail code is split by concern into gauge lines, crossings and check rails, rail materials, rail profile measuring, planning the cuts and laying the geometry, instead of one TrackRails.cpp; rail_offset reuses nearest_distance and lateral; TTrack::rail_dimensions measures the profile through track_rails::measure_rail
This commit is contained in:
142
world/Track.cpp
142
world/Track.cpp
@@ -2613,148 +2613,10 @@ TTrack::track_rail_profile( int const Profile ) {
|
||||
track_rails::rail_size
|
||||
TTrack::rail_dimensions() const {
|
||||
|
||||
track_rails::rail_size result;
|
||||
if( m_profiles.empty() ) {
|
||||
return result;
|
||||
return {};
|
||||
}
|
||||
auto const &profile { track_rail_profile( m_profile1.second ) };
|
||||
auto const count { profile.size() / 2 };
|
||||
if( count < 2 ) {
|
||||
return result;
|
||||
}
|
||||
auto top { -1e9 };
|
||||
auto bottom { 1e9 };
|
||||
result.low = 1e9;
|
||||
result.high = -1e9;
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
top = std::max( top, static_cast<double>( point.y ) );
|
||||
bottom = std::min( bottom, static_cast<double>( point.y ) );
|
||||
result.low = std::min( result.low, static_cast<double>( point.x ) );
|
||||
result.high = std::max( result.high, static_cast<double>( point.x ) );
|
||||
}
|
||||
result.height = top - bottom;
|
||||
result.crest = top;
|
||||
std::size_t firsttop { count };
|
||||
std::size_t lasttop { 0 };
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
if( profile[ i ].position.y > top - 1e-4 ) {
|
||||
firsttop = std::min( firsttop, i );
|
||||
lasttop = std::max( lasttop, i );
|
||||
}
|
||||
}
|
||||
std::vector<glm::dvec2> sides[ 2 ];
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( i <= firsttop ) {
|
||||
sides[ 0 ].emplace_back( point.y, point.x );
|
||||
}
|
||||
if( i >= lasttop ) {
|
||||
sides[ 1 ].emplace_back( point.y, point.x );
|
||||
}
|
||||
}
|
||||
for( auto &side : sides ) {
|
||||
std::sort( side.begin(), side.end(), []( glm::dvec2 const &A, glm::dvec2 const &B ) { return A.x < B.x; } );
|
||||
}
|
||||
auto const mean = []( std::vector<glm::dvec2> const &Side ) {
|
||||
auto sum { 0.0 };
|
||||
for( auto const &knot : Side ) {
|
||||
sum += knot.y;
|
||||
}
|
||||
return sum / std::max<std::size_t>( Side.size(), 1 ); };
|
||||
auto const fieldfirst { mean( sides[ 0 ] ) > mean( sides[ 1 ] ) };
|
||||
result.field = sides[ fieldfirst ? 0 : 1 ];
|
||||
result.gauge = sides[ fieldfirst ? 1 : 0 ];
|
||||
auto const middle { top - 0.5 * result.height };
|
||||
auto webfrom { 1e9 };
|
||||
auto webto { -1e9 };
|
||||
for( std::size_t i = 0; i + 1 < count; ++i ) {
|
||||
auto const &a { profile[ i ].position };
|
||||
auto const &b { profile[ i + 1 ].position };
|
||||
if( a.y != b.y && ( a.y - middle ) * ( b.y - middle ) <= 0.0 ) {
|
||||
auto const x { a.x + ( b.x - a.x ) * ( middle - a.y ) / ( b.y - a.y ) };
|
||||
webfrom = std::min( webfrom, x );
|
||||
webto = std::max( webto, x );
|
||||
}
|
||||
}
|
||||
if( webfrom < webto ) {
|
||||
result.web = 0.5 * ( webfrom + webto );
|
||||
result.neck = top;
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( point.y > middle && ( point.x < webfrom - 0.0005 || point.x > webto + 0.0005 ) ) {
|
||||
result.neck = std::min( result.neck, static_cast<double>( point.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
result.head = 0.0;
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( point.y > top - 0.3 * result.height ) {
|
||||
result.head = std::max( result.head, static_cast<double>( point.x ) );
|
||||
}
|
||||
}
|
||||
result.tread = result.head;
|
||||
std::vector<std::size_t> heads, lips;
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( point.y > top - 0.015 ) {
|
||||
( point.x < -0.02 ? lips : heads ).push_back( i );
|
||||
}
|
||||
}
|
||||
if( heads.empty() || lips.empty() ) {
|
||||
return result;
|
||||
}
|
||||
auto const first { heads.back() < lips.front() ? heads.back() : lips.back() };
|
||||
auto const last { heads.back() < lips.front() ? lips.front() : heads.front() };
|
||||
if( first >= last || ( heads.back() > lips.front() && lips.back() > heads.front() ) ) {
|
||||
return result;
|
||||
}
|
||||
auto groove { 1e9 };
|
||||
for( auto i { first + 1 }; i < last; ++i ) {
|
||||
groove = std::min( groove, static_cast<double>( profile[ i ].position.y ) );
|
||||
}
|
||||
if( groove > top ) {
|
||||
return result;
|
||||
}
|
||||
result.grooved = true;
|
||||
result.groove = groove;
|
||||
result.lip = -1e9;
|
||||
result.liptop = -1e9;
|
||||
for( auto const i : lips ) {
|
||||
result.lip = std::max( result.lip, static_cast<double>( profile[ i ].position.x ) );
|
||||
result.liptop = std::max( result.liptop, static_cast<double>( profile[ i ].position.y ) );
|
||||
}
|
||||
result.tread = -1e9;
|
||||
for( auto const i : heads ) {
|
||||
if( profile[ i ].position.y > top - 0.0005 ) {
|
||||
result.tread = std::max( result.tread, static_cast<double>( profile[ i ].position.x ) );
|
||||
}
|
||||
}
|
||||
result.ledge = 1e9;
|
||||
for( auto const i : lips ) {
|
||||
if( profile[ i ].position.y > result.liptop - 0.0005 ) {
|
||||
result.ledge = std::min( result.ledge, static_cast<double>( profile[ i ].position.x ) );
|
||||
}
|
||||
}
|
||||
result.rim = 1e9;
|
||||
result.crown = -1e9;
|
||||
auto const reach = [&]( double const X ) {
|
||||
result.rim = std::min( result.rim, X );
|
||||
result.crown = std::max( result.crown, X ); };
|
||||
for( std::size_t i = 0; i < count; ++i ) {
|
||||
auto const &point { profile[ i ].position };
|
||||
if( point.y > groove + 1e-4 ) {
|
||||
reach( point.x );
|
||||
}
|
||||
if( i + 1 < count ) {
|
||||
auto const &next { profile[ i + 1 ].position };
|
||||
if( ( point.y - groove ) * ( next.y - groove ) < 0.0 ) {
|
||||
reach( point.x + ( next.x - point.x ) * ( groove - point.y ) / ( next.y - point.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return track_rails::measure_rail( track_rail_profile( m_profile1.second ) );
|
||||
}
|
||||
|
||||
float
|
||||
|
||||
Reference in New Issue
Block a user