mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 11:23:08 +01:00
A curve laid anew, its radius changed or made compound, or a straight moved: the paths of the chain are cut again where their joints stood, set square onto the new line, each keeping its stretch of the ground, so their events, their track circuits and the cuts of the block sections stay where they were instead of being handed on along the line; the parts between the switches alike, the old even sharing kept where the joints don't follow one another along the new line. The objects by a track taken for a change go with it by themselves: the signals and the warning discs it or its run reads, the SHP resonators by their events, and the controls of the block sections, the hectometre posts, the W17 markers and the other signs by the track nearest to them, within 12 m. They move square to the new axis keeping their offset and their turn, an object moved by hand meanwhile staying where it was put. Such a binding isn't kept in the scenery nor shown among the bound objects of the infra tool, which can still bind the object for good, and the undo and the redo take the objects back and forth with the tracks. The status of the Plan tells how many objects moved with the tracks. A path taking an object over the other way round keeps it on its side, turned as it was.
321 lines
9.0 KiB
C++
321 lines
9.0 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);
|
|
// the points of the plan set square onto the line, the chainages of them in their order between From and To; empty where they
|
|
// don't follow one another along it
|
|
std::vector<double> breaks_at(result const &Result, std::vector<glm::dvec2> const &Points, double const From, double const To);
|
|
// the pieces of the line ending at the joints of the old paths set square onto it, so that each old path keeps its stretch of the
|
|
// ground: Intervals receives the old path of each piece, or stays empty where the joints don't follow one another along the line
|
|
// and the pieces are cut as by pieces() alone
|
|
std::vector<segment_data> pieces_at(result const &Result, design const &Design, std::size_t const Count, std::vector<glm::dvec2> const &Joints, std::vector<std::size_t> &Intervals);
|
|
|
|
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);
|
|
|
|
}
|