diff --git a/world/RailLayer.cpp b/world/RailLayer.cpp index 9c3f2bbb..4d6b07ed 100644 --- a/world/RailLayer.cpp +++ b/world/RailLayer.cpp @@ -568,11 +568,9 @@ void TTrack::rail_layer::lay_guards() { sort_cuts( cuts ); auto start { guard.from }; auto startmiter { guard.frommiter }; - rail_cut startcut; for( std::size_t i = 0; i <= cuts.size(); ++i ) { auto const end { i < cuts.size() ? cuts[ i ].end : guard.to }; auto const endmiter { i < cuts.size() ? cuts[ i ].endmiter : guard.tomiter }; - auto const endcut { i < cuts.size() ? cuts[ i ] : rail_cut {} }; auto const a { std::max( { mitered( startmiter, start, false ), m_from, 0.0 } ) }; auto const b { std::min( { mitered( endmiter, end, true ), m_length, mitered( guard.tomiter, guard.to, true ) } ) }; if( b - a > 0.01 ) { @@ -583,17 +581,14 @@ void TTrack::rail_layer::lay_guards() { ( ending == ( miter.y < 0.0 ) ? uppers : lowers ).emplace_back( 1.0 / miter.y, -miter.x / miter.y - m_guardoffset ); } } - auto const glued { a == start && false == startcut.startfit.empty() }; - auto const gluedend { b == end && false == endcut.endfit.empty() }; piece( m_profile, - { .from = a, .to = b, .offsets = offsets, .extents = envelope( uppers, true, a, b ), .inner = envelope( lowers, false, a, b ), .capfrom = false == glued, .capto = false == gluedend, .rolled = false }, - { a, b, { glued ? startcut.startbend : 0.0, glued ? startcut.startfit : knots::line {} }, { gluedend ? endcut.endbend : 0.0, gluedend ? endcut.endfit : knots::line {} } } ); + { .from = a, .to = b, .offsets = offsets, .extents = envelope( uppers, true, a, b ), .inner = envelope( lowers, false, a, b ), .capfrom = true, .capto = true, .rolled = false }, + { a, b, {}, {} } ); } if( i < cuts.size() && cuts[ i ].start > start ) { start = cuts[ i ].start; startmiter = cuts[ i ].startmiter; - startcut = cuts[ i ]; } } } @@ -639,7 +634,6 @@ void TTrack::rail_layer::lay_cuts( gfx::vertex_array const &Shape, std::vector m_from ? startbend : 0.0, start > m_from ? startfit : knots::line {} }, - { end < m_length ? Cuts[ i ].endbend : 0.0, end < m_length ? Cuts[ i ].endfit : knots::line {} } }; + { start > m_from ? startbend : 0.0 }, + { end < m_length ? Cuts[ i ].endbend : 0.0 } }; if( b - a > 0.01 ) { std::vector active; for( auto const &tread : Treads ) { @@ -714,7 +708,6 @@ void TTrack::rail_layer::lay_cuts( gfx::vertex_array const &Shape, std::vector 0.0 ? Cut.from - 0.005 : Cut.to + 0.005 ) / into, facing / into }; cut.startmiter = { at + ( into > 0.0 ? Cut.to + 0.005 : Cut.from - 0.005 ) / into, facing / into }; - auto const glue = [&]( knots::line const &Line, double const Edge, double &Position, glm::dvec2 &Miter, double &Bend, knots::line &Fit, bool &Cap ) { - if( Line.empty() ) { - return; - } - Position = at + Edge / into; - Miter = {}; - Bend = facing / into; - for( auto const &knot : Line ) { - Fit.emplace_back( knot.x, ( knot.y - Edge ) / into ); - } - Cap = false; }; - glue( into > 0.0 ? Cut.fromline : Cut.toline, into > 0.0 ? Cut.from : Cut.to, cut.end, cut.endmiter, cut.endbend, cut.endfit, cut.endcap ); - glue( into > 0.0 ? Cut.toline : Cut.fromline, into > 0.0 ? Cut.to : Cut.from, cut.start, cut.startmiter, cut.startbend, cut.startfit, cut.startcap ); Plan.cuts.push_back( cut ); } -std::vector glue_line( std::vector const &Outline, double const Base ) { +track_rails::rail_cut corner_cut( track_rails::rail_crossing const &Crossing, double const Face, double const Toward, double const Head, double const Other ) { - std::vector line; - for( auto const &knot : Outline ) { - line.emplace_back( knot.x, Base - knot.y ); - } - return line; + auto const mitre = [&]( double const Edge, double const Flange ) { + auto const slope { Flange * Other / ( Toward * Head ) }; + return glm::dvec2 { Crossing.at + ( Edge - Face * slope ) / Crossing.into, ( slope + Crossing.facing ) / Crossing.into }; }; + auto const rail { mitre( 0.0, 1.0 ) }; + auto const guard { mitre( flangeway, -1.0 ) }; + auto const rising { Crossing.into > 0.0 }; + track_rails::rail_cut cut; + cut.at = Crossing.at; + cut.endmiter = ( rising ? rail : guard ); + cut.startmiter = ( rising ? guard : rail ); + cut.end = cut.endmiter.x + cut.endmiter.y * Face; + cut.start = cut.startmiter.x + cut.startmiter.y * Face; + cut.endbend = cut.endmiter.y; + cut.startbend = cut.startmiter.y; + return cut; } track_rails::rail_fill guard_fill( track_rails::guard_rail const &Guard, track_rails::rail_size const &Size ) { @@ -443,15 +438,12 @@ void TTrack::rail_planner::cross_grooved( rail_crossing const &Crossing, rail_si void TTrack::rail_planner::cross_wide( rail_crossing const &Crossing, rail_size const &Other ) { - auto const through { goes_through( m_track, *Crossing.track ) }; - wide( plan_of( Crossing ), Crossing, { through ? 0.0 : -Other.head, flangeway, 0.0, m_size.head, through ? knots::line {} : glue_line( Other.field, 0.0 ) } ); - if( through ) { - add_tread( Crossing.path, Crossing.side, shared_span( Crossing, Other ), *Crossing.track, Crossing.otherpath ); - } + plan_of( Crossing ).cuts.push_back( corner_cut( Crossing, 0.0, -1.0, m_size.head, Other.head ) ); + add_tread( Crossing.path, Crossing.side, shared_span( Crossing, Other ), *Crossing.track, Crossing.otherpath ); auto const reach { ( flangeway + m_size.head + guard_reach ) / std::abs( Crossing.into ) }; track_rails::guard_rail guard { Crossing.at - reach, Crossing.at + reach }; - guard.through = through; - wide( guard.plan, Crossing, { -Other.head, through ? flangeway : flangeway + Other.head, m_guardoffset, m_guardoffset + m_size.head, glue_line( Other.field, 0.0 ), through ? knots::line {} : glue_line( Other.gauge, flangeway + Other.head ) } ); + guard.through = goes_through( m_track, *Crossing.track ); + guard.plan.cuts.push_back( corner_cut( Crossing, -flangeway, 1.0, m_size.head, Other.head ) ); merge_guard( m_layout.guards[ Crossing.path ][ Crossing.side > 0 ], guard ); } diff --git a/world/RailProfile.cpp b/world/RailProfile.cpp index c3a01cfd..e8d5b244 100644 --- a/world/RailProfile.cpp +++ b/world/RailProfile.cpp @@ -33,36 +33,6 @@ rail_size measure_rail( gfx::vertex_array const &Profile ) { } 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 ); - } - } - knots::line 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 ) { - knots::sort( side ); - } - auto const mean = []( knots::line const &Side ) { - auto sum { 0.0 }; - for( auto const &knot : Side ) { - sum += knot.y; - } - return sum / std::max( 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 }; diff --git a/world/Segment.cpp b/world/Segment.cpp index d52113c7..c5389f13 100644 --- a/world/Segment.cpp +++ b/world/Segment.cpp @@ -616,23 +616,13 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig } std::sort( stations.begin(), stations.end() ); stations.erase( std::unique( stations.begin(), stations.end(), []( double const A, double const B ) { return B - A < 0.001; } ), stations.end() ); - if( Span.fromend.bend != 0.0 || Span.toend.bend != 0.0 || false == Span.fromend.fit.empty() || false == Span.toend.fit.empty() ) { + if( Span.fromend.bend != 0.0 || Span.toend.bend != 0.0 ) { auto widest { 0.0 }; for( auto const &point : ShapePoints ) { widest = std::max( widest, std::abs( static_cast( Span.side * point.position.x - Span.halfwidth ) ) ); } - auto offsetmost { 0.0 }; - for( auto const &knot : Span.offsets ) { - offsetmost = std::max( offsetmost, std::abs( knot.y ) ); - } - auto const margin = [&]( loft_end const &End ) { - auto fitmost { 0.0 }; - for( auto const &knot : End.fit ) { - fitmost = std::max( fitmost, std::abs( knot.y ) ); - } - return std::abs( End.bend ) * ( End.fit.empty() ? widest : widest + offsetmost ) + fitmost + 0.001; }; - auto const frommargin { margin( Span.fromend ) }; - auto const tomargin { margin( Span.toend ) }; + auto const frommargin { std::abs( Span.fromend.bend ) * widest + 0.001 }; + auto const tomargin { std::abs( Span.toend.bend ) * widest + 0.001 }; stations.erase( std::remove_if( stations.begin(), stations.end(), [&]( double const Distance ) { return ( Distance > Span.from && Distance < Span.to ) && ( Distance < Span.from + frommargin || Distance > Span.to - tomargin ); } ), stations.end() ); @@ -671,17 +661,14 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig static loft_end const unshaped; auto const &shaped { Distance <= Span.from ? Span.fromend : Distance >= Span.to ? Span.toend : unshaped }; auto const bend { shaped.bend }; - auto const &fit { shaped.fit }; auto along { glm::vec3 { 0.f } }; - auto forward { glm::vec3 { 0.f } }; - if( bend != 0.0 || false == fit.empty() ) { + if( bend != 0.0 ) { glm::dvec3 ahead, behind, unused; plan_frame( std::min( Distance + 0.001, static_cast( fLength ) ), ahead, unused ); plan_frame( std::max( Distance - 0.001, 0.0 ), behind, unused ); auto const tangent { glm::dvec3 { ahead.x - behind.x, 0.0, ahead.z - behind.z } }; if( glm::length2( tangent ) > 0.0 ) { - forward = glm::vec3 { glm::normalize( tangent ) }; - along = forward * static_cast( bend ); + along = glm::vec3 { glm::normalize( tangent ) } * static_cast( bend ); } } Ring.clear(); @@ -763,7 +750,7 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig wall = ( side > 0 ? outerwall : innerwall ); } } - auto pt { parallel * static_cast( Span.side * ( Span.halfwidth + outside + offset ) ) + position + along * static_cast( outside + offset ) + forward * static_cast( knots::sample( fit, shape.position.y, 0.0 ) ) }; + auto pt { parallel * static_cast( Span.side * ( Span.halfwidth + outside + offset ) ) + position + along * static_cast( outside + offset ) }; pt.y += shape.position.y + Span.lift; auto norm { shape.normal.x * parallel }; norm.y += shape.normal.y; diff --git a/world/Segment.h b/world/Segment.h index 971794c3..afe0953c 100644 --- a/world/Segment.h +++ b/world/Segment.h @@ -24,7 +24,6 @@ struct map_colored_paths { struct loft_end { double bend { 0.0 }; - knots::line fit; }; struct loft_span {