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

refactor(track): one plan projection, cross product and meeting of two lines in plan for the crossings of rails, the frog of a switch and the check rails, in place of copies in each

This commit is contained in:
maj00r
2026-10-13 19:05:11 +02:00
parent 9016d72d74
commit 1aaaa3be9c

View File

@@ -17,6 +17,27 @@ http://mozilla.org/MPL/2.0/.
namespace {
glm::dvec2 plan( glm::dvec3 const &V ) {
return glm::dvec2{ V.x, V.z };
}
double cross( glm::dvec2 const &A, glm::dvec2 const &B ) {
return A.x * B.y - A.y * B.x;
}
bool meet( glm::dvec2 const &A0, glm::dvec2 const &A, glm::dvec2 const &B0, glm::dvec2 const &B, double const Parallel, double &U, double &V ) {
auto const denominator { cross( A, B ) };
if( std::abs( denominator ) < Parallel ) {
return false;
}
U = cross( B0 - A0, B ) / denominator;
V = cross( B0 - A0, A ) / denominator;
return true;
}
// gauge line of a rail: the running edge of its head, along a path and on past its ends along the tangents
struct gauge_line {
TSegment const *segment { nullptr };
@@ -64,10 +85,10 @@ gauge_line make_gauge_line( TSegment const &Segment, double const Offset, double
for( int i = 0; i <= count; ++i ) {
add( From + ( length - From ) * i / count );
}
line.low = line.high = glm::dvec2{ line.points.front().x, line.points.front().z };
line.low = line.high = plan( line.points.front() );
for( auto const &point : line.points ) {
line.low = glm::min( line.low, glm::dvec2{ point.x, point.z } );
line.high = glm::max( line.high, glm::dvec2{ point.x, point.z } );
line.low = glm::min( line.low, plan( point ) );
line.high = glm::max( line.high, plan( point ) );
}
return line;
}
@@ -324,11 +345,10 @@ glm::dvec3 rail_point( TTrack const &Track, int const Path, int const Side, doub
void rail_offset( TTrack const &Track, int const Path, int const Side, glm::dvec3 const &Point, double &Distance, double &Lateral ) {
auto const line { make_gauge_line( path_segment( Track, Path ), Side * 0.5 * std::abs( Track.fTrackWidth ), 0.0 ) };
auto const flat = []( glm::dvec3 const &V ) { return glm::dvec2{ V.x, V.z }; };
Distance = line.distances.front();
auto nearest { std::numeric_limits<double>::max() };
for( std::size_t i = 0; i < line.points.size(); ++i ) {
auto const gap { glm::length( flat( line.points[ i ] - Point ) ) };
auto const gap { glm::length( plan( line.points[ i ] - Point ) ) };
if( gap < nearest ) {
nearest = gap;
Distance = line.distances[ i ];
@@ -337,10 +357,10 @@ void rail_offset( TTrack const &Track, int const Path, int const Side, glm::dvec
glm::dvec3 point, tangent;
for( int step = 0; step < 8; ++step ) {
line.at( Distance, point, tangent );
Distance += glm::dot( flat( Point - point ), glm::normalize( flat( tangent ) ) );
Distance += glm::dot( plan( Point - point ), glm::normalize( plan( tangent ) ) );
}
line.at( Distance, point, tangent );
Lateral = -glm::dot( flat( Point - point ), flat( line.normal( Distance, Side ) ) );
Lateral = -glm::dot( plan( Point - point ), plan( line.normal( Distance, Side ) ) );
}
} // namespace track_rails
@@ -407,10 +427,6 @@ std::vector<TTrack::rail_crossing> TTrack::rail_crossings( bool const Joined ) {
}
}
}
auto const cross = []( glm::dvec2 const &A, glm::dvec2 const &B ) {
return A.x * B.y - A.y * B.x; };
auto const plan = []( glm::dvec3 const &V ) {
return glm::dvec2{ V.x, V.z }; };
auto const bend = [&]( gauge_line const &Line, double const At ) {
glm::dvec3 point, before, after;
Line.at( At - 1.0, point, before );
@@ -452,12 +468,10 @@ std::vector<TTrack::rail_crossing> TTrack::rail_crossings( bool const Joined ) {
|| alow.y > std::max( b0.y, b0.y + b.y ) + reach || std::min( b0.y, b0.y + b.y ) - reach > ahigh.y ) {
continue;
}
auto const denominator { cross( a, b ) };
if( std::abs( denominator ) < 1e-12 ) {
double u, v;
if( false == meet( a0, a, b0, b, 1e-12, u, v ) ) {
continue;
}
auto const u { cross( b0 - a0, b ) / denominator };
auto const v { cross( b0 - a0, a ) / denominator };
if( u < -0.01 || u > 1.01 || v < -0.01 || v > 1.01 ) {
continue;
}
@@ -618,7 +632,6 @@ TTrack::check_rail_set TTrack::check_rails( std::vector<rail_crossing> const &Cr
}
auto const halfwidth { 0.5 * std::abs( fTrackWidth ) };
auto const clearance { 0.046 + 0.04 * size.head / 0.0735 + size.head };
auto const flat = []( glm::dvec3 const &V ) { return glm::dvec2{ V.x, V.z }; };
for( int path = 0; path < ( eType == tt_Switch ? 2 : 1 ); ++path ) {
auto const &segment { path_segment( *this, path ) };
auto const length { segment.GetLength() };
@@ -642,8 +655,8 @@ TTrack::check_rail_set TTrack::check_rails( std::vector<rail_crossing> const &Cr
}
// check rails keep clear of the blades and the rails of the other path of a switch running inside the rail, here and in a switch joined at an end, and of the blade tips
std::vector<glm::dvec2> blocks;
auto const start { flat( segment.FastGetPoint_0() ) };
auto const end { flat( segment.FastGetPoint_1() ) };
auto const start { plan( segment.FastGetPoint_0() ) };
auto const end { plan( segment.FastGetPoint_1() ) };
std::vector<gauge_line> others;
auto const add_path = [&]( TSegment const &Other ) {
others.push_back( make_gauge_line( Other, -halfwidth, 0.0 ) );
@@ -656,7 +669,7 @@ TTrack::check_rail_set TTrack::check_rails( std::vector<rail_crossing> const &Cr
if( neighbour == nullptr || neighbour == this || neighbour->eType != tt_Switch || neighbour->SwitchExtension == nullptr ) {
continue;
}
auto const tip { flat( neighbour->SwitchExtension->Segments[ 0 ]->FastGetPoint_0() ) };
auto const tip { plan( neighbour->SwitchExtension->Segments[ 0 ]->FastGetPoint_0() ) };
if( glm::distance( start, tip ) < 0.1 ) {
blocks.emplace_back( -1e9, 0.3 );
continue;
@@ -668,7 +681,7 @@ TTrack::check_rail_set TTrack::check_rails( std::vector<rail_crossing> const &Cr
for( int otherpath = 0; otherpath < 2; ++otherpath ) {
auto const &other { *neighbour->SwitchExtension->Segments[ otherpath ] };
auto const continues = [&]( glm::dvec2 const &Point ) {
return glm::distance( Point, flat( other.FastGetPoint_0() ) ) < 0.1 || glm::distance( Point, flat( other.FastGetPoint_1() ) ) < 0.1; };
return glm::distance( Point, plan( other.FastGetPoint_0() ) ) < 0.1 || glm::distance( Point, plan( other.FastGetPoint_1() ) ) < 0.1; };
if( false == continues( start ) && false == continues( end ) ) {
add_path( other );
}
@@ -680,20 +693,17 @@ TTrack::check_rail_set TTrack::check_rails( std::vector<rail_crossing> const &Cr
for( auto s { check.from }; s <= check.to; s += 0.1 ) {
glm::dvec3 point, tangent;
ours.at( s, point, tangent );
auto const gauge { flat( point ) };
auto const inward { flat( ours.normal( s, side ) ) };
auto const gauge { plan( point ) };
auto const inward { plan( ours.normal( s, side ) ) };
auto blocked { false };
for( auto const &other : others ) {
for( std::size_t i = 1; i < other.points.size() && false == blocked; ++i ) {
auto const a { flat( other.points[ i - 1 ] ) };
auto const edge { flat( other.points[ i ] ) - a };
auto const determinant { inward.x * edge.y - inward.y * edge.x };
if( std::abs( determinant ) < 1e-9 ) {
auto const a { plan( other.points[ i - 1 ] ) };
auto const edge { plan( other.points[ i ] ) - a };
double t, u;
if( false == meet( gauge, inward, a, edge, 1e-9, t, u ) ) {
continue;
}
auto const offset { a - gauge };
auto const t { ( offset.x * edge.y - offset.y * edge.x ) / determinant };
auto const u { ( offset.x * inward.y - offset.y * inward.x ) / determinant };
blocked = ( u > -1e-6 && u < 1.0 + 1e-6 && t > -0.05 && t < clearance );
}
}
@@ -754,8 +764,6 @@ TTrack::switch_frog TTrack::frog() const {
distances[ path ].push_back( distance );
}
}
auto const cross = []( glm::dvec2 const &A, glm::dvec2 const &B ) {
return A.x * B.y - A.y * B.x; };
for( std::size_t i = 1; i < lines[ 0 ].size() && false == result.valid; ++i ) {
if( distances[ 0 ][ i ] <= result.blades[ 0 ] ) {
continue;
@@ -768,12 +776,10 @@ TTrack::switch_frog TTrack::frog() const {
}
auto const b0 { lines[ 1 ][ j - 1 ] };
auto const b { lines[ 1 ][ j ] - b0 };
auto const denominator { cross( a, b ) };
if( std::abs( denominator ) < 1e-12 ) {
double u, v;
if( false == meet( a0, a, b0, b, 1e-12, u, v ) ) {
continue;
}
auto const u { cross( b0 - a0, b ) / denominator };
auto const v { cross( b0 - a0, a ) / denominator };
if( u < 0.0 || u > 1.0 || v < 0.0 || v > 1.0 ) {
continue;
}
@@ -805,11 +811,6 @@ TTrack::switch_frog TTrack::frog() const {
namespace {
glm::dvec2 plan( glm::dvec3 const &V ) {
return glm::dvec2{ V.x, V.z };
}
// a wing rail ending right beside a check rail of the rail it runs along goes on in its place up to the far end of it, past the end of the wing
std::vector<glm::dvec2> wing_extension( TTrack &Track, TTrack::check_rail_set const &Checks, int const Path, int const Side, double const At, double const Toward, double const Slope, TTrack &Partner, int const Partnerpath, int const Partnerside, double const Partnerat, double const Partnerdirection ) {