mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 22:54:54 +01:00
feat(rails): the wing rails of the low section drawn of its profile, Zu1-60 (60E1A1), not the plain one shortened: below the head the web thickened to 44 mm, the foot 55 mm inwards and 85 mm outwards of the middle, the edges of the foot and the root of the web higher, of the measures of the profile drawn, made over as far as the foot is raised along the forged ends; the end faces of the rails of the same
This commit is contained in:
@@ -1281,6 +1281,7 @@ loft_span TTrack::rail_layer::span( rail_piece const &Piece, piece_ends const &E
|
||||
result.rises = Piece.rises;
|
||||
if( false == Piece.rises.empty() ) {
|
||||
result.head = { m_drawing.size.neck, m_drawing.size.crest };
|
||||
result.low = { m_rise, low_web, low_inward, low_outward, low_edge, low_root };
|
||||
}
|
||||
if( std::abs( Piece.from - Ends.from ) < 1e-6 ) {
|
||||
result.fromend = Ends.fromend;
|
||||
|
||||
@@ -52,6 +52,13 @@ double constexpr blade_spacing { 0.5 };
|
||||
double constexpr blade_runon_margin { 0.2 }; // how far short of the end of the plain track a blade running on into it ends
|
||||
double constexpr wing_low { 1.5 }; // how far before the throat the wing rails are of the low section of the blades, raised on their timbers as the blades
|
||||
double constexpr wing_forged { 0.5 }; // how long the end of a wing rail forged to the plain rail is, going down to it
|
||||
// the low section of the blades, Zu1-60 (60E1A1) against 60E1: its web 44 mm thick against 16.5, its foot 55 mm inwards and 85 mm outwards
|
||||
// of the middle against 75 both ways, the edges of its foot 20 mm high against 11.5, its web from 36 mm up against 30.6
|
||||
double constexpr low_web { 44.0 / 16.5 };
|
||||
double constexpr low_inward { 55.0 / 75.0 };
|
||||
double constexpr low_outward { 85.0 / 75.0 };
|
||||
double constexpr low_edge { 20.0 / 11.5 };
|
||||
double constexpr low_root { 36.0 / 30.6 };
|
||||
|
||||
// where the inner rails of the two paths of a switch cross, found from their gauge lines behind the blades
|
||||
struct switch_frog {
|
||||
|
||||
@@ -764,6 +764,87 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
|
||||
return Height;
|
||||
}
|
||||
return static_cast<float>( Height + Rise * ( Span.head.x - Height ) / ( Span.head.x - bottom ) ); };
|
||||
// the profile below its head as drawn, about the middle of its foot: how far the foot reaches inwards and outwards, how thick the web
|
||||
// is, how wide the head, where its underside is, how high the top of the edges of the foot and the root of the web are
|
||||
struct {
|
||||
double middle { 0.0 }, inward { 0.0 }, outward { 0.0 }, web { 1e6 }, head { 0.0 }, underside { 1e6 }, edge { 0.0 }, root { 1e6 };
|
||||
} drawn;
|
||||
auto const across = [&]( gfx::basic_vertex const &Point ) {
|
||||
return static_cast<double>( Span.side * Point.position.x - Span.halfwidth ); };
|
||||
auto low { Span.low.full > 0.0 && Span.head.x > bottom };
|
||||
if( low ) {
|
||||
glm::dvec2 foot { 1e6, -1e6 };
|
||||
for( auto const &point : ShapePoints ) {
|
||||
if( point.position.y < bottom + 0.0005f ) {
|
||||
foot = { std::min( foot.x, across( point ) ), std::max( foot.y, across( point ) ) };
|
||||
}
|
||||
}
|
||||
drawn.middle = 0.5 * ( foot.x + foot.y );
|
||||
drawn.inward = drawn.middle - foot.x;
|
||||
drawn.outward = foot.y - drawn.middle;
|
||||
for( auto const &point : ShapePoints ) {
|
||||
auto const off { std::abs( across( point ) - drawn.middle ) };
|
||||
if( point.position.y >= Span.head.x ) {
|
||||
drawn.head = std::max( drawn.head, off );
|
||||
}
|
||||
else if( point.position.y > bottom + 0.25 * ( Span.head.x - bottom ) ) {
|
||||
drawn.web = std::min( drawn.web, off );
|
||||
}
|
||||
}
|
||||
for( auto const &point : ShapePoints ) {
|
||||
auto const off { std::abs( across( point ) - drawn.middle ) };
|
||||
auto const height { static_cast<double>( point.position.y - bottom ) };
|
||||
if( point.position.y >= Span.head.x && off >= drawn.head - 0.001 ) {
|
||||
drawn.underside = std::min( drawn.underside, static_cast<double>( point.position.y ) );
|
||||
}
|
||||
if( point.position.y < Span.head.x && off <= drawn.web + 0.0005 ) {
|
||||
drawn.root = std::min( drawn.root, height );
|
||||
}
|
||||
if( off >= 0.9 * std::min( drawn.inward, drawn.outward ) ) {
|
||||
drawn.edge = std::max( drawn.edge, height );
|
||||
}
|
||||
}
|
||||
low = ( drawn.web < std::min( drawn.inward, drawn.outward ) && drawn.web < drawn.head && drawn.edge > 0.0 && drawn.edge < drawn.root && drawn.root < Span.head.x - bottom && drawn.underside < 1e6 );
|
||||
}
|
||||
// the profile made over into the low section with its foot raised by Rise, by as much of it as the rise is of the full one: below the
|
||||
// head the web thickened, the foot reshaped, the web shortened
|
||||
std::vector<gfx::basic_vertex> lowpoints;
|
||||
auto const lowered = [&]( double const Rise ) -> gfx::vertex_array const & {
|
||||
auto const share { std::clamp( Rise / Span.low.full, 0.0, 1.0 ) };
|
||||
auto const web { drawn.web * glm::mix( 1.0, Span.low.web, share ) };
|
||||
auto const inward { drawn.inward * glm::mix( 1.0, Span.low.inward, share ) };
|
||||
auto const outward { drawn.outward * glm::mix( 1.0, Span.low.outward, share ) };
|
||||
auto const edge { drawn.edge * glm::mix( 1.0, Span.low.edge, share ) };
|
||||
auto const root { drawn.root * glm::mix( 1.0, Span.low.root, share ) };
|
||||
auto const below { Span.head.x - bottom };
|
||||
auto const top { std::max( below - Rise, root + 0.001 ) };
|
||||
lowpoints = ShapePoints;
|
||||
for( auto &point : lowpoints ) {
|
||||
if( point.position.y >= drawn.underside ) {
|
||||
continue;
|
||||
}
|
||||
auto const off { across( point ) - drawn.middle };
|
||||
auto const distance { std::abs( off ) };
|
||||
auto moved { distance };
|
||||
if( point.position.y >= Span.head.x ) {
|
||||
moved = web + ( std::max( distance, drawn.web ) - drawn.web ) * ( drawn.head - web ) / std::max( drawn.head - drawn.web, 1e-6 );
|
||||
}
|
||||
else {
|
||||
auto const was { off < 0.0 ? drawn.inward : drawn.outward };
|
||||
auto const reach { off < 0.0 ? inward : outward };
|
||||
moved = ( distance <= drawn.web ?
|
||||
distance * web / drawn.web :
|
||||
web + ( distance - drawn.web ) * ( reach - web ) / std::max( was - drawn.web, 1e-6 ) );
|
||||
auto const height { static_cast<double>( point.position.y - bottom ) };
|
||||
auto const made {
|
||||
height <= drawn.edge ? height * edge / drawn.edge :
|
||||
height <= drawn.root ? edge + ( height - drawn.edge ) * ( root - edge ) / ( drawn.root - drawn.edge ) :
|
||||
root + ( height - drawn.root ) * ( top - root ) / ( below - drawn.root ) };
|
||||
point.position.y = static_cast<float>( bottom + below - top + made );
|
||||
}
|
||||
point.position.x = static_cast<float>( Span.side * ( Span.halfwidth + drawn.middle + std::copysign( moved, off ) ) );
|
||||
}
|
||||
return lowpoints; };
|
||||
|
||||
auto const ring = [&]( double const Distance, double const Middle, std::vector<gfx::basic_vertex> &Ring, std::vector<float> &Wear ) {
|
||||
glm::dvec3 point;
|
||||
@@ -797,7 +878,9 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
|
||||
}
|
||||
auto const worn { knots::sample( Span.ramp, Distance, -1e6 ) };
|
||||
auto const drop { knots::sample( Span.drops, Distance, 0.0 ) };
|
||||
auto const rise { Span.rises.empty() ? Span.rise : knots::sample( Span.rises, Distance, 0.0 ) };
|
||||
auto const sampled { Span.rises.empty() ? Span.rise : knots::sample( Span.rises, Distance, 0.0 ) };
|
||||
auto const &points { low && sampled > 0.0 ? lowered( sampled ) : ShapePoints };
|
||||
auto const rise { low ? 0.0 : sampled };
|
||||
static loft_end const unshaped;
|
||||
auto const &shaped { Distance <= Span.from ? Span.fromend : Distance >= Span.to ? Span.toend : unshaped };
|
||||
auto const bend { shaped.bend };
|
||||
@@ -813,11 +896,11 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
|
||||
}
|
||||
Ring.clear();
|
||||
Wear.clear();
|
||||
auto const count { ShapePoints.size() };
|
||||
auto const count { points.size() };
|
||||
auto const reach = [&]( std::size_t const Index ) {
|
||||
return static_cast<double>( Span.side * ShapePoints[ Index ].position.x - Span.halfwidth ); };
|
||||
return static_cast<double>( Span.side * points[ Index ].position.x - Span.halfwidth ); };
|
||||
auto const twin = [&]( std::size_t const A, std::size_t const B ) {
|
||||
return ShapePoints[ A ].position.x == ShapePoints[ B ].position.x && ShapePoints[ A ].position.y == ShapePoints[ B ].position.y; };
|
||||
return points[ A ].position.x == points[ B ].position.x && points[ A ].position.y == points[ B ].position.y; };
|
||||
auto const clamped = [&]( std::size_t const Index ) {
|
||||
auto const outside { reach( Index ) };
|
||||
return ( outside > middleextent ? 1 : outside < middleinner ? -1 : 0 ); };
|
||||
@@ -831,15 +914,15 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
|
||||
// nothing of the profile between the limits there: the ring shrinks to one point, the step draws nothing
|
||||
auto const outside { std::clamp( 0.5 * ( std::min( extent, farthest ) + std::max( innerextent, nearest ) ), nearest, farthest ) };
|
||||
auto pt { parallel * static_cast<float>( Span.side * ( Span.halfwidth + outside + offset ) ) + position };
|
||||
pt.y += raised( ShapePoints.front().position.y, rise ) + Span.lift;
|
||||
pt.y += raised( points.front().position.y, rise ) + Span.lift;
|
||||
for( std::size_t j = 0; j < count; ++j ) {
|
||||
Ring.emplace_back( pt, glm::vec3{ 0.f, 1.f, 0.f }, glm::vec2{ ShapePoints[ j ].texture.x, 0.f } );
|
||||
Ring.emplace_back( pt, glm::vec3{ 0.f, 1.f, 0.f }, glm::vec2{ points[ j ].texture.x, 0.f } );
|
||||
Wear.push_back( 1.f );
|
||||
}
|
||||
return;
|
||||
}
|
||||
for( std::size_t j = 0; j < count; ++j ) {
|
||||
auto shape { ShapePoints[ j ] };
|
||||
auto shape { points[ j ] };
|
||||
auto outside { reach( j ) };
|
||||
auto wall { glm::vec3{ 0.f } };
|
||||
auto const side { clamped( j ) };
|
||||
@@ -866,7 +949,7 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
|
||||
if( false == open( neighbour ) ) {
|
||||
continue;
|
||||
}
|
||||
auto const &other { ShapePoints[ neighbour ] };
|
||||
auto const &other { points[ neighbour ] };
|
||||
auto const t { std::clamp( static_cast<float>( ( limit - reach( neighbour ) ) / ( side > 0 ? std::max( outside - reach( neighbour ), 1e-6 ) : std::min( outside - reach( neighbour ), -1e-6 ) ) ), 0.f, 1.f ) };
|
||||
shape.position.y = glm::mix( other.position.y, shape.position.y, t );
|
||||
shape.texture.x = glm::mix( other.texture.x, shape.texture.x, t );
|
||||
@@ -889,7 +972,7 @@ bool TSegment::RenderLoftSpan( gfx::vertex_array &Output, glm::dvec3 const &Orig
|
||||
continue;
|
||||
}
|
||||
auto const t { static_cast<float>( ( limit - reach( static_cast<std::size_t>( neighbour ) ) ) / ( reach( static_cast<std::size_t>( index ) ) - reach( static_cast<std::size_t>( neighbour ) ) ) ) };
|
||||
auto const height { glm::mix( ShapePoints[ neighbour ].position.y, ShapePoints[ index ].position.y, t ) };
|
||||
auto const height { glm::mix( points[ neighbour ].position.y, points[ index ].position.y, t ) };
|
||||
top = std::max( top, height );
|
||||
bottom = std::min( bottom, height );
|
||||
++ends;
|
||||
|
||||
@@ -28,6 +28,17 @@ struct loft_end {
|
||||
double bend { 0.0 };
|
||||
};
|
||||
|
||||
// a rail profile made over below its head into a lower section, as the wing rails of a frog of the section of the blades: its web, its
|
||||
// foot inwards and outwards as many times as thick and wide, the top of the edges of its foot and the root of its web as many times as high
|
||||
struct loft_low {
|
||||
double full { 0.0 }; // the rise of the foot the profile is the whole low section at; none where it's 0
|
||||
double web { 1.0 };
|
||||
double inward { 1.0 };
|
||||
double outward { 1.0 };
|
||||
double edge { 1.0 };
|
||||
double root { 1.0 };
|
||||
};
|
||||
|
||||
struct loft_span {
|
||||
int side { 1 };
|
||||
float halfwidth { 0.f };
|
||||
@@ -49,6 +60,7 @@ struct loft_span {
|
||||
glm::dvec2 head { 0.0 };
|
||||
double rise { 0.0 }; // how far the foot of the profile is raised, the web below the head (head.x) shortened by as much
|
||||
knots::line rises; // along the span, in place of rise where given
|
||||
loft_low low; // what the profile is made over into as its foot is raised
|
||||
};
|
||||
|
||||
struct segment_data {
|
||||
|
||||
Reference in New Issue
Block a user