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

feat(tracks): switches keep their neighbours joined on replacing, flipping and moving; events copied on splitting; circuits, overhead line, sleepers and events of the paths; curve design through the switches of a line; changes in files included more than once or with parameters reported instead of written; split of a straight at the point found, not a share of its length

This commit is contained in:
maj00r
2026-10-05 01:21:11 +02:00
parent 8f050d9c3e
commit b07050fa52
5 changed files with 567 additions and 40 deletions

View File

@@ -269,6 +269,11 @@ result fit_between(design const &Design)
auto const start{plan_of(Design.start)};
auto const end{plan_of(Design.end)};
if (glm::length(Design.start_direction) < 1e-9 || glm::length(Design.end_direction) < 1e-9)
{
r.errors.emplace_back("The direction of an end of the fragment is undefined, its end path has zero length");
return r;
}
auto const startdirection{glm::normalize(Design.start_direction)};
auto const enddirection{glm::normalize(Design.end_direction)};
auto const count{Design.vertices.size()};
@@ -872,7 +877,8 @@ std::size_t minimum_pieces(result const &Result, design const &Design)
return count;
}
std::vector<segment_data> pieces(result const &Result, design const &Design, std::size_t const Count)
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)
{
struct span
{
@@ -920,23 +926,56 @@ std::vector<segment_data> pieces(result const &Result, design const &Design, std
}
spans.erase(spans.begin() + i);
}
while (false == spans.empty() && spans.size() < Count)
{
auto longest = std::max_element(spans.begin(), spans.end(), [&](span const &A, span const &B) { return extent(A) < extent(B); });
span second{*longest};
if (longest->generic)
// splits the span at the chainage
auto const split = [&](std::vector<span>::iterator Span, double const Chainage) {
span second{*Span};
if (Span->generic)
{
auto const middle{(longest->start + longest->end) * 0.5};
second.start = middle;
longest->end = middle;
second.start = Chainage;
Span->end = Chainage;
}
else
{
auto const middle{(longest->from + longest->to) * 0.5};
second.from = middle;
longest->to = middle;
auto const local{Chainage - Result.elements[Span->element].chainage};
second.from = local;
Span->to = local;
}
spans.insert(std::next(longest), second);
spans.insert(std::next(Span), second);
};
double constexpr margin{0.01};
for (auto const chainage : Breaks)
{
auto inside{std::find_if(spans.begin(), spans.end(), [&](span const &Span) { return chainage_from(Span) < chainage - margin && chainage_to(Span) > chainage + margin; })};
if (inside != spans.end())
split(inside, chainage);
}
auto const interval = [&](span const &Span) {
return static_cast<std::size_t>(std::upper_bound(Breaks.begin(), Breaks.end(), (chainage_from(Span) + chainage_to(Span)) * 0.5) - Breaks.begin());
};
for (std::size_t k = 0; k < Counts.size(); ++k)
{
while (true)
{
auto const inside{static_cast<std::size_t>(std::count_if(spans.begin(), spans.end(), [&](span const &Span) { return interval(Span) == k; }))};
if (inside == 0 || inside >= Counts[k])
break;
auto longest{spans.end()};
for (auto candidate = spans.begin(); candidate != spans.end(); ++candidate)
if (interval(*candidate) == k && (longest == spans.end() || extent(*candidate) > extent(*longest)))
longest = candidate;
split(longest, (chainage_from(*longest) + chainage_to(*longest)) * 0.5);
}
}
while (false == spans.empty() && spans.size() < Count)
{
auto longest = std::max_element(spans.begin(), spans.end(), [&](span const &A, span const &B) { return extent(A) < extent(B); });
split(longest, (chainage_from(*longest) + chainage_to(*longest)) * 0.5);
}
if (Intervals != nullptr)
{
Intervals->clear();
for (auto const &piece : spans)
Intervals->push_back(interval(piece));
}
std::vector<segment_data> result;