mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-06 12:48:35 +01:00
perf(track): the gauge lines, crossings and check rails of a track are kept until a track is made, rebuilt or removed, so laying the rails of a track no longer recomputes its neighbours' crossings for each wing rail; self-test command railtime times planning the rails of all tracks
This commit is contained in:
@@ -47,6 +47,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
// select <track name>
|
// select <track name>
|
||||||
// frog [name] logs where the inner rails of each switch cross: distance on both paths, 1:n, throat, nose, check rails
|
// frog [name] logs where the inner rails of each switch cross: distance on both paths, 1:n, throat, nose, check rails
|
||||||
// guards [name] logs each guard rail and what each of its ends and breaks is cut along; a fault when a cut is not along a rail or a glued end not on the guard rail of the other track
|
// guards [name] logs each guard rail and what each of its ends and breaks is cut along; a fault when a cut is not along a rail or a glued end not on the guard rail of the other track
|
||||||
|
// railtime lays out the rails of every track, as when its geometry is made, and logs how long it took
|
||||||
// crossings [name] logs where rails of tracks cross rails of other tracks, checks that each acute crossing has one partner and one nose
|
// crossings [name] logs where rails of tracks cross rails of other tracks, checks that each acute crossing has one partner and one nose
|
||||||
// frogkey name [on|off] sets or clears the frogs key of a switch (one undo step); logs the key, whether it is written, the frog and the crossings
|
// frogkey name [on|off] sets or clears the frogs key of a switch (one undo step); logs the key, whether it is written, the frog and the crossings
|
||||||
// geomhash [name] logs the number of vertices and a hash of the drawn geometry of each rail track (rails, trackbed, cut faces), to compare builds
|
// geomhash [name] logs the number of vertices and a hash of the drawn geometry of each rail track (rails, trackbed, cut faces), to compare builds
|
||||||
@@ -344,6 +345,21 @@ void editor_mode::selftest_step()
|
|||||||
}
|
}
|
||||||
WriteLog(format("SELFTEST guards: %d guard rails, %d faults", count, faults));
|
WriteLog(format("SELFTEST guards: %d guard rails, %d faults", count, faults));
|
||||||
}
|
}
|
||||||
|
else if (command == "railtime")
|
||||||
|
{
|
||||||
|
track_rails::forget();
|
||||||
|
auto const started{std::chrono::steady_clock::now()};
|
||||||
|
int tracks{0};
|
||||||
|
for (auto *track : simulation::Paths.sequence())
|
||||||
|
{
|
||||||
|
if (track == nullptr || track->m_editorremoved || (track->iCategoryFlag & 15) != 1)
|
||||||
|
continue;
|
||||||
|
track->plan_rails(true);
|
||||||
|
++tracks;
|
||||||
|
}
|
||||||
|
auto const elapsed{std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - started).count()};
|
||||||
|
WriteLog(format("SELFTEST railtime: the rails of %d tracks laid out in %.1f ms", tracks, elapsed));
|
||||||
|
}
|
||||||
else if (command == "crossings")
|
else if (command == "crossings")
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|||||||
@@ -171,10 +171,14 @@ void TIsolated::Modify(int i, TDynamicObject *o)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// tworzenie nowego odcinka ruchu
|
// tworzenie nowego odcinka ruchu
|
||||||
TTrack::TTrack( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
TTrack::TTrack( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {
|
||||||
|
|
||||||
|
track_rails::forget();
|
||||||
|
}
|
||||||
|
|
||||||
TTrack::~TTrack()
|
TTrack::~TTrack()
|
||||||
{ // likwidacja odcinka
|
{ // likwidacja odcinka
|
||||||
|
track_rails::forget();
|
||||||
if( eType == tt_Cross ) {
|
if( eType == tt_Cross ) {
|
||||||
delete SwitchExtension->vPoints; // skrzyżowanie może mieć punkty
|
delete SwitchExtension->vPoints; // skrzyżowanie może mieć punkty
|
||||||
}
|
}
|
||||||
@@ -1359,6 +1363,7 @@ glm::vec3 TTrack::get_nearest_point(const glm::dvec3 &point) const
|
|||||||
// wypełnianie tablic VBO
|
// wypełnianie tablic VBO
|
||||||
void TTrack::rebuild_geometry( gfx::geometrybank_handle const &Bank ) {
|
void TTrack::rebuild_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||||
|
|
||||||
|
track_rails::forget();
|
||||||
Geometry1.clear();
|
Geometry1.clear();
|
||||||
Geometry2.clear();
|
Geometry2.clear();
|
||||||
GeometryCut1.clear();
|
GeometryCut1.clear();
|
||||||
|
|||||||
@@ -116,10 +116,34 @@ bool replaced_check( std::vector<TTrack::check_rail> const &Checks, double const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct rails_memo {
|
||||||
|
std::optional<gauge_line> lines[ 2 ][ 2 ][ 2 ]; // path, right side, from the blades
|
||||||
|
std::optional<std::vector<TTrack::rail_crossing>> own;
|
||||||
|
std::optional<std::vector<TTrack::rail_crossing>> joined;
|
||||||
|
std::optional<TTrack::check_rail_set> checks;
|
||||||
|
};
|
||||||
|
std::unordered_map<TTrack const *, rails_memo> memos;
|
||||||
|
unsigned int memostamp { 0 };
|
||||||
|
unsigned int stamp { 1 };
|
||||||
|
|
||||||
|
rails_memo &memo_of( TTrack const &Track ) {
|
||||||
|
|
||||||
|
if( memostamp != stamp ) {
|
||||||
|
memos.clear();
|
||||||
|
memostamp = stamp;
|
||||||
|
}
|
||||||
|
return memos[ &Track ];
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace track_rails {
|
namespace track_rails {
|
||||||
|
|
||||||
|
void forget() {
|
||||||
|
|
||||||
|
++stamp;
|
||||||
|
}
|
||||||
|
|
||||||
double wing_reach( double const Slope ) {
|
double wing_reach( double const Slope ) {
|
||||||
|
|
||||||
return 0.15 / Slope + 0.3;
|
return 0.15 / Slope + 0.3;
|
||||||
@@ -323,148 +347,174 @@ void rail_offset( TTrack const &Track, int const Path, int const Side, glm::dvec
|
|||||||
|
|
||||||
using namespace track_rails;
|
using namespace track_rails;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// gauge line of a rail of a track, along a path of a switch from past its blades when Blades
|
||||||
|
gauge_line const &rail_line( TTrack const &Track, int const Path, int const Side, bool const Blades ) {
|
||||||
|
|
||||||
|
auto const blades { Blades && Track.eType == tt_Switch };
|
||||||
|
auto &line { memo_of( Track ).lines[ Path ][ Side ][ blades ] };
|
||||||
|
if( false == line.has_value() ) {
|
||||||
|
line = make_gauge_line( path_segment( Track, Path ), ( Side ? 1.0 : -1.0 ) * ( 0.5 * std::abs( Track.fTrackWidth ) ), blades ? blade_length( Track, Path ) : 0.0 );
|
||||||
|
}
|
||||||
|
return *line;
|
||||||
|
}
|
||||||
|
|
||||||
|
TTrack::check_rail_set const &rail_checks( TTrack &Track ) {
|
||||||
|
|
||||||
|
auto &checks { memo_of( Track ).checks };
|
||||||
|
if( false == checks.has_value() ) {
|
||||||
|
checks = Track.check_rails( Track.rail_crossings() );
|
||||||
|
}
|
||||||
|
return *checks;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
std::vector<TTrack::rail_crossing> TTrack::rail_crossings( bool const Joined ) {
|
std::vector<TTrack::rail_crossing> TTrack::rail_crossings( bool const Joined ) {
|
||||||
|
|
||||||
std::vector<rail_crossing> result;
|
std::vector<rail_crossing> result;
|
||||||
if( false == cut_rails( *this ) || simulation::Region == nullptr ) {
|
if( false == cut_rails( *this ) || simulation::Region == nullptr ) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
auto &memo { memo_of( *this ) };
|
||||||
|
if( Joined && memo.joined.has_value() ) {
|
||||||
|
return *memo.joined;
|
||||||
|
}
|
||||||
auto const extension { 10.0 };
|
auto const extension { 10.0 };
|
||||||
auto const halfwidth { 0.5 * std::abs( fTrackWidth ) };
|
|
||||||
auto const paths { eType == tt_Switch ? 2 : 1 };
|
auto const paths { eType == tt_Switch ? 2 : 1 };
|
||||||
gauge_line ours[ 2 ][ 2 ];
|
if( memo.own.has_value() ) {
|
||||||
for( int path = 0; path < paths; ++path ) {
|
result = *memo.own;
|
||||||
for( int side = 0; side < 2; ++side ) {
|
|
||||||
ours[ path ][ side ] = make_gauge_line( path_segment( *this, path ), ( side ? 1.0 : -1.0 ) * halfwidth, 0.0 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
auto const sections { simulation::Region->sections( location(), static_cast<float>( radius() + 50.0 ) ) };
|
else {
|
||||||
std::vector<TTrack *> others;
|
auto const sections { simulation::Region->sections( location(), static_cast<float>( radius() + 50.0 ) ) };
|
||||||
for( auto *section : sections ) {
|
std::vector<TTrack *> others;
|
||||||
for( auto const &cell : section->m_cells ) {
|
for( auto *section : sections ) {
|
||||||
if( glm::length( cell.area().center - location() ) > cell.area().radius + radius() + 1.0 ) {
|
for( auto const &cell : section->m_cells ) {
|
||||||
continue;
|
if( glm::length( cell.area().center - location() ) > cell.area().radius + radius() + 1.0 ) {
|
||||||
}
|
|
||||||
for( auto *other : cell.m_directories.paths ) {
|
|
||||||
if( other == nullptr || other == this || false == cut_rails( *other ) ) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if( glm::length( other->location() - location() ) > other->radius() + radius() + 1.0 ) {
|
for( auto *other : cell.m_directories.paths ) {
|
||||||
continue;
|
if( other == nullptr || other == this || false == cut_rails( *other ) ) {
|
||||||
}
|
continue;
|
||||||
if( std::find( others.begin(), others.end(), other ) == others.end() ) {
|
}
|
||||||
others.push_back( other );
|
if( glm::length( other->location() - location() ) > other->radius() + radius() + 1.0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( std::find( others.begin(), others.end(), other ) == others.end() ) {
|
||||||
|
others.push_back( other );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
auto const cross = []( glm::dvec2 const &A, glm::dvec2 const &B ) {
|
||||||
auto const cross = []( glm::dvec2 const &A, glm::dvec2 const &B ) {
|
return A.x * B.y - A.y * B.x; };
|
||||||
return A.x * B.y - A.y * B.x; };
|
auto const plan = []( glm::dvec3 const &V ) {
|
||||||
auto const plan = []( glm::dvec3 const &V ) {
|
return glm::dvec2{ V.x, V.z }; };
|
||||||
return glm::dvec2{ V.x, V.z }; };
|
auto const bend = [&]( gauge_line const &Line, double const At ) {
|
||||||
auto const bend = [&]( gauge_line const &Line, double const At ) {
|
glm::dvec3 point, before, after;
|
||||||
glm::dvec3 point, before, after;
|
Line.at( At - 1.0, point, before );
|
||||||
Line.at( At - 1.0, point, before );
|
Line.at( At + 1.0, point, after );
|
||||||
Line.at( At + 1.0, point, after );
|
return std::abs( cross( plan( before ), plan( after ) ) ); };
|
||||||
return std::abs( cross( plan( before ), plan( after ) ) ); };
|
auto const heading = []( glm::dvec2 const &Tangent ) {
|
||||||
auto const heading = []( glm::dvec2 const &Tangent ) {
|
auto const angle { std::atan2( Tangent.y, Tangent.x ) };
|
||||||
auto const angle { std::atan2( Tangent.y, Tangent.x ) };
|
return ( angle < 0.0 ? angle + M_PI : angle ); };
|
||||||
return ( angle < 0.0 ? angle + M_PI : angle ); };
|
auto const overlap = []( gauge_line const &A, gauge_line const &B ) {
|
||||||
auto const overlap = []( gauge_line const &A, gauge_line const &B ) {
|
return A.low.x <= B.high.x && B.low.x <= A.high.x && A.low.y <= B.high.y && B.low.y <= A.high.y; };
|
||||||
return A.low.x <= B.high.x && B.low.x <= A.high.x && A.low.y <= B.high.y && B.low.y <= A.high.y; };
|
for( auto *other : others ) {
|
||||||
for( auto *other : others ) {
|
auto const otherpaths { other->eType == tt_Switch ? 2 : 1 };
|
||||||
auto const otherwidth { 0.5 * std::abs( other->fTrackWidth ) };
|
for( int otherpath = 0; otherpath < otherpaths; ++otherpath ) {
|
||||||
auto const otherpaths { other->eType == tt_Switch ? 2 : 1 };
|
auto const &othersegment { path_segment( *other, otherpath ) };
|
||||||
for( int otherpath = 0; otherpath < otherpaths; ++otherpath ) {
|
auto const otherfrom { other->eType == tt_Switch ? blade_length( *other, otherpath ) : 0.0 };
|
||||||
auto const &othersegment { path_segment( *other, otherpath ) };
|
auto const otherlength { othersegment.GetLength() };
|
||||||
auto const otherfrom { other->eType == tt_Switch ? blade_length( *other, otherpath ) : 0.0 };
|
for( int otherside = 0; otherside < 2; ++otherside ) {
|
||||||
auto const otherlength { othersegment.GetLength() };
|
auto const &theirs { rail_line( *other, otherpath, otherside, true ) };
|
||||||
for( int otherside = 0; otherside < 2; ++otherside ) {
|
for( int path = 0; path < paths; ++path ) {
|
||||||
auto const theirs { make_gauge_line( othersegment, ( otherside ? 1.0 : -1.0 ) * otherwidth, otherfrom ) };
|
auto const length { path_segment( *this, path ).GetLength() };
|
||||||
for( int path = 0; path < paths; ++path ) {
|
for( int side = 0; side < 2; ++side ) {
|
||||||
auto const length { path_segment( *this, path ).GetLength() };
|
auto const &line { rail_line( *this, path, side, false ) };
|
||||||
for( int side = 0; side < 2; ++side ) {
|
if( false == overlap( line, theirs ) ) {
|
||||||
auto const &line { ours[ path ][ side ] };
|
continue;
|
||||||
if( false == overlap( line, theirs ) ) {
|
}
|
||||||
continue;
|
for( std::size_t i = 1; i < line.points.size(); ++i ) {
|
||||||
}
|
auto const a0 { plan( line.points[ i - 1 ] ) };
|
||||||
for( std::size_t i = 1; i < line.points.size(); ++i ) {
|
auto const a { plan( line.points[ i ] ) - a0 };
|
||||||
auto const a0 { plan( line.points[ i - 1 ] ) };
|
for( std::size_t j = 1; j < theirs.points.size(); ++j ) {
|
||||||
auto const a { plan( line.points[ i ] ) - a0 };
|
auto const b0 { plan( theirs.points[ j - 1 ] ) };
|
||||||
for( std::size_t j = 1; j < theirs.points.size(); ++j ) {
|
auto const b { plan( theirs.points[ j ] ) - b0 };
|
||||||
auto const b0 { plan( theirs.points[ j - 1 ] ) };
|
auto const denominator { cross( a, b ) };
|
||||||
auto const b { plan( theirs.points[ j ] ) - b0 };
|
if( std::abs( denominator ) < 1e-12 ) {
|
||||||
auto const denominator { cross( a, b ) };
|
continue;
|
||||||
if( std::abs( denominator ) < 1e-12 ) {
|
}
|
||||||
continue;
|
auto const u { cross( b0 - a0, b ) / denominator };
|
||||||
}
|
auto const v { cross( b0 - a0, a ) / denominator };
|
||||||
auto const u { cross( b0 - a0, b ) / denominator };
|
if( u < -0.01 || u > 1.01 || v < -0.01 || v > 1.01 ) {
|
||||||
auto const v { cross( b0 - a0, a ) / denominator };
|
continue;
|
||||||
if( u < -0.01 || u > 1.01 || v < -0.01 || v > 1.01 ) {
|
}
|
||||||
continue;
|
auto s { glm::mix( line.distances[ i - 1 ], line.distances[ i ], u ) };
|
||||||
}
|
auto t { glm::mix( theirs.distances[ j - 1 ], theirs.distances[ j ], v ) };
|
||||||
auto s { glm::mix( line.distances[ i - 1 ], line.distances[ i ], u ) };
|
glm::dvec3 p, tp, q, tq;
|
||||||
auto t { glm::mix( theirs.distances[ j - 1 ], theirs.distances[ j ], v ) };
|
for( int step = 0; step < 6; ++step ) {
|
||||||
glm::dvec3 p, tp, q, tq;
|
line.at( s, p, tp );
|
||||||
for( int step = 0; step < 6; ++step ) {
|
theirs.at( t, q, tq );
|
||||||
|
auto const d { cross( plan( tp ), plan( tq ) ) };
|
||||||
|
if( std::abs( d ) < 1e-9 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto const offset { plan( q ) - plan( p ) };
|
||||||
|
s += cross( offset, plan( tq ) ) / d;
|
||||||
|
t += cross( offset, plan( tp ) ) / d;
|
||||||
|
}
|
||||||
line.at( s, p, tp );
|
line.at( s, p, tp );
|
||||||
theirs.at( t, q, tq );
|
theirs.at( t, q, tq );
|
||||||
auto const d { cross( plan( tp ), plan( tq ) ) };
|
if( glm::length( plan( p ) - plan( q ) ) > 0.01
|
||||||
if( std::abs( d ) < 1e-9 ) {
|
|| s < 0.0 || s > length
|
||||||
break;
|
|| t < otherfrom || t > otherlength ) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
auto const offset { plan( q ) - plan( p ) };
|
if( std::abs( p.y - q.y ) > 0.5 ) {
|
||||||
s += cross( offset, plan( tq ) ) / d;
|
continue;
|
||||||
t += cross( offset, plan( tp ) ) / d;
|
}
|
||||||
|
if( ( s < 0.5 || s > length - 0.5 ) && ( t < 0.5 || t > otherlength - 0.5 ) && joined( *this, *other ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto const tangent { glm::normalize( plan( tp ) ) };
|
||||||
|
auto const othertangent { glm::normalize( plan( tq ) ) };
|
||||||
|
auto const angle { std::acos( std::min( 1.0, std::abs( glm::dot( tangent, othertangent ) ) ) ) };
|
||||||
|
if( angle < 0.03 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto const sidevalue { side ? 1 : -1 };
|
||||||
|
if( std::any_of( result.begin(), result.end(), [&]( rail_crossing const &Crossing ) {
|
||||||
|
return Crossing.path == path && Crossing.side == sidevalue && std::abs( Crossing.at - s ) < 0.05; } ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto const normal { glm::normalize( plan( line.normal( s, sidevalue ) ) ) };
|
||||||
|
auto const othernormal { glm::normalize( plan( theirs.normal( t, otherside ? 1 : -1 ) ) ) };
|
||||||
|
rail_crossing crossing;
|
||||||
|
crossing.track = other;
|
||||||
|
crossing.path = path;
|
||||||
|
crossing.side = sidevalue;
|
||||||
|
crossing.at = s;
|
||||||
|
crossing.angle = angle;
|
||||||
|
crossing.into = glm::dot( tangent, othernormal );
|
||||||
|
crossing.facing = glm::dot( normal, othernormal );
|
||||||
|
auto const ourbend { bend( line, s ) };
|
||||||
|
auto const theirbend { bend( theirs, t ) };
|
||||||
|
crossing.nose = ( std::abs( ourbend - theirbend ) > 1e-4 ? ourbend < theirbend : heading( tangent ) < heading( othertangent ) );
|
||||||
|
crossing.otherpath = otherpath;
|
||||||
|
crossing.otherside = ( otherside ? 1 : -1 );
|
||||||
|
crossing.otherat = t;
|
||||||
|
crossing.aligned = glm::dot( tangent, othertangent ) > 0.0;
|
||||||
|
result.push_back( crossing );
|
||||||
}
|
}
|
||||||
line.at( s, p, tp );
|
|
||||||
theirs.at( t, q, tq );
|
|
||||||
if( glm::length( plan( p ) - plan( q ) ) > 0.01
|
|
||||||
|| s < 0.0 || s > length
|
|
||||||
|| t < otherfrom || t > otherlength ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if( std::abs( p.y - q.y ) > 0.5 ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if( ( s < 0.5 || s > length - 0.5 ) && ( t < 0.5 || t > otherlength - 0.5 ) && joined( *this, *other ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto const tangent { glm::normalize( plan( tp ) ) };
|
|
||||||
auto const othertangent { glm::normalize( plan( tq ) ) };
|
|
||||||
auto const angle { std::acos( std::min( 1.0, std::abs( glm::dot( tangent, othertangent ) ) ) ) };
|
|
||||||
if( angle < 0.03 ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto const sidevalue { side ? 1 : -1 };
|
|
||||||
if( std::any_of( result.begin(), result.end(), [&]( rail_crossing const &Crossing ) {
|
|
||||||
return Crossing.path == path && Crossing.side == sidevalue && std::abs( Crossing.at - s ) < 0.05; } ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto const normal { glm::normalize( plan( line.normal( s, sidevalue ) ) ) };
|
|
||||||
auto const othernormal { glm::normalize( plan( theirs.normal( t, otherside ? 1 : -1 ) ) ) };
|
|
||||||
rail_crossing crossing;
|
|
||||||
crossing.track = other;
|
|
||||||
crossing.path = path;
|
|
||||||
crossing.side = sidevalue;
|
|
||||||
crossing.at = s;
|
|
||||||
crossing.angle = angle;
|
|
||||||
crossing.into = glm::dot( tangent, othernormal );
|
|
||||||
crossing.facing = glm::dot( normal, othernormal );
|
|
||||||
auto const ourbend { bend( line, s ) };
|
|
||||||
auto const theirbend { bend( theirs, t ) };
|
|
||||||
crossing.nose = ( std::abs( ourbend - theirbend ) > 1e-4 ? ourbend < theirbend : heading( tangent ) < heading( othertangent ) );
|
|
||||||
crossing.otherpath = otherpath;
|
|
||||||
crossing.otherside = ( otherside ? 1 : -1 );
|
|
||||||
crossing.otherat = t;
|
|
||||||
crossing.aligned = glm::dot( tangent, othertangent ) > 0.0;
|
|
||||||
result.push_back( crossing );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
memo.own = result;
|
||||||
}
|
}
|
||||||
if( false == Joined ) {
|
if( false == Joined ) {
|
||||||
return result;
|
return result;
|
||||||
@@ -513,6 +563,7 @@ std::vector<TTrack::rail_crossing> TTrack::rail_crossings( bool const Joined ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
memo.joined = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,7 +804,7 @@ glm::dvec2 plan( glm::dvec3 const &V ) {
|
|||||||
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 ) {
|
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 ) {
|
||||||
|
|
||||||
std::vector<glm::dvec2> knots;
|
std::vector<glm::dvec2> knots;
|
||||||
auto const partnerchecks { &Partner == &Track ? Checks : Partner.check_rails( Partner.rail_crossings() ) };
|
auto const partnerchecks { &Partner == &Track ? Checks : rail_checks( Partner ) };
|
||||||
auto const wingend { Partnerat + Partnerdirection * wing_reach( Slope ) };
|
auto const wingend { Partnerat + Partnerdirection * wing_reach( Slope ) };
|
||||||
auto farend { 0.0 };
|
auto farend { 0.0 };
|
||||||
if( false == replaced_check( partnerchecks[ Partnerpath ][ Partnerside > 0 ], wingend, Partnerdirection, farend ) ) {
|
if( false == replaced_check( partnerchecks[ Partnerpath ][ Partnerside > 0 ], wingend, Partnerdirection, farend ) ) {
|
||||||
@@ -882,7 +933,7 @@ TTrack::rail_layout TTrack::plan_rails( bool const Crossings ) {
|
|||||||
if( Crossings ) {
|
if( Crossings ) {
|
||||||
crossings = rail_crossings();
|
crossings = rail_crossings();
|
||||||
}
|
}
|
||||||
layout.checks = check_rails( crossings );
|
layout.checks = ( Crossings ? rail_checks( *this ) : check_rails( crossings ) );
|
||||||
auto const &checks { layout.checks };
|
auto const &checks { layout.checks };
|
||||||
auto &plans { layout.plans };
|
auto &plans { layout.plans };
|
||||||
auto &guards { layout.guards };
|
auto &guards { layout.guards };
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ double constexpr nose_tip { 0.012 };
|
|||||||
double constexpr middle_angle { 0.35 };
|
double constexpr middle_angle { 0.35 };
|
||||||
double constexpr wide_angle { 0.785 };
|
double constexpr wide_angle { 0.785 };
|
||||||
|
|
||||||
|
void forget();
|
||||||
// how far a wing rail reaches past the crossing point of the rails
|
// how far a wing rail reaches past the crossing point of the rails
|
||||||
double wing_reach( double const Slope );
|
double wing_reach( double const Slope );
|
||||||
double check_length( double const Slope );
|
double check_length( double const Slope );
|
||||||
|
|||||||
Reference in New Issue
Block a user