mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 22:54:54 +01:00
fix(editor): the heights from point to point broke the grade only at the bends of straights which stay bends, a curve traced or bends clicked close along a curve going at one grade from one of its ends to the other, attached there; and two tracks laid no longer meet at two heights where a point was clicked within 5 m of their joint, each end of a piece not cut there taking the height of its own stretch, not of the one the middle of the piece lies on (steps of 0.6 m on a steep grade in abc). Unit tests of the heights from point to point
This commit is contained in:
@@ -1409,6 +1409,9 @@ class editor_mode : public application_mode, private editor_track::observer, pri
|
||||
std::vector<lay_trace> traces;
|
||||
// the straights of a fixed direction the next bend slides along: from a free end, out of a curve traced
|
||||
std::vector<std::pair<glm::dvec3, glm::dvec3>> guides;
|
||||
// where the grade breaks from point to point: the bends kept as such, at the heights clicked; a curve traced, or bends made
|
||||
// one curve, goes at one grade from end to end
|
||||
std::vector<glm::dvec3> knots;
|
||||
};
|
||||
// lays new track through the clicked points, with no path needed to start from
|
||||
struct lay_tool
|
||||
|
||||
@@ -1029,7 +1029,7 @@ std::vector<segment_data> editor_mode::lay_pieces(std::vector<glm::dvec3> const
|
||||
if (EditorSettings.heights() == editorSettings::lay_heights::fitted)
|
||||
follow_ground(pieces, Points.front().y, grade0, Points.back().y, grade1, style);
|
||||
else
|
||||
ground_follow::follow_points(pieces, std::vector<glm::dvec3>(Points.begin() + 1, Points.end() - 1), {Points.front().y, grade0, Points.back().y, grade1});
|
||||
ground_follow::follow_points(pieces, plan.knots, {Points.front().y, grade0, Points.back().y, grade1});
|
||||
if (Plan != nullptr)
|
||||
*Plan = std::move(plan);
|
||||
return pieces;
|
||||
@@ -1279,6 +1279,18 @@ bool editor_mode::lay_line(std::vector<glm::dvec3> const &Points, std::vector<la
|
||||
Error = Plan.shape.errors.empty() ? std::string{STR_C("The track can't be laid through these points")} : Plan.shape.errors.front();
|
||||
return false;
|
||||
}
|
||||
// the grade breaks at the bends which stayed bends; along a curve, traced or made of bends, it goes on even from end to end
|
||||
for (std::size_t k = 0; k < design.vertices.size() && k < Plan.corners.size(); ++k)
|
||||
{
|
||||
if (Plan.corners[k] != 1)
|
||||
continue;
|
||||
for (auto const &bend : bends)
|
||||
if (bend.corner && glm::distance(plan_of(bend.position), design.vertices[k].position) < 1e-3)
|
||||
{
|
||||
Plan.knots.push_back(bend.position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1739,7 +1751,7 @@ void editor_mode::render_lay_ui()
|
||||
if (int heights{static_cast<int>(EditorSettings.heights())};
|
||||
segmented("layheights", heights,
|
||||
{{0, STR_C("Fitted"), "The grades fitted to the ground as Tracks onto the terrain fits them: vertical curves of the norms, the bumps of the ground gone past; the terrain is left as it is. On the terrain model the whole track laid in a row is fitted again at each click"},
|
||||
{1, STR_C("Point to point"), "Each point clicked at the height of the ground, an even grade between them: the grade changes only where you click"},
|
||||
{1, STR_C("Point to point"), "Each bend of the straights clicked at the height of the ground, an even grade between them: the grade changes only at the bends. A curve traced, or bends clicked close along a curve, goes at an even grade from one end of it to the other"},
|
||||
{2, STR_C("Flat"), "The track goes on at the height it's laid from, whatever the ground; the first point on the ground"}}))
|
||||
{
|
||||
EditorSettings.heights(static_cast<editorSettings::lay_heights>(heights));
|
||||
|
||||
@@ -427,10 +427,13 @@ void follow_points(std::vector<segment_data> &Pieces, std::vector<glm::dvec3> co
|
||||
knots.push_back(total);
|
||||
heights.push_back(Ends.height1);
|
||||
auto const last{knots.size() - 1};
|
||||
// the height at the chainage on the stretch Middle is on, an end of it taken at a knot
|
||||
// the height at the chainage on its stretch; at a knot itself on the one Middle is on, for the grade of the piece there. A piece
|
||||
// not cut at a knot too near its end lies on two stretches, each of its ends on its own
|
||||
auto const at = [&](double const Chainage, double const Middle, double &Grade) {
|
||||
std::size_t stretch{0};
|
||||
while (stretch + 1 < last && Middle > knots[stretch + 1])
|
||||
while (stretch + 1 < last && Chainage > knots[stretch + 1] + 1e-6)
|
||||
++stretch;
|
||||
if (stretch + 1 < last && std::abs(Chainage - knots[stretch + 1]) <= 1e-6 && Middle > knots[stretch + 1])
|
||||
++stretch;
|
||||
auto const span{knots[stretch + 1] - knots[stretch]};
|
||||
auto const even{(heights[stretch + 1] - heights[stretch]) / span};
|
||||
|
||||
@@ -11902,3 +11902,6 @@ msgstr "Dwie krzywe przejściowe, bez łuku"
|
||||
|
||||
msgid "The bend eased the way the lines are drawn: two transition curves meeting at the radius, with no arc between them and no cant; their lengths follow from the radius and the angle"
|
||||
msgstr "Załamanie wyokrąglone tak, jak projektuje się linie: dwie krzywe przejściowe stykające się przy promieniu, bez łuku między nimi i bez przechyłki; ich długości wynikają z promienia i kąta"
|
||||
|
||||
msgid "Each bend of the straights clicked at the height of the ground, an even grade between them: the grade changes only at the bends. A curve traced, or bends clicked close along a curve, goes at an even grade from one end of it to the other"
|
||||
msgstr "Każde kliknięte załamanie prostych na wysokości terenu, między nimi równe pochylenie: pochylenie zmienia się tylko na załamaniach. Łuk odrysowany albo załamania kliknięte gęsto wzdłuż łuku idą jednym pochyleniem od jego początku do końca"
|
||||
|
||||
@@ -17,6 +17,9 @@ add_executable(${UNIT_TESTS_NAME}
|
||||
editor_stubs.cpp
|
||||
# the geometry of the lines the track editor designs, standing on its own
|
||||
"${CMAKE_SOURCE_DIR}/editor/editorAlignment.cpp"
|
||||
# and the heights of the tracks laid
|
||||
"${CMAKE_SOURCE_DIR}/editor/editorGroundFollow.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/editor/editorProfile.cpp"
|
||||
${UNIT_TEST_CASES})
|
||||
|
||||
# the core library brings the game's build settings along
|
||||
|
||||
42
tests/unit/test_heights.cpp
Normal file
42
tests/unit/test_heights.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "stdafx.h"
|
||||
#include "doctest.h"
|
||||
#include "editor/editorGroundFollow.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
namespace {
|
||||
|
||||
segment_data straight(double const From, double const To) {
|
||||
segment_data piece;
|
||||
piece.points[segment_data::point::start] = {From, 0.0, 0.0};
|
||||
piece.points[segment_data::point::end] = {To, 0.0, 0.0};
|
||||
return piece;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("heights: from point to point the tracks meet at one height where a point is clicked just past a joint") {
|
||||
// three tracks of 40 m, the grade breaking 3 m past the first joint and 2 m short of the second one, steeply
|
||||
std::vector<segment_data> pieces{straight(0.0, 40.0), straight(40.0, 80.0), straight(80.0, 120.0)};
|
||||
auto const unknown{std::numeric_limits<double>::quiet_NaN()};
|
||||
|
||||
ground_follow::follow_points(pieces, {{43.0, -5.0, 0.0}, {78.0, 3.0, 0.0}}, {0.0, unknown, 0.0, unknown});
|
||||
|
||||
REQUIRE(pieces.size() >= 3);
|
||||
for (std::size_t i = 0; i + 1 < pieces.size(); ++i)
|
||||
CHECK(pieces[i].points[segment_data::point::end].y == doctest::Approx(pieces[i + 1].points[segment_data::point::start].y).epsilon(1e-9));
|
||||
CHECK(pieces.front().points[segment_data::point::start].y == doctest::Approx(0.0));
|
||||
CHECK(pieces.back().points[segment_data::point::end].y == doctest::Approx(0.0));
|
||||
}
|
||||
|
||||
TEST_CASE("heights: with no point between the ends the grade is even from one end to the other") {
|
||||
std::vector<segment_data> pieces{straight(0.0, 50.0), straight(50.0, 100.0)};
|
||||
auto const unknown{std::numeric_limits<double>::quiet_NaN()};
|
||||
|
||||
ground_follow::follow_points(pieces, {}, {10.0, unknown, 12.0, unknown});
|
||||
|
||||
REQUIRE(pieces.size() == 2);
|
||||
CHECK(pieces[0].points[segment_data::point::end].y == doctest::Approx(11.0));
|
||||
CHECK(pieces[1].points[segment_data::point::start].y == doctest::Approx(11.0));
|
||||
}
|
||||
Reference in New Issue
Block a user