17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-31 05:20:52 +01:00

feat(editor): the tracks laid on the terrain model go onto it as the tracks going onto the terrain do, the chain laid since the laying began fitted again at each click, with the tracks around kept and met; a straight or an arc cut by the fit before made one again, a path cut only where it would part from the line by more than 3 cm; a choice of the heights while laying: fitted, from point to point, level, kept in the settings; the fit taken back with its click

This commit is contained in:
maj00r
2026-10-23 15:55:58 +02:00
parent 7c0b3bc858
commit 4d2f95aa43
11 changed files with 392 additions and 90 deletions

View File

@@ -1203,6 +1203,55 @@ std::vector<double> breaks(line const &Line)
return result;
}
std::vector<double> fewest_breaks(line const &Line, std::vector<double> Joints, double const Tolerance)
{
std::sort(Joints.begin(), Joints.end());
Joints.erase(std::unique(Joints.begin(), Joints.end(), [](double const A, double const B) { return std::abs(A - B) < 1e-6; }), Joints.end());
auto const all{breaks(Line)};
auto const inward = [&](double const Chainage, double const Other) { return grade(Line, Chainage + std::min(1e-3, std::abs(Other - Chainage) * 0.5) * (Other > Chainage ? 1.0 : -1.0)); };
auto const follows = [&](double const From, double const To) {
auto const length{To - From};
auto const h0{elevation(Line, From)};
auto const h1{elevation(Line, To)};
auto const g0{inward(From, To) * length};
auto const g1{inward(To, From) * length};
auto const count{std::max(4, static_cast<int>(std::ceil(length)))};
for (int i = 1; i < count; ++i)
{
auto const u{static_cast<double>(i) / count};
auto const u2{u * u};
auto const u3{u2 * u};
auto const height{(2.0 * u3 - 3.0 * u2 + 1.0) * h0 + (u3 - 2.0 * u2 + u) * g0 + (-2.0 * u3 + 3.0 * u2) * h1 + (u3 - u2) * g1};
if (std::abs(height - elevation(Line, From + u * length)) > Tolerance)
return false;
}
return true;
};
std::vector<double> result;
for (std::size_t k = 0; k + 1 < Joints.size(); ++k)
{
std::vector<double> stops;
for (auto const chainage : all)
if (chainage > Joints[k] + 1e-6 && chainage < Joints[k + 1] - 1e-6)
stops.push_back(chainage);
stops.push_back(Joints[k + 1]);
auto from{Joints[k]};
std::size_t next{0};
while (next + 1 < stops.size())
{
auto reach{next};
for (auto i{next + 1}; i < stops.size() && follows(from, stops[i]); ++i)
reach = i;
if (reach + 1 == stops.size())
break;
result.push_back(stops[reach]);
from = stops[reach];
next = reach + 1;
}
}
return result;
}
std::string format_chainage(double const Chainage)
{
auto const value{std::abs(Chainage)};

View File

@@ -179,6 +179,9 @@ std::vector<departure> bridged(std::vector<double> const &Chainages, std::vector
// chainages where the paths have to end so that each of them carries a single grade or a single curve
std::vector<double> breaks(line const &Line);
// of the breaks those the paths between Joints can't do without: a path from one joint or break kept to the next follows the line
// within Tolerance with the heights and the grades of its ends
std::vector<double> fewest_breaks(line const &Line, std::vector<double> Joints, double const Tolerance);
std::string format_chainage(double const Chainage);

View File

@@ -116,6 +116,8 @@ bool editorSettings::load()
m_top_rails = static_cast<std::uint32_t>(std::strtoul(value.c_str(), nullptr, 16)) | 0xff000000u;
else if (key == "track_norms")
m_norms = value == "free" ? track_norms::free_laying : value == "plk" ? track_norms::plk : track_norms::ask;
else if (key == "lay_heights")
m_heights = value == "points" ? lay_heights::points : value == "level" ? lay_heights::level : lay_heights::fitted;
else if (key.rfind(origin_prefix, 0) == 0)
{
// northing;easting
@@ -165,6 +167,7 @@ bool editorSettings::save()
stream << "top_tracks " << m_top_tracks << "\n";
stream << "top_rails " << std::hex << (m_top_rails & 0xffffffu) << std::dec << "\n";
stream << "track_norms " << (m_norms == track_norms::free_laying ? "free" : m_norms == track_norms::plk ? "plk" : "ask") << "\n";
stream << "lay_heights " << (m_heights == lay_heights::points ? "points" : m_heights == lay_heights::level ? "level" : "fitted") << "\n";
stream << std::fixed << std::setprecision(3);
for (auto const &origin : m_orthophoto_origins)
stream << origin.first << " " << origin.second.first << ";" << origin.second.second << "\n";

View File

@@ -76,6 +76,16 @@ public:
};
track_norms norms() const { return m_norms; }
void norms(track_norms Norms) { m_norms = Norms; }
// the heights of the tracks laid on the ground: fitted to it as the tracks go onto the terrain, the points clicked on it with
// even grades between them, level
enum class lay_heights
{
fitted,
points,
level
};
lay_heights heights() const { return m_heights; }
void heights(lay_heights Heights) { m_heights = Heights; }
private:
movement_scheme m_movement{movement_scheme::wsad};
@@ -92,6 +102,7 @@ private:
int m_top_tracks{0}; // the railway in the top view: whole, without the ballast, the rails alone
std::uint32_t m_top_rails{0xffff6e28}; // colour of the rails alone, as ImGui keeps it: ABGR
track_norms m_norms{track_norms::ask};
lay_heights m_heights{lay_heights::fitted};
};
// global editor settings instance