mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 05:39:29 +01:00
feat(editor): the hectometre posts go by the kilometrage of the line where the Kilometrage tool sets it, its jumps too, a post at a jump of the km on from it or of the km it is reached at, the km given at the point still there as a choice; the posts standing go with the place of their number nearest to them
This commit is contained in:
@@ -163,51 +163,22 @@ void km_tool::refresh()
|
||||
auto const high{axis->anchors.back().chainage + 1.0};
|
||||
for (auto const chainage : axis->chainage)
|
||||
entry.guessed.push_back(chainage < low || chainage > high ? 1 : 0);
|
||||
std::vector<double> jumps;
|
||||
for (auto const &anchor : axis->anchors)
|
||||
{
|
||||
if (std::abs(anchor.after - anchor.before) < 1e-6)
|
||||
continue;
|
||||
jumps.push_back(anchor.chainage);
|
||||
auto const way{kilometrage::direction_on(*axis, anchor.chainage)};
|
||||
entry.ticks.push_back({kilometrage::point_on(*axis, anchor.chainage), {-way.y, 0.0, way.x}, 0, true});
|
||||
}
|
||||
// a tick at each hectometre the km pass along the axis, none at a jump
|
||||
auto const hectometres_along = [&](std::vector<glm::dvec3> const &Points, std::vector<double> const &Km, std::vector<double> const &Chainage, std::vector<tick> &Ticks) {
|
||||
for (std::size_t i = 1; i < Points.size(); ++i)
|
||||
if (std::abs(anchor.after - anchor.before) >= 1e-6)
|
||||
{
|
||||
auto const from{std::min(Chainage[i - 1], Chainage[i])};
|
||||
auto const to{std::max(Chainage[i - 1], Chainage[i])};
|
||||
if (std::any_of(jumps.begin(), jumps.end(), [&](double const Jump) { return Jump >= from - 1e-6 && Jump <= to + 1e-6; }))
|
||||
continue;
|
||||
auto const k0{Km[i - 1]};
|
||||
auto const k1{Km[i]};
|
||||
if (std::abs(k1 - k0) < 1e-9)
|
||||
continue;
|
||||
auto way{plan_of(Points[i] - Points[i - 1])};
|
||||
way = glm::length(way) > 1e-9 ? glm::normalize(way) : glm::dvec2{0.0, 1.0};
|
||||
auto const first{static_cast<int>(std::floor(std::min(k0, k1) * 10.0 + 1e-9)) + 1};
|
||||
auto const last{static_cast<int>(std::floor(std::max(k0, k1) * 10.0 + 1e-9))};
|
||||
for (auto hectometres = first; hectometres <= last && hectometres < first + 10; ++hectometres)
|
||||
Ticks.push_back({glm::mix(Points[i - 1], Points[i], (hectometres / 10.0 - k0) / (k1 - k0)), {-way.y, 0.0, way.x}, hectometres, false});
|
||||
auto const way{kilometrage::direction_on(*axis, anchor.chainage)};
|
||||
entry.ticks.push_back({kilometrage::point_on(*axis, anchor.chainage), {-way.y, 0.0, way.x}, 0, true});
|
||||
}
|
||||
};
|
||||
std::vector<double> km;
|
||||
for (auto const chainage : axis->chainage)
|
||||
km.push_back(kilometrage::km_on(*axis, chainage));
|
||||
hectometres_along(axis->points, km, axis->chainage, entry.ticks);
|
||||
for (auto const &hectometre : kilometrage::hectometres(*axis))
|
||||
entry.ticks.push_back({hectometre.at, {-hectometre.rising.y, 0.0, hectometre.rising.x}, hectometre.number, false});
|
||||
m_drawn.push_back(std::move(entry));
|
||||
// the shorter track where the tracks run apart, with its irregular hectometre
|
||||
// the shorter track where the tracks run apart
|
||||
for (auto const &side : axis->sides)
|
||||
{
|
||||
drawn apart;
|
||||
apart.line = line;
|
||||
apart.points = side.points;
|
||||
apart.guessed.assign(side.points.size(), 0);
|
||||
km.clear();
|
||||
for (auto const along : side.along)
|
||||
km.push_back(kilometrage::km_on(*axis, side, along));
|
||||
hectometres_along(side.points, km, side.chainage, apart.ticks);
|
||||
m_drawn.push_back(std::move(apart));
|
||||
}
|
||||
}
|
||||
@@ -303,18 +274,8 @@ void km_tool::pick(TTrack &Track, glm::dvec3 const &Point)
|
||||
else
|
||||
{
|
||||
// the line the point lies on, and its km there
|
||||
auto best{kReadoutReach};
|
||||
for (auto const &line : kilometrage::lines())
|
||||
if (auto const *axis{kilometrage::axis_of(line)}; axis != nullptr)
|
||||
{
|
||||
double gap{0.0};
|
||||
kilometrage::chainage_at(*axis, entry.point, gap);
|
||||
if (gap < best)
|
||||
{
|
||||
best = gap;
|
||||
m_line = line;
|
||||
}
|
||||
}
|
||||
if (auto const line{kilometrage::line_at(entry.point, kReadoutReach)}; false == line.empty())
|
||||
m_line = line;
|
||||
double km{0.0};
|
||||
if (false == m_line.empty() && kilometrage::km_at(m_line, entry.point, km, kReadoutReach))
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "editor/editorFormat.hpp"
|
||||
#include "editor/editorGeometry.hpp"
|
||||
#include "editor/editorIncludeInfo.hpp"
|
||||
#include "editor/editorKilometrage.hpp"
|
||||
|
||||
#include "scene/scene.h"
|
||||
#include "scene/scenelayers.h"
|
||||
@@ -442,61 +443,97 @@ void hekto_tool::hekto_update()
|
||||
continue;
|
||||
tool.found.push_back(post);
|
||||
}
|
||||
if (false == tool.km_read)
|
||||
tool.line_set = kilometrage::line_at(tool.point);
|
||||
tool.line = tool.own_km ? std::string{} : tool.line_set;
|
||||
if (tool.line.empty() && false == tool.km_read)
|
||||
{
|
||||
tool.km_read = true;
|
||||
hekto_read_kilometrage();
|
||||
}
|
||||
auto const chainage_of = [&](int const Hectometres) { return tool.origin + tool.growth * (Hectometres / 10.0 - tool.km) * 1000.0; };
|
||||
for (auto &post : tool.found)
|
||||
{
|
||||
post.expected = chainage_of(post.hectometres);
|
||||
post.error = post.chainage - post.expected;
|
||||
post.outside = true;
|
||||
}
|
||||
auto const km_at = [&](double const Chainage) { return tool.km + tool.growth * (Chainage - tool.origin) / 1000.0; };
|
||||
auto const low{std::max(0, static_cast<int>(std::ceil(std::min(km_at(0.0), km_at(length)) * 10.0 - 1e-6)))};
|
||||
auto const high{static_cast<int>(std::floor(std::max(km_at(0.0), km_at(length)) * 10.0 + 1e-6))};
|
||||
for (int hectometres = low; hectometres <= high && tool.posts.size() < 5000; ++hectometres)
|
||||
{
|
||||
hekto_post post;
|
||||
post.hectometres = hectometres;
|
||||
post.chainage = chainage_of(hectometres);
|
||||
if (post.chainage < 0.0 || post.chainage > length)
|
||||
continue;
|
||||
auto const axis{editor_track::sampled_position(tool.samples, post.chainage)};
|
||||
auto const growing{sampled_direction(tool.samples, post.chainage) * static_cast<double>(tool.growth)};
|
||||
auto const place = [&](hekto_post &Post) {
|
||||
auto const axis{editor_track::sampled_position(tool.samples, Post.chainage)};
|
||||
auto const growing{sampled_direction(tool.samples, Post.chainage) * static_cast<double>(Post.growth)};
|
||||
glm::dvec2 const left{-growing.y, growing.x};
|
||||
// alternately: the even hectometres on the right, the odd ones on the left of the growing kilometrage
|
||||
auto const side{tool.side != 0 ? tool.side : (hectometres % 2 == 0 ? 1 : -1)};
|
||||
auto const side{tool.side != 0 ? tool.side : (Post.hectometres % 2 == 0 ? 1 : -1)};
|
||||
auto const planar{plan_of(axis) + left * (side * tool.offset)};
|
||||
post.position = m_ground.placement_on_ground({planar.x, axis.y, planar.y});
|
||||
post.yaw = std::fmod(heading_of(growing) + tool.turn, 360.0);
|
||||
// of the posts with this number the one nearest to the place stands for it, the others are duplicates. it stands wrong
|
||||
// when it's farther from the place than allowed: along the line, across it, or on the other side
|
||||
auto best{std::numeric_limits<double>::max()};
|
||||
for (int i = 0; i < static_cast<int>(tool.found.size()); ++i)
|
||||
Post.position = m_ground.placement_on_ground({planar.x, axis.y, planar.y});
|
||||
Post.yaw = std::fmod(heading_of(growing) + tool.turn, 360.0);
|
||||
tool.posts.push_back(Post);
|
||||
};
|
||||
auto const *axis{tool.line.empty() ? nullptr : kilometrage::axis_of(tool.line)};
|
||||
if (axis != nullptr)
|
||||
{
|
||||
// the hectometres of the kilometrage of the line, the jumps in it too
|
||||
double km{0.0};
|
||||
if (kilometrage::km_at(tool.line, tool.point, km))
|
||||
tool.km = std::round(km * 1000.0) / 1000.0;
|
||||
tool.growth = kilometrage::growth_at(tool.line, tool.point, sampled_direction(tool.samples, tool.origin)) < 0 ? -1 : 1;
|
||||
for (auto const &hectometre : kilometrage::hectometres(*axis))
|
||||
{
|
||||
auto &found{tool.found[i]};
|
||||
if (found.hectometres != hectometres)
|
||||
hekto_post post;
|
||||
post.hectometres = hectometre.number;
|
||||
post.chainage = project(tool.samples, hectometre.at, distance);
|
||||
if (distance > kLineCorridor || post.chainage <= 0.0 || post.chainage >= length || hectometre.number < 0 || tool.posts.size() >= 5000)
|
||||
continue;
|
||||
found.outside = false;
|
||||
found.distance = plan_distance(found.post.location, post.position);
|
||||
if (found.distance < best)
|
||||
post.growth = glm::dot(hectometre.rising, sampled_direction(tool.samples, post.chainage)) < 0.0 ? -1 : 1;
|
||||
place(post);
|
||||
}
|
||||
std::sort(tool.posts.begin(), tool.posts.end(), [](hekto_post const &A, hekto_post const &B) { return A.chainage < B.chainage; });
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const km_at = [&](double const Chainage) { return tool.km + tool.growth * (Chainage - tool.origin) / 1000.0; };
|
||||
auto const low{std::max(0, static_cast<int>(std::ceil(std::min(km_at(0.0), km_at(length)) * 10.0 - 1e-6)))};
|
||||
auto const high{static_cast<int>(std::floor(std::max(km_at(0.0), km_at(length)) * 10.0 + 1e-6))};
|
||||
for (int hectometres = low; hectometres <= high && tool.posts.size() < 5000; ++hectometres)
|
||||
{
|
||||
hekto_post post;
|
||||
post.hectometres = hectometres;
|
||||
post.chainage = tool.origin + tool.growth * (hectometres / 10.0 - tool.km) * 1000.0;
|
||||
post.growth = tool.growth;
|
||||
if (post.chainage < 0.0 || post.chainage > length)
|
||||
continue;
|
||||
place(post);
|
||||
}
|
||||
}
|
||||
// each post standing goes with the place of its number nearest to it; of the posts going with a place the one nearest to it
|
||||
// stands for it, the others are duplicates. it stands wrong when it's farther from the place than allowed: along the line,
|
||||
// across it, or on the other side
|
||||
for (auto &found : tool.found)
|
||||
{
|
||||
found.outside = true;
|
||||
found.place = -1;
|
||||
for (int i = 0; i < static_cast<int>(tool.posts.size()); ++i)
|
||||
{
|
||||
auto const &post{tool.posts[i]};
|
||||
if (post.hectometres != found.hectometres)
|
||||
continue;
|
||||
auto const distance{plan_distance(found.post.location, post.position)};
|
||||
if (found.place < 0 || distance < found.distance)
|
||||
{
|
||||
best = found.distance;
|
||||
post.standing = i;
|
||||
found.outside = false;
|
||||
found.place = i;
|
||||
found.distance = distance;
|
||||
found.expected = post.chainage;
|
||||
found.error = found.chainage - post.chainage;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < static_cast<int>(tool.found.size()); ++i)
|
||||
{
|
||||
auto &found{tool.found[i]};
|
||||
if (found.hectometres != hectometres)
|
||||
continue;
|
||||
found.duplicate = i != post.standing;
|
||||
found.wrong = false == found.duplicate && found.distance > tool.tolerance;
|
||||
}
|
||||
tool.posts.push_back(post);
|
||||
}
|
||||
for (int i = 0; i < static_cast<int>(tool.found.size()); ++i)
|
||||
{
|
||||
auto const &found{tool.found[i]};
|
||||
if (found.place < 0)
|
||||
continue;
|
||||
auto &post{tool.posts[found.place]};
|
||||
if (post.standing < 0 || found.distance < tool.found[post.standing].distance)
|
||||
post.standing = i;
|
||||
}
|
||||
for (int i = 0; i < static_cast<int>(tool.found.size()); ++i)
|
||||
{
|
||||
auto &found{tool.found[i]};
|
||||
found.duplicate = found.place >= 0 && tool.posts[found.place].standing != i;
|
||||
found.wrong = found.place >= 0 && false == found.duplicate && found.distance > tool.tolerance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -576,21 +613,40 @@ void hekto_tool::render_options()
|
||||
if (Changed)
|
||||
tool.dirty = true;
|
||||
};
|
||||
if (begin_fields("##hektokm", 0.45f))
|
||||
if (false == tool.line.empty())
|
||||
{
|
||||
field_row("Kilometre at the point (km)");
|
||||
changed(ImGui::InputDouble("##hektokilometre", &tool.km, 0.0, 0.0, "%.3f"));
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
if (ImGui::Button(STR_C("Read from the posts"), ImVec2(-FLT_MIN, 0.0f)))
|
||||
ImGui::TextWrapped("%s", format(STR_C("The km of line %s, as the Kilometrage tool sets them, its jumps too: km %s at the point"), tool.line.c_str(), kilometrage::text(tool.km).c_str()).c_str());
|
||||
if (ImGui::SmallButton(STR_C("Give the km here instead")))
|
||||
{
|
||||
tool.own_km = true;
|
||||
tool.km_read = false;
|
||||
tool.dirty = true;
|
||||
}
|
||||
ImGui::EndTable();
|
||||
item_tooltip("The posts go by the km given at the point and the way it grows, without the jumps of the line");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (false == tool.line_set.empty() && ImGui::SmallButton(format(STR_C("Follow the km of line %s"), tool.line_set.c_str()).c_str()))
|
||||
{
|
||||
tool.own_km = false;
|
||||
tool.dirty = true;
|
||||
}
|
||||
if (begin_fields("##hektokm", 0.45f))
|
||||
{
|
||||
field_row("Kilometre at the point (km)");
|
||||
changed(ImGui::InputDouble("##hektokilometre", &tool.km, 0.0, 0.0, "%.3f"));
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
if (ImGui::Button(STR_C("Read from the posts"), ImVec2(-FLT_MIN, 0.0f)))
|
||||
{
|
||||
tool.km_read = false;
|
||||
tool.dirty = true;
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::TextDisabled("%s", STR_C("The kilometrage grows"));
|
||||
changed(segmented("growth", tool.growth, {{1, STR_C("along the line")}, {-1, STR_C("against it")}}));
|
||||
}
|
||||
ImGui::TextDisabled("%s", STR_C("The kilometrage grows"));
|
||||
changed(segmented("growth", tool.growth, {{1, STR_C("along the line")}, {-1, STR_C("against it")}}));
|
||||
ImGui::TextDisabled("%s", STR_C("Side, looking where it grows"));
|
||||
changed(segmented("side", tool.side, {{1, STR_C("on the right")}, {-1, STR_C("on the left")}, {0, STR_C("alternately"), "The even hectometres on the right, the odd ones on the left"}}));
|
||||
if (ImGui::TreeNode(STR_C("More settings")))
|
||||
@@ -1056,6 +1112,7 @@ editor_selftest_result hekto_tool::selftest(std::string const &Command, std::ist
|
||||
auto &tool{m_hekto};
|
||||
if (values.count("reach"))
|
||||
tool.reach = std::stod(values["reach"]);
|
||||
tool.own_km = values["own"] == "1";
|
||||
tool.dirty = true;
|
||||
hekto_update();
|
||||
if (values.count("km"))
|
||||
@@ -1067,7 +1124,10 @@ editor_selftest_result hekto_tool::selftest(std::string const &Command, std::ist
|
||||
tool.dirty = true;
|
||||
hekto_update();
|
||||
auto const missing{std::count_if(tool.posts.begin(), tool.posts.end(), [](hekto_post const &Post) { return Post.standing < 0; })};
|
||||
WriteLog(format("SELFTEST hekto: km %.3f growth %d, %zu posts along %.0f m, %d to place, %zu standing. %s", tool.km, tool.growth, tool.posts.size(), tool.samples.empty() ? 0.0 : tool.samples.back().chainage, static_cast<int>(missing), tool.found.size(), tool.status.c_str()));
|
||||
auto const wrong{std::count_if(tool.found.begin(), tool.found.end(), [](hekto_found const &Post) { return Post.wrong; })};
|
||||
auto const duplicates{std::count_if(tool.found.begin(), tool.found.end(), [](hekto_found const &Post) { return Post.duplicate; })};
|
||||
WriteLog(format("SELFTEST hekto: line %s km %.3f growth %d, %zu posts along %.0f m, %d to place, %zu standing, %d wrong, %d duplicate. %s", tool.line.empty() ? "-" : tool.line.c_str(), tool.km, tool.growth, tool.posts.size(), tool.samples.empty() ? 0.0 : tool.samples.back().chainage, static_cast<int>(missing), tool.found.size(),
|
||||
static_cast<int>(wrong), static_cast<int>(duplicates), tool.status.c_str()));
|
||||
for (std::size_t i = 0; i < tool.posts.size() && i < 4; ++i)
|
||||
{
|
||||
auto const &post{tool.posts[i]};
|
||||
@@ -1076,10 +1136,17 @@ editor_selftest_result hekto_tool::selftest(std::string const &Command, std::ist
|
||||
auto const direction{editor_track::sampled_position(tool.samples, post.chainage + 1.0) - axis};
|
||||
glm::dvec2 const offset{post.position.x - axis.x, post.position.z - axis.z};
|
||||
lateral = glm::length(offset);
|
||||
auto const right{(direction.x * offset.y - direction.z * offset.x) * tool.growth >= 0.0};
|
||||
auto const right{(direction.x * offset.y - direction.z * offset.x) * post.growth >= 0.0};
|
||||
WriteLog(format("SELFTEST hekto post %d.%d at %.1f m, %.2f m from the axis, %s of the growing kilometrage, at %.1f %.1f %.1f", post.hectometres / 10, post.hectometres % 10, post.chainage, lateral, right ? "right" : "left", post.position.x, post.position.y,
|
||||
post.position.z));
|
||||
}
|
||||
if (values["list"] == "1")
|
||||
{
|
||||
std::string list;
|
||||
for (auto const &post : tool.posts)
|
||||
list += format(" %d@%.0f", post.hectometres, post.chainage);
|
||||
WriteLog("SELFTEST hekto posts:" + list);
|
||||
}
|
||||
if (values["place"] == "1")
|
||||
{
|
||||
hekto_place();
|
||||
|
||||
@@ -41,6 +41,7 @@ class hekto_tool final : public editor_tool
|
||||
double chainage{0.0};
|
||||
glm::dvec3 position{0.0};
|
||||
double yaw{0.0};
|
||||
int growth{1}; // 1: the kilometrage grows along the line there, -1: against
|
||||
int standing{-1}; // post already there with this number
|
||||
};
|
||||
struct hekto_found
|
||||
@@ -54,6 +55,7 @@ class hekto_tool final : public editor_tool
|
||||
bool wrong{false};
|
||||
bool duplicate{false}; // another post with the same number stands nearer to its place
|
||||
bool outside{false}; // its number belongs past the ends of the line
|
||||
int place{-1}; // of the posts, the one with its number nearest to it
|
||||
};
|
||||
struct hekto_state
|
||||
{
|
||||
@@ -62,6 +64,9 @@ class hekto_tool final : public editor_tool
|
||||
double km{0.0};
|
||||
bool km_read{false}; // the kilometrage was read from the posts already standing
|
||||
int growth{1}; // 1: grows along the line, -1: against
|
||||
std::string line; // of the kilometrage set for the line in the Kilometrage tool the posts follow, empty for the one given here
|
||||
std::string line_set; // the line the Kilometrage tool sets the kilometrage of at the point, empty for none
|
||||
bool own_km{false}; // the kilometrage given here, even where the line has one set
|
||||
int side{1}; // 1: to the right of the growing kilometrage, -1: to the left, 0: alternately
|
||||
double offset{3.0}; // m from the axis
|
||||
int style{0}; // nowy, stary, zgnity, mixed
|
||||
|
||||
@@ -927,6 +927,86 @@ bool km_at(std::string const &Line, glm::dvec3 const &Point, double &Km, double
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string line_at(glm::dvec3 const &Point, double const Reach)
|
||||
{
|
||||
std::string result;
|
||||
auto nearest{Reach};
|
||||
for (auto const &line : lines())
|
||||
if (auto const *found{axis_of(line)}; found != nullptr)
|
||||
{
|
||||
double gap{0.0};
|
||||
chainage_at(*found, Point, gap);
|
||||
if (gap < nearest)
|
||||
{
|
||||
nearest = gap;
|
||||
result = line;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int growth_at(std::string const &Line, glm::dvec3 const &Point, glm::dvec2 const &Way, double const Reach)
|
||||
{
|
||||
auto const *found{axis_of(Line)};
|
||||
if (found == nullptr)
|
||||
return 0;
|
||||
double gap{0.0};
|
||||
auto const chainage{chainage_at(*found, Point, gap)};
|
||||
if (gap > Reach)
|
||||
return 0;
|
||||
return glm::dot(direction_on(*found, chainage) * static_cast<double>(found->growth), Way) >= 0.0 ? 1 : -1;
|
||||
}
|
||||
|
||||
std::vector<hectometre> hectometres(axis const &Axis)
|
||||
{
|
||||
std::vector<hectometre> result;
|
||||
std::vector<double> jumps;
|
||||
for (auto const &anchor : Axis.anchors)
|
||||
if (std::abs(anchor.after - anchor.before) >= 1e-6)
|
||||
jumps.push_back(anchor.chainage);
|
||||
auto const along = [&](std::vector<glm::dvec3> const &Points, std::vector<double> const &Km, std::vector<double> const &Chainage) {
|
||||
for (std::size_t i = 1; i < Points.size(); ++i)
|
||||
{
|
||||
auto const from{std::min(Chainage[i - 1], Chainage[i])};
|
||||
auto const to{std::max(Chainage[i - 1], Chainage[i])};
|
||||
if (std::any_of(jumps.begin(), jumps.end(), [&](double const Jump) { return Jump >= from - 1e-6 && Jump <= to + 1e-6; }))
|
||||
continue;
|
||||
auto const k0{Km[i - 1]};
|
||||
auto const k1{Km[i]};
|
||||
if (std::abs(k1 - k0) < 1e-9)
|
||||
continue;
|
||||
auto way{plan_of(Points[i] - Points[i - 1])};
|
||||
way = glm::length(way) > 1e-9 ? glm::normalize(way) : glm::dvec2{0.0, 1.0};
|
||||
auto const first{static_cast<int>(std::floor(std::min(k0, k1) * 10.0 + 1e-9)) + 1};
|
||||
auto const last{static_cast<int>(std::floor(std::max(k0, k1) * 10.0 + 1e-9))};
|
||||
for (auto number = first; number <= last && number < first + 10; ++number)
|
||||
result.push_back({glm::mix(Points[i - 1], Points[i], (number / 10.0 - k0) / (k1 - k0)), k1 > k0 ? way : -way, number});
|
||||
}
|
||||
};
|
||||
// at a jump the post of the km on from it, as the posts of a line built anew begin there, else of the km the jump is reached at
|
||||
for (auto const &anchor : Axis.anchors)
|
||||
{
|
||||
if (std::abs(anchor.after - anchor.before) < 1e-6)
|
||||
continue;
|
||||
auto const round = [](double const Km) { return std::abs(Km * 10.0 - std::round(Km * 10.0)) < 1e-4; };
|
||||
auto const km{round(anchor.after) ? anchor.after : anchor.before};
|
||||
if (round(km))
|
||||
result.push_back({point_on(Axis, anchor.chainage), direction_on(Axis, anchor.chainage) * static_cast<double>(Axis.growth), static_cast<int>(std::lround(km * 10.0))});
|
||||
}
|
||||
std::vector<double> km;
|
||||
for (auto const chainage : Axis.chainage)
|
||||
km.push_back(km_on(Axis, chainage));
|
||||
along(Axis.points, km, Axis.chainage);
|
||||
for (auto const &side : Axis.sides)
|
||||
{
|
||||
km.clear();
|
||||
for (auto const distance : side.along)
|
||||
km.push_back(km_on(Axis, side, distance));
|
||||
along(side.points, km, side.chainage);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TTrack *track_near(glm::dvec3 const &Point, double const Reach)
|
||||
{
|
||||
TTrack *best{nullptr};
|
||||
|
||||
@@ -127,6 +127,20 @@ glm::dvec2 direction_on(axis const &Axis, double const Chainage);
|
||||
double km_on(axis const &Axis, axis::side const &Side, double const Along);
|
||||
// the km of the line at the point, when it lies within the reach of the axis
|
||||
bool km_at(std::string const &Line, glm::dvec3 const &Point, double &Km, double const Reach = 30.0);
|
||||
// the line whose axis, or a track running apart from it, passes nearest to the point within the reach, empty for none
|
||||
std::string line_at(glm::dvec3 const &Point, double const Reach = 30.0);
|
||||
// the km of the line rise along the way at the point: 1, against it: -1, 0 where the axis doesn't reach
|
||||
int growth_at(std::string const &Line, glm::dvec3 const &Point, glm::dvec2 const &Way, double const Reach = 30.0);
|
||||
// a hectometre the km of a line pass
|
||||
struct hectometre
|
||||
{
|
||||
glm::dvec3 at{0.0};
|
||||
glm::dvec2 rising{0.0, 1.0}; // the way the km rise there, in the plan
|
||||
int number{0}; // of the hectometres from km 0, 1043 for km 104,3
|
||||
};
|
||||
// the hectometres along the axis and along the tracks running apart from it; at a jump the one of the km on from it, else of
|
||||
// the km it is reached at, whichever is a whole hectometre
|
||||
std::vector<hectometre> hectometres(axis const &Axis);
|
||||
// the track nearest to the point in the plan within the reach, nullptr for none
|
||||
TTrack *track_near(glm::dvec3 const &Point, double const Reach);
|
||||
// the path of the track nearest to the point in the plan, On: the point of it nearest
|
||||
|
||||
@@ -10780,3 +10780,15 @@ msgstr "Przez stację linia biegnie tym torem, a nie po prostych torach rozjazd
|
||||
msgid "%s: this way"
|
||||
msgstr "%s: tędy"
|
||||
|
||||
msgid "The km of line %s, as the Kilometrage tool sets them, its jumps too: km %s at the point"
|
||||
msgstr "Kilometraż linii %s z narzędzia Kilometraż, razem z uskokami: km %s w punkcie"
|
||||
|
||||
msgid "Give the km here instead"
|
||||
msgstr "Podaj kilometr tutaj"
|
||||
|
||||
msgid "The posts go by the km given at the point and the way it grows, without the jumps of the line"
|
||||
msgstr "Słupki pójdą według kilometra podanego w punkcie i kierunku, w którym rośnie, bez uskoków linii"
|
||||
|
||||
msgid "Follow the km of line %s"
|
||||
msgstr "Według kilometrażu linii %s"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user