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:
@@ -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)};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user