17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-26 18:14:55 +01:00
Files
maszyna/application/editormodesrk.h
maj00r 4c55951d8a feat(editor): the automatic block both ways or mixed, and the lines out on the schematic
A block boundary of a line both ways has, on each track, the block signal of its trains 15 m before the joint and the one of the wrong-track trains 15 m beyond it, named after its twin with N, both on the outside of the line, the templates leaning the other way picked for the N ones, as on the lines of PKP PLK. The mixed block keeps the automatic block for the trains of the track and the semi-automatic one for the wrong-track ones: no N signals, a warning disc the braking distance before the entry signal of the wrong-track trains. A choice under the table of the lines sets either for the double-track lines of the station, kept in the record of the station, and by itself a line takes the mixed block where a warning disc stands for its wrong-track trains and no N signal does. Set the line signals places the N signals or the warning disc and takes the other away, a block boundary drawn places the N signals of a line both ways, and sbl_odstep.inc switches both block signals of a section with its 7th parameter. The name shown at the mouse while drawing takes the letter the block signal will get where its number stands already.

The station schematic shows the lines out to the next stations straightened: their block sections in the colours of their names with their lengths, the joints, the block signals and the warning discs with their km on the outside of the line, the axis in km; Lines fits them in, a section under the mouse tells its name, length and km, and a click on it flies there in the 3d view.
2026-10-22 20:47:52 +02:00

356 lines
18 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 "application/editortool.h"
#include "editor/editorStation.hpp"
#include "scene/scenelayers.h"
#include "imgui/imgui.h"
#include <map>
#include <optional>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
// the signalling of a station (SRK): the station found from a switch of it, its schematic, its name and code
class srk_tool final : public editor_tool
{
public:
srk_tool(editor_selection &Selection, editor_view &View, editor_history &History, editor_templates &Templates, editor_signals &Signals)
: m_selection{Selection}, m_view{View}, m_history{History}, m_templates{Templates}, m_signals{Signals}
{
}
void update() override;
void draw_overlay() const override;
void render_options() override;
void render_windows() override;
void forget(scene::basic_node const *Node) override;
editor_selftest_result selftest(std::string const &Command, std::istringstream &Words) override;
void set_open(bool const Open) { m_open = Open; }
// the block boundaries drawn by hand on the lines out of the open station
bool drawing() const { return m_open && m_drawing && m_layout.has_value(); }
// what a click at the point of a track does while the block boundaries are drawn, for the label at the mouse; Valid: it does
// something
std::string boundary_hover(glm::dvec3 const &Point, bool &Valid);
void boundary_click();
// the stations described go to the files of their layers, as "//$s" lines
void store();
private:
editor_selection &m_selection;
editor_view &m_view;
editor_history &m_history;
editor_templates &m_templates;
editor_signals &m_signals;
// the block of a line out of the station
enum class block_kind
{
semi, // semi-automatic: a warning disc before the entry signal
three, // the automatic one of three aspects: the block sections no shorter than the braking distance
four // of four aspects, the warning two signals ahead: the sections no shorter than half of it
};
// where the block of a line out of the station comes from
enum class block_reason
{
hand, // set by hand
standing, // block signals stand along it
double_track, // the automatic one on a double-track line
single // the semi-automatic one on a single-track line
};
// a station described: found again by a switch of it
struct record
{
scene::layer_handle layer{null_handle};
std::string anchor; // the name of a switch of the station
TTrack *track{nullptr}; // the switch, once found: it stays the anchor when it gets renamed
std::string code; // the abbreviation of the station, as MMz
std::string name;
std::string line; // the number of the railway line
std::string km; // of the axis of the station along the line, empty while unknown
bool reversed{false}; // the km rise to the left of the schematic, the switches numbered from there
int braking{0}; // m, the braking distance of the line set by hand, 0: after its speed
std::map<std::string, block_kind> blocks; // of the lines by their entry signals, as set by hand
std::map<std::string, bool> ways; // the automatic block of the lines by their entry signals both ways, as set by hand
};
// the schematic: the chainage across, the offsets upwards, exaggerated
struct view
{
double from{0.0};
double to{1000.0};
double centre{0.0};
float exaggeration{0.0f}; // 0: fit at the next draw
};
bool m_open{false};
bool m_strip{true}; // the schematic shown, off for the screenshots of the self-tests
bool m_loaded{false};
bool m_changed{false};
std::vector<record> m_records;
std::optional<station::layout> m_layout;
int m_record{-1}; // of the open station, -1 while it has none
TTrack *m_anchor{nullptr}; // the switch the open station was found from
bool m_reversed{false}; // the switches numbered from the right end of the schematic
std::size_t m_history_revision{0};
TTrack const *m_picked{nullptr}; // the track selected when the station was looked for
view m_view_state;
bool m_fit_lines{false}; // the schematic fits the lines out to the next stations too
int m_hover{-1}; // path of the layout under the mouse in the schematic
bool m_dragging{false};
std::vector<std::pair<std::string, std::size_t>> m_found; // the stations of the scenery: a switch and the count of them
struct circuit_mark
{
glm::dvec2 at{0.0}; // in the schematic
glm::dvec3 world{0.0};
std::string text;
ImU32 colour{0};
double length{0.0};
bool labelled{true}; // the circuits of the switches go without, named after them
};
std::vector<int> m_circuit_of; // of each path of the layout, an index into m_circuits, -1 for none
std::vector<circuit_mark> m_circuits;
std::vector<glm::dvec2> m_ticks; // the joints between the circuits, in the schematic
struct joint_mark
{
glm::dvec3 at{0.0};
glm::dvec3 across{0.0}; // of the track there, in the plan
};
std::vector<joint_mark> m_joints; // the same in the scenery
struct signal_mark
{
glm::dvec2 at{0.0}; // in the schematic
bool ahead{true}; // the trains it faces run along the chainage
std::string text;
glm::dvec3 head{0.0}; // above its lamps, in the scenery
bool unfit{false}; // its lights don't show what its routes need
};
std::vector<signal_mark> m_signal_marks;
bool m_signals_known{false}; // the signals standing surveyed, once their templates are found
std::vector<station::lengths> m_lengths; // of the station tracks, by their numbers
bool m_measured{false};
bool m_numbered{false}; // the station has tracks numbered by their circuits
int m_length_hover{-1}; // of the lengths, the row under the mouse
int m_length_canvas{-1}; // of the lengths, of the track under the mouse in the schematic
int m_length_shown{-1}; // of the lengths, the one drawn: of the row or the track under the mouse, else of the track selected
// how the SHP track resonator of a signal stands
enum class shp_state
{
needless, // the signal needs none
missing,
beyond, // missing, the tracks before the signal end short of its place
off, // farther from its place than allowed
placed
};
// a signal of the station or of its lines, its lights as the routes of its trains need them: Ie-1, Ie-4 § 8
struct head_check
{
scene::instance_handle instance{0};
std::string name; // shown, without the code of the station
std::string kind;
glm::dvec3 position{0.0};
glm::dvec2 travel{0.0, 1.0};
std::string file; // of its template
std::string lamps;
std::vector<int> own; // the speeds of its template
bool station{false}; // stands by the station, not out on a line
std::vector<station::route> routes;
std::vector<std::string> nexts; // of the routes, the signals they end at, shown
std::vector<int> speeds; // km/h, the lower ones it must show: 40, 60, 100
bool informs{false}; // it must tell the next signal shows stop
bool white{false}; // it must give the substitute signal
int shortened{0}; // km/h, it slows the trains to, the next signal nearer than the braking distance: Ie-4 § 8 ust. 5
bool indicator{false}; // a W21 "14" beside it, for 140 km/h so
bool fits{true}; // its template shows all of it
bool more{false}; // its template has more than it needs
std::string fit; // the template that fits best, empty for none
std::vector<std::string> problems; // of its place
// m before it the SHP track resonator belongs, -1 for none: 200 m before an entry signal, a block signal and a warning disc,
// at an exit signal onto a line of the automatic block
double shp{-1.0};
double shp_found{-1.0}; // m before it the trains run into the event of the SHP resonator standing, -1 for none
bool shp_short{false}; // the tracks before it end short of the place of its resonator
shp_state shp_of() const;
};
std::vector<head_check> m_heads;
bool m_heads_known{false}; // the templates found
int m_head_hover{-1}; // of the heads, the row under the mouse
// a line out of the open station, from an entry signal of it
struct line_row
{
std::string entry; // the entry signal, shown
glm::dvec3 position{0.0}; // of the entry signal
glm::dvec2 travel{0.0, 1.0}; // the trains it faces run, in the plan
int number{0}; // of the track of a double-track line, 0 on a single-track one
bool inbound{true}; // its trains run towards the station
int partner{-1}; // the other track of a double-track line, of the lines
double length{0.0}; // to the entry signal of the next station, or to the end of the tracks
std::string next; // the entry signal of the next station facing out along it, shown; empty for none
bool station{false}; // ends at the next station rather than at the end of the tracks
std::size_t blocks{0}; // the block signals standing along it
// the block boundaries of the same facing its trains, the joints they turn them to stop at, out along it, with the signal shown
std::vector<std::pair<double, std::string>> stops;
std::vector<std::pair<double, std::string>> wrong; // the block signals facing its wrong-track trains, out along it, shown
block_kind block{block_kind::semi};
block_reason why{block_reason::single}; // the block it has, so
block_kind own{block_kind::semi}; // the block it has by itself, unless set by hand
block_reason own_why{block_reason::single};
// the automatic block both ways: at each block boundary a block signal of each track either way, the wrong-track one with N
bool both{false};
bool both_hand{false}; // so set by hand
bool own_both{false}; // so by itself
// block signals stand along it, none switched by block sections of the editor: it keeps the block of the scenery as it stands
bool legacy{false};
double braking{0.0}; // m, the braking distance on it
std::string km_number; // the line of the kilometrage it runs along
bool rising{true}; // its trains run towards the higher km
bool km_known{false}; // the km out along it are known
// in the schematic, straightened: the chainage of the entry signal, 1 or -1 the way out along the chainage, the offset of the
// track there
double chainage{0.0};
double outward{1.0};
double offset{0.0};
struct run
{
double from{0.0}; // out along the line
double to{0.0};
std::string name;
double km_from{0.0};
double km_to{0.0};
};
std::vector<run> sections; // the track circuits along it, out from the station
struct post
{
double distance{0.0}; // out along the line
std::string name; // shown
bool wrong{false}; // facing the wrong-track trains
double km{0.0};
};
std::vector<post> posts; // the block signals along it
// the signals of the other block standing along it: warning discs on a line of the automatic block, block signals on one of the
// semi-automatic one, the first of them
std::size_t leftovers{0};
glm::dvec3 leftover{0.0};
glm::dvec2 leftover_travel{0.0, 1.0};
};
std::vector<line_row> m_lines;
std::vector<station::line> m_line_ways; // of the lines listed
std::unordered_set<std::string> m_signal_names; // of the signals of the scenery, lowercase: a block signal drawn on one's number takes a letter
std::string m_lines_problem; // why the station has no lines listed
bool m_drawing{false}; // the block boundaries drawn by hand
// a block boundary under the mouse while they are drawn: block signals across the line there, or the ones standing taken away
struct boundary
{
bool valid{false};
bool remove{false};
std::string entry; // of the line under the mouse, its entry signal shown
glm::dvec3 point{0.0}; // the joint, on its axis
std::vector<std::pair<glm::dvec3, glm::dvec3>> joints; // of each track, on its axis, the way out along it
struct post
{
glm::dvec3 point{0.0}; // on the axis
glm::dvec3 side{1.0, 0.0, 0.0}; // the signal stands off the axis so
std::string name;
};
std::vector<post> posts; // of the block signals
};
boundary m_boundary;
// a block boundary drawn on a line of the automatic block of the open station
struct block_edit
{
std::string entry; // of the line, its entry signal shown
glm::dvec3 point{0.0}; // on its axis
bool remove{false}; // the block signals standing there taken away, else placed
};
std::string m_status;
void load();
void open(TTrack &Track);
void refresh();
record &record_of_open();
std::string title() const;
void render_found();
void render_canvas(float const Height);
void fit_view(float const Width, float const Height);
void find_all();
// the switches numbered along the station and named after its code; one step of the history
void number_switches();
// the station cut at the joints of its track circuits and the circuits named; one step of the history
void set_circuits();
// the track circuits as the tracks have them, for the schematic
void survey();
// the signals placed where the station has none and the standing ones named, the circuits before the entry signals set too; one
// step of the history
void set_signals();
// the signals standing by the station, for the schematic
void survey_signals();
// the lengths of the station tracks, the signals given by them
void measure(std::vector<station::signal> const &Signals);
// km/h, the highest of the speeds the tracks of the open station are set to, 0 while none is
double set_speed_of_open() const;
// km/h, the trains run the station at: the highest set on its tracks, else after the braking distance set by hand, else 160
double speed_of_open() const;
// m, the braking distance of the line of the open station: set by hand, else after its speed, as Ie-4 § 8 gives it
double braking_of_open() const;
// the lights of the signals checked against the routes of their trains and the places of the signals they tell of
void check_heads(std::vector<standing_signal> const &Standing);
void render_heads();
// the signals given the templates whose lights fit their routes; one step of the history
void fit_heads();
// the lengths of the station tracks as the list of the tracks gives them, the useful ones each way
void render_lengths();
// the lengths as a table to paste into a spreadsheet, a line a track, the columns parted by tabs
std::string lengths_table() const;
// of the lengths, the one of the station track the track is a part of, -1 for none
int length_of(TTrack const *Track) const;
// the signals of the lines out of the station: on a double-track line the block signals to the next station and the block
// sections between them, on a single-track one a warning disc before the entry signal; one step of the history
void set_lines(block_edit const *Edit = nullptr);
// the lines out of the open station from its entry signals standing, Entries: the signals of the plan they begin at, Owners:
// the standing ones; false with the reason while it has none
bool lines_of_open(std::vector<standing_signal> const &Standing, std::vector<station::line> &Lines, std::vector<station::signal> &Entries, std::vector<std::size_t> &Owners, std::string &Problem) const;
// the block of the line: as set by hand for its entry signal, else the automatic one where block signals stand along it, of four
// aspects where one of them has, else on a double-track line, of the aspects of the block signal chosen in the Signals tool, else
// the semi-automatic one; Own: the block it has by itself
block_kind block_of(station::line const &Line, std::string const &Entry, std::vector<standing_signal> const &Standing, std::vector<signal_head> const &Heads, block_reason &Why, block_kind &Own, block_reason &Own_why, std::size_t &Blocks) const;
// the automatic block of the double-track line both ways: as set by hand for its entry signal, else where block signals stand
// along it, when some of them face its wrong-track trains, else on a new line; Own: so by itself
bool both_ways(std::vector<station::line> const &Lines, std::size_t Index, std::string const &Entry, std::vector<standing_signal> const &Standing, bool &Hand, bool &Own) const;
// the line of the kilometrage a line out of the open station runs along: of the station, at a junction another one
std::string km_line(station::line const &Line) const;
// the km out along the line, Number: of the line of its kilometrage
double km_along(station::line const &Line, std::string const &Number, double const Distance) const;
// the trains of the line run towards the higher km
bool km_rising(station::line const &Line, std::string const &Number) const;
// m, the braking distance at the highest speed out along the line, at 160 km/h while its tracks have none, unless set by hand
double line_braking(station::line const &Line) const;
// the lines out of the open station, for the panel
void survey_lines(std::vector<standing_signal> const &Standing);
void render_lines();
// the SHP track resonators placed where the signals checked need them and have none: 200 m before an entry signal, a block
// signal and a warning disc, at an exit signal onto a line of the automatic block, the track cut where none of its joints lies
// within 5 m, its event put on the track the trains run into there; one step of the history
void set_shp();
// the names of the switches and the circuits of the open station begin with it, empty while it has no code
std::string stem_of_open() const;
// the km at the chainage of the open station: of the kilometrage of its line, else of its record, else of its switches; false
// while unknown
bool km_of_open(double const Chainage, double &Km) const;
// the km at the chainage of the open station, as the Kilometrage tool sets them for its line; false where it doesn't
bool km_of_line(double const Chainage, double &Km) const;
// the line of the open station: of its record, else the one the Kilometrage tool sets the km of through it; empty for none
std::string line_of_open() const;
// the station tracks by their numbers with their circuits as the tracks have them, Inside: the tracks of the circuits; false
// while it has none
bool station_tracks(std::vector<station::numbered> &Tracks, std::unordered_set<TTrack const *> &Inside) const;
// the circuits of the station track of the track renamed after another number; one step of the history
void renumber_track(TTrack const &Track, std::string const &Number);
};