17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-18 04:29:18 +02:00

feat(editor): digitizing takes the good parts of a line: a run whose design can't be read whole is split at the track the reading fails at and each part is digitized on its own, only single tracks that make no line are left out and named in the log; Digitize all reports the lines digitized and the paths left out, opening a line digitized in parts says so with the reason for the paths left out; a stored radius agrees with the one its design makes within 0.1 %

This commit is contained in:
maj00r
2026-10-12 18:00:26 +02:00
parent 95c3842748
commit 9b75e64c9b
4 changed files with 71 additions and 22 deletions

View File

@@ -829,14 +829,15 @@ class editor_mode : public application_mode, private editor_track::observer
bool route_from_line(TTrack &Track);
alignment::vertex route_vertex_of(editor_track::curve const &Curve) const;
bool route_load(TTrack &Track);
void route_read_stored();
void route_read_stored(TTrack &Track);
void route_take_stored(int const Index);
void record_switch(TTrack &Track, editor_track::switch_template const &Shape);
void record_slip(std::vector<TTrack *> const &Parts, std::string const &Kind, std::string const &Type, double const Radius, double const Angle, std::string const &Base);
void render_switch_record(TTrack const &Track) const;
void route_store();
bool digitize_drawn(std::vector<TTrack *> const &Created, bool const Alone = true);
bool digitize_chain(editor_track::chain const &Chain, std::string *Reason = nullptr);
bool digitize_chain(editor_track::chain const &Chain, std::string *Reason = nullptr, TTrack **Culprit = nullptr);
int digitize_parts(editor_track::chain const &Chain, std::string *Reason, int &Skipped);
void digitize_all();
void render_route_stored();
void route_update()

View File

@@ -1649,12 +1649,12 @@ bool editor_mode::route_load(TTrack &Track)
m_route.designed = 0;
if (false == (m_route.single ? route_from_curve(Track) : route_from_line(Track)))
return false;
route_read_stored();
route_read_stored(Track);
return true;
}
// the design kept in the scenery for the fragment takes the place of the one read from the paths; its chainage is carried on
void editor_mode::route_read_stored()
void editor_mode::route_read_stored(TTrack &Track)
{
auto &route{m_route};
route.departed = -1;
@@ -1668,15 +1668,24 @@ void editor_mode::route_read_stored()
route.departed = alignment_store::departed(chain.tracks, route.departure);
auto const loose{std::any_of(chain.tracks.begin(), chain.tracks.end(), [](TTrack const *Track) { return false == alignment_store::on_track(*Track).has_value(); })};
bool digitized{false};
int parts{0};
int skipped{0};
std::string failure;
if (index < 0 && route.departed < 0 && loose && false == route.single)
{
if (digitize_chain(chain, &failure))
parts = digitize_parts(chain, &failure, skipped);
if (parts == 1 && skipped == 0)
{
alignment_store::settle();
index = alignment_store::find(chain.start, chain.end, reversed);
digitized = true;
}
else if (parts > 0)
{
alignment_store::settle();
route_from_line(Track);
route.departed = alignment_store::departed(route.chain.tracks, route.departure);
}
}
if (index >= 0 && false == reversed && false == route.single)
{
@@ -1693,6 +1702,10 @@ void editor_mode::route_read_stored()
route.status += STR_C("\nThe line is digitized now, a straight");
else if (digitized)
route.status += format(STR_C("\nThe line is digitized now, curves kept in the scenery: %d"), route.designed);
else if (parts > 0)
route.status += format(STR_C("\nThe line is digitized in parts: %d, paths left out: %d"), parts, skipped) + (failure.empty() ? std::string{} : " - " + failure);
else if (skipped > 0 && loose && skipped < static_cast<int>(chain.tracks.size()))
route.status += format(STR_C("\nPaths left out of the digitized line: %d"), skipped) + (failure.empty() ? std::string{} : " - " + failure);
else if (false == failure.empty())
route.status += STR_C("\nThe line can't be digitized: ") + failure;
else if (route.designed > 0)
@@ -1808,21 +1821,12 @@ void editor_mode::digitize_all()
}
visited.insert(chain.tracks.begin(), chain.tracks.end());
std::string reason;
if (digitize_chain(chain, &reason))
{
++kept;
continue;
}
++failed;
if (false == reason.empty())
{
WriteLog("Editor: digitizing - " + reason, logtype::generic);
if (first.empty())
first = reason;
}
kept += digitize_parts(chain, &reason, failed);
if (first.empty())
first = reason;
}
alignment_store::settle();
auto text{format(STR_C("Lines digitized: %d, not digitized: %d"), kept, failed)};
auto text{format(STR_C("Lines digitized: %d, paths left out: %d"), kept, failed)};
if (false == first.empty())
text += STR_C(", the first: ") + first;
WriteLog("Editor: " + text, logtype::generic);
@@ -1831,7 +1835,40 @@ void editor_mode::digitize_all()
route_load(*m_route.chain.tracks[m_route.chain.tracks.size() / 2]);
}
bool editor_mode::digitize_chain(editor_track::chain const &Chain, std::string *Reason)
int editor_mode::digitize_parts(editor_track::chain const &Chain, std::string *Reason, int &Skipped)
{
auto const count{Chain.tracks.size()};
if (count == 0 || std::all_of(Chain.tracks.begin(), Chain.tracks.end(), [](TTrack const *Track) { return alignment_store::on_track(*Track).has_value(); }))
return 0;
TTrack *culprit{nullptr};
std::string reason;
if (digitize_chain(Chain, &reason, &culprit))
return 1;
if (count == 1)
{
++Skipped;
reason = (Chain.tracks.front()->name().empty() ? std::string{"(noname)"} : Chain.tracks.front()->name()) + ": " + reason;
WriteLog("Editor: digitizing - " + reason, logtype::generic);
if (Reason != nullptr && Reason->empty())
*Reason = reason;
return 0;
}
auto const found{static_cast<std::size_t>(std::find(Chain.tracks.begin(), Chain.tracks.end(), culprit) - Chain.tracks.begin())};
auto const split{found < count ? std::max<std::size_t>(1, found) : count / 2};
int parts{0};
for (auto const &[first, last] : {std::pair<std::size_t, std::size_t>{0, split - 1}, std::pair<std::size_t, std::size_t>{split, count - 1}})
{
editor_track::chain part;
std::string error;
if (editor_track::find_chain(Chain.tracks[first], Chain.tracks[last], part, error) && part.tracks.size() == last - first + 1)
parts += digitize_parts(part, Reason, Skipped);
else
Skipped += static_cast<int>(last - first + 1);
}
return parts;
}
bool editor_mode::digitize_chain(editor_track::chain const &Chain, std::string *Reason, TTrack **Culprit)
{
if (Chain.tracks.empty())
return false;
@@ -1887,6 +1924,8 @@ bool editor_mode::digitize_chain(editor_track::chain const &Chain, std::string *
{
if (Reason != nullptr)
*Reason = format(STR_C("the straights meet with no curve at path %s"), name(nearest(entry.position)).c_str());
if (Culprit != nullptr)
*Culprit = nearest(entry.position);
return false;
}
auto vertex{route_vertex_of(entry.shape)};
@@ -1923,6 +1962,8 @@ bool editor_mode::digitize_chain(editor_track::chain const &Chain, std::string *
}
if (false == fits)
{
if (Culprit != nullptr)
*Culprit = farthest;
if (Reason != nullptr)
*Reason = closest < std::numeric_limits<double>::max() ? format(STR_C("the curves read from the paths leave path %s by %.2f m"), name(farthest).c_str(), closest) : std::string{STR_C("the paths don't make a line of straights, arcs and transition curves")};
return false;

View File

@@ -96,9 +96,10 @@ bool agrees(std::vector<stored_element> const &Stored, std::vector<alignment::el
made.push_back(describe(e));
if (stored.size() != made.size())
return false;
auto const close = [](double const A, double const B) { return std::abs(A - B) <= 0.01 + 1e-3 * std::abs(A); };
for (std::size_t i = 0; i < stored.size(); ++i)
if (stored[i].kind != made[i].kind || std::abs(stored[i].chainage - made[i].chainage) > 0.01 || std::abs(stored[i].length - made[i].length) > 0.01 ||
std::abs(stored[i].radius_start - made[i].radius_start) > 0.01 || std::abs(stored[i].radius_end - made[i].radius_end) > 0.01)
false == close(stored[i].radius_start, made[i].radius_start) || false == close(stored[i].radius_end, made[i].radius_end))
return false;
return true;
}

View File

@@ -5185,8 +5185,8 @@ msgstr "Zdigitalizuj wszystkie tory"
msgid "Every line of the scenery not digitized yet is kept in it with its straights, arcs and transition curves, the way the drawn tracks are kept; the paths stay as they are"
msgstr "Każda jeszcze niezdigitalizowana linia scenerii zostaje w niej zapisana z prostymi, łukami i krzywymi przejściowymi, tak jak rysowane tory; tory zostają tak, jak leżą"
msgid "Lines digitized: %d, not digitized: %d"
msgstr "Zdigitalizowane linie: %d, niezdigitalizowane: %d"
msgid "Lines digitized: %d, paths left out: %d"
msgstr "Zdigitalizowane linie: %d, pominięte tory: %d"
msgid ", the first: "
msgstr ", pierwsza: "
@@ -5197,6 +5197,12 @@ msgstr "\nLinia zdigitalizowana: prosta"
msgid "\nThe line is digitized now, curves kept in the scenery: %d"
msgstr "\nLinia zdigitalizowana, łuki zapisane w scenerii: %d"
msgid "\nThe line is digitized in parts: %d, paths left out: %d"
msgstr "\nLinia zdigitalizowana w częściach: %d, pominięte tory: %d"
msgid "\nPaths left out of the digitized line: %d"
msgstr "\nTory pominięte w zdigitalizowanej linii: %d"
msgid "\nThe line can't be digitized: "
msgstr "\nNie da się zdigitalizować linii: "