mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 03:59:19 +02:00
73 lines
2.5 KiB
C++
73 lines
2.5 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "world/Segment.h"
|
|
|
|
namespace track_rails {
|
|
|
|
inline glm::dvec2 plan( glm::dvec3 const &V ) {
|
|
|
|
return glm::dvec2{ V.x, V.z };
|
|
}
|
|
|
|
inline double cross( glm::dvec2 const &A, glm::dvec2 const &B ) {
|
|
|
|
return A.x * B.y - A.y * B.x;
|
|
}
|
|
|
|
inline 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 };
|
|
double offset { 0.0 }; // across the path, to the running edge
|
|
double from { 0.0 };
|
|
std::vector<glm::dvec3> points;
|
|
std::vector<double> distances;
|
|
glm::dvec2 low { 0.0 };
|
|
glm::dvec2 high { 0.0 };
|
|
|
|
void at( double const Distance, glm::dvec3 &Point, glm::dvec3 &Tangent ) const {
|
|
auto const length { segment->GetLength() };
|
|
auto const local = [&]( double const D ) {
|
|
glm::dvec3 point, across;
|
|
segment->plan_frame( D, point, across );
|
|
return point + across * offset; };
|
|
auto const inside { std::clamp( Distance, 0.0, length ) };
|
|
auto const delta { std::min( 0.05, 0.5 * length ) };
|
|
auto const a { std::max( inside - delta, 0.0 ) };
|
|
auto const b { std::min( inside + delta, length ) };
|
|
Tangent = local( b ) - local( a );
|
|
Tangent = ( glm::length2( Tangent ) > 0.0 ? glm::normalize( Tangent ) : glm::dvec3{ 1.0, 0.0, 0.0 } );
|
|
Point = local( inside ) + Tangent * ( Distance - inside );
|
|
}
|
|
glm::dvec3 normal( double const Distance, int const Side ) const {
|
|
glm::dvec3 point, across;
|
|
segment->plan_frame( std::clamp( Distance, 0.0, segment->GetLength() ), point, across );
|
|
return across * static_cast<double>( -Side );
|
|
}
|
|
};
|
|
|
|
gauge_line make_gauge_line( TSegment const &Segment, double const Offset, double const From );
|
|
double lateral( gauge_line const &Line, int const Side, glm::dvec3 const &Point, double &Distance );
|
|
double nearest_distance( gauge_line const &Line, glm::dvec3 const &Point );
|
|
|
|
} // namespace track_rails
|