mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 21:44:53 +01:00
A track laid on from a free end in the PKP PLK laying, by a drag out of the end, by clicks from it or laid back onto it, starts from the curvature and the cant the end has. An arc turning the same way as the end is a compound curve: a transition of the norms ramps the curvature and the cant from the one arc into the other. From a straight the arc gets its entry transition, the arc then straight its exit one. Where the way is too short the transitions are cut and the cant lowered to what they ramp, and the readout says so; with no room at all the track is laid as before and the note says why. The curves traced on the orthophoto and the recommended values of a compound curve get the transitions between their arcs too. The free laying stays as it was.
314 lines
8.2 KiB
C++
314 lines
8.2 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:
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <glm/glm.hpp>
|
|
|
|
#include "world/Segment.h"
|
|
|
|
namespace alignment
|
|
{
|
|
|
|
enum class transition_shape
|
|
{
|
|
cubic_parabola,
|
|
clothoid
|
|
};
|
|
|
|
struct limits
|
|
{
|
|
double gauge{1500.0};
|
|
double unbalanced{0.6};
|
|
double cant_max{150.0};
|
|
double cant_rate{35.0};
|
|
double ramp_factor{10.0};
|
|
double jerk{0.3};
|
|
double vertical_factor{0.4};
|
|
double vertical_min{2000.0};
|
|
double tangent_min_time{0.0};
|
|
double arc_min{20.0};
|
|
double arc_min_factor{0.4};
|
|
bool checked{true};
|
|
|
|
bool operator==(limits const &) const = default;
|
|
};
|
|
|
|
struct compound_arc
|
|
{
|
|
double radius{600.0};
|
|
double transition{0.0};
|
|
double share{1.0};
|
|
};
|
|
|
|
struct vertex
|
|
{
|
|
glm::dvec2 position{0.0};
|
|
double offset{100.0};
|
|
double radius{1000.0};
|
|
double transition_in{0.0};
|
|
double transition_out{0.0};
|
|
double cant{0.0};
|
|
bool reverse_turn{false};
|
|
bool compound{false};
|
|
double share{1.0};
|
|
std::vector<compound_arc> arcs;
|
|
};
|
|
|
|
struct design
|
|
{
|
|
glm::dvec3 start{0.0};
|
|
glm::dvec3 end{0.0};
|
|
glm::dvec2 start_direction{0.0, 1.0};
|
|
glm::dvec2 end_direction{0.0, 1.0};
|
|
double start_grade{0.0};
|
|
double end_grade{0.0};
|
|
double start_radius{0.0};
|
|
double end_radius{0.0};
|
|
// length of the straight beyond the start and the end, which the curves can take over
|
|
double start_reserve{0.0};
|
|
double end_reserve{0.0};
|
|
std::vector<vertex> vertices;
|
|
transition_shape shape{transition_shape::cubic_parabola};
|
|
double speed{100.0};
|
|
int transition_pieces{1};
|
|
double arc_piece_angle{10.0};
|
|
limits norms;
|
|
};
|
|
|
|
struct recommendation
|
|
{
|
|
double cant_equilibrium{0.0};
|
|
double cant_min{0.0};
|
|
double cant{0.0};
|
|
double radius_min{0.0};
|
|
double transition{0.0};
|
|
};
|
|
recommendation recommend(double const Speed, double const Radius, limits const &Limits);
|
|
double transition_length(double const Speed, double const Radius, double const Cant, limits const &Limits);
|
|
// the transition curve from the curvature and the cant of one arc to those of the next one, 0 for a straight; the curvature positive
|
|
// turning one way, the cant with the same sign as the curvature it leans into
|
|
double transition_between(double const Speed, double const Curvature0, double const Cant0, double const Curvature1, double const Cant1, limits const &Limits);
|
|
double unbalanced_acceleration(double const Speed, double const Radius, double const Cant, limits const &Limits);
|
|
|
|
enum class element_kind
|
|
{
|
|
straight,
|
|
transition_in,
|
|
arc,
|
|
transition_out,
|
|
spiral
|
|
};
|
|
|
|
struct element
|
|
{
|
|
element_kind kind{element_kind::straight};
|
|
int vertex{-1};
|
|
double chainage{0.0};
|
|
double length{0.0};
|
|
double radius{0.0};
|
|
double transition{0.0};
|
|
int turn{0};
|
|
double cant{0.0};
|
|
double curvature_start{0.0};
|
|
double curvature_end{0.0};
|
|
double curvature_peak{0.0};
|
|
glm::dvec2 origin{0.0};
|
|
glm::dvec2 direction{0.0, 1.0};
|
|
glm::dvec2 normal{0.0};
|
|
};
|
|
|
|
struct curve_report
|
|
{
|
|
int vertex{-1};
|
|
double radius{0.0};
|
|
std::vector<double> radii;
|
|
double transition_in{0.0};
|
|
double transition_out{0.0};
|
|
double deflection{0.0};
|
|
double arc_length{0.0};
|
|
double tangent_in{0.0};
|
|
double tangent_out{0.0};
|
|
double unbalanced{0.0};
|
|
double cant_rate_in{0.0};
|
|
double cant_rate_out{0.0};
|
|
double jerk_in{0.0};
|
|
double jerk_out{0.0};
|
|
recommendation recommended;
|
|
};
|
|
|
|
struct profile_point
|
|
{
|
|
double chainage{0.0};
|
|
double elevation{0.0};
|
|
double radius{0.0};
|
|
double tangent{0.0};
|
|
};
|
|
|
|
struct result
|
|
{
|
|
bool valid{false};
|
|
transition_shape shape{transition_shape::cubic_parabola};
|
|
double gauge{1500.0};
|
|
std::vector<std::string> errors;
|
|
std::vector<std::string> warnings;
|
|
std::vector<std::string> radius_warnings;
|
|
std::vector<glm::dvec2> vertices;
|
|
std::vector<double> vertex_chainages;
|
|
std::vector<double> vertex_elevations;
|
|
std::vector<element> elements;
|
|
std::vector<curve_report> curves;
|
|
std::vector<profile_point> profile;
|
|
double length{0.0};
|
|
glm::dvec3 start{0.0};
|
|
glm::dvec3 end{0.0};
|
|
double start_extension{0.0};
|
|
double end_extension{0.0};
|
|
};
|
|
|
|
result compute(design const &Design);
|
|
double speed_limit(double const Radius, limits const &Limits);
|
|
result compute_recommended(design &Design, bool const Transitions);
|
|
bool tangent_intersection(design const &Design, glm::dvec2 &Point);
|
|
bool collinear(design const &Design);
|
|
bool spiral_tangents(transition_shape const Shape, double const TurnIn, double const TurnOut, double &TangentIn, double &TangentOut);
|
|
|
|
struct station
|
|
{
|
|
glm::dvec3 position{0.0};
|
|
glm::dvec3 direction{0.0};
|
|
double cant{0.0};
|
|
int turn{0};
|
|
};
|
|
station evaluate(result const &Result, double const Chainage);
|
|
double elevation(result const &Result, double const Chainage);
|
|
double grade(result const &Result, double const Chainage);
|
|
|
|
// a point of the plan projected on the alignment, its offset positive to the left; past the ends it's measured from the straights carried on
|
|
struct plan_projection
|
|
{
|
|
double chainage{0.0};
|
|
double offset{0.0};
|
|
};
|
|
std::vector<plan_projection> project(result const &Result, std::vector<glm::dvec2> const &Points);
|
|
|
|
struct trace_fit
|
|
{
|
|
bool valid{false};
|
|
vertex fitted;
|
|
double rms{0.0};
|
|
double worst{0.0};
|
|
};
|
|
// the radii of the curve of the vertex and their shares which follow the points traced along the track best; the tangents, the
|
|
// transitions and the cant stay. Radii 0 takes the fewest radii, up to three, which follow the points about as well as more would
|
|
trace_fit fit_trace(design const &Design, std::size_t const Vertex, std::vector<glm::dvec2> const &Points, int const Radii);
|
|
|
|
std::size_t minimum_pieces(result const &Result, design const &Design);
|
|
// Breaks: ascending chainages at which pieces have to end. Counts: least number of the pieces between the consecutive breaks,
|
|
// one more than the breaks; Intervals receives the number of the interval of each piece
|
|
std::vector<segment_data> pieces(result const &Result, design const &Design, std::size_t const Count, std::vector<double> const &Breaks = {}, std::vector<std::size_t> const &Counts = {},
|
|
std::vector<std::size_t> *Intervals = nullptr);
|
|
|
|
struct join_end
|
|
{
|
|
glm::dvec3 position{0.0};
|
|
glm::dvec2 direction{0.0, 1.0};
|
|
double roll{0.0};
|
|
|
|
bool operator==(join_end const &) const = default;
|
|
};
|
|
|
|
enum class join_kind
|
|
{
|
|
none,
|
|
straight,
|
|
arc,
|
|
curve,
|
|
reverse_curve,
|
|
bezier
|
|
};
|
|
|
|
struct join_request
|
|
{
|
|
join_end start;
|
|
join_end end;
|
|
double radius{0.0};
|
|
int variant{0};
|
|
bool transitions{false};
|
|
double speed{100.0};
|
|
double kink{0.1};
|
|
transition_shape shape{transition_shape::cubic_parabola};
|
|
limits norms;
|
|
};
|
|
|
|
struct join_result
|
|
{
|
|
join_kind kind{join_kind::none};
|
|
std::vector<segment_data> pieces;
|
|
double length{0.0};
|
|
double radius{0.0};
|
|
double cant{0.0};
|
|
double transition{0.0};
|
|
double speed{0.0};
|
|
double kink{0.0};
|
|
int variants{0};
|
|
std::vector<std::string> warnings;
|
|
std::vector<std::string> radius_warnings;
|
|
};
|
|
|
|
join_result join(join_request const &Request);
|
|
|
|
enum class lay_kind
|
|
{
|
|
arc_straight,
|
|
straight_arc,
|
|
arc,
|
|
straight
|
|
};
|
|
|
|
// a track laid on from an end the way the layout lays it, with the transition curves of the norms: from the curvature the end has
|
|
// into the arc, between the arcs of a compound curve where both turn the same way, and out of the arc to the straight
|
|
struct lay_request
|
|
{
|
|
join_end start; // the roll in degrees, as the track goes on
|
|
double curvature{0.0}; // of the end as the track goes on, positive turning from x towards z
|
|
glm::dvec3 target{0.0};
|
|
lay_kind kind{lay_kind::arc_straight};
|
|
double radius{500.0}; // of the arc, but the arc through the target
|
|
double speed{100.0};
|
|
double piece_length{100.0};
|
|
limits norms;
|
|
|
|
bool operator==(lay_request const &) const = default;
|
|
};
|
|
|
|
// no pieces where the norms find no room for the transitions, the note says why
|
|
struct lay_result
|
|
{
|
|
std::vector<segment_data> pieces;
|
|
std::string note;
|
|
double length{0.0};
|
|
double radius{0.0};
|
|
double cant{0.0};
|
|
double entry{0.0}; // the transition out of the curvature of the end
|
|
double exit{0.0};
|
|
double from_radius{0.0}; // of the end, 0 for a straight
|
|
bool compound{false};
|
|
};
|
|
|
|
std::optional<lay_result> lay_on(lay_request const &Request);
|
|
|
|
// the transitions between the arcs of a compound curve which the norms ask for at the speed, the cant of the vertex on its sharpest arc
|
|
void recommend_between(vertex &Vertex, double const Speed, limits const &Limits);
|
|
|
|
}
|