summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2025-05-10 13:50:08 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2025-05-10 13:50:08 +0100
commitdf9b9bc264e0bf12e99b447be7903050c822692d (patch)
treee92ddbfb0c61cc94131512ed2d757df798157f72 /test
parentNew genCurveDef for 2 directions (diff)
downloadilt-df9b9bc264e0bf12e99b447be7903050c822692d.tar.bz2
ilt-df9b9bc264e0bf12e99b447be7903050c822692d.tar.xz
ilt-df9b9bc264e0bf12e99b447be7903050c822692d.zip
Add new network building interface
Imperfect, matches some legacy interface in places, has some TODO notes.
Diffstat (limited to 'test')
-rw-r--r--test/test-network.cpp238
1 files changed, 216 insertions, 22 deletions
diff --git a/test/test-network.cpp b/test/test-network.cpp
index 1c91981..2b4b958 100644
--- a/test/test-network.cpp
+++ b/test/test-network.cpp
@@ -23,10 +23,13 @@ BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase);
namespace {
struct TestLinkS;
+ struct TestLinkC;
struct TestLink : public virtual Link {
using StraightLink = TestLinkS;
- using CurveLink = TestLinkS;
+ using CurveLink = TestLinkC;
+
+ struct Vertex { };
};
struct TestLinkS : public TestLink, public LinkStraight {
@@ -35,15 +38,34 @@ namespace {
{
}
- TestLinkS(NetworkLinkHolder<TestLinkS> &, Node::Ptr nodeA, Node::Ptr nodeB, RelativePosition2D difference) :
- Link {{.node = std::move(nodeA), .dir = 0}, {.node = std::move(nodeB), .dir = pi}, glm::length(difference)}
+ TestLinkS(NetworkLinkHolder<TestLinkS> & network, Node::Ptr nodeA, Node::Ptr nodeB,
+ RelativePosition2D difference) :
+ TestLinkS {network, std::move(nodeA), std::move(nodeB), glm::length(difference), vector_yaw(difference)}
{
}
- struct Vertex { };
+ TestLinkS(NetworkLinkHolder<TestLinkS> &, Node::Ptr nodeA, Node::Ptr nodeB, float length, Angle dirForward) :
+ Link {{.node = std::move(nodeA), .dir = dirForward},
+ {.node = std::move(nodeB), .dir = normalize(pi + dirForward)}, length}
+ {
+ }
+ };
- TestLinkS(NetworkLinkHolder<TestLinkS> &, Node::Ptr nodeA, Node::Ptr nodeB, float length) :
- Link {{.node = std::move(nodeA), .dir = 0}, {.node = std::move(nodeB), .dir = pi}, length}
+ struct TestLinkC : public TestLink, public LinkCurve {
+ TestLinkC(NetworkLinkHolder<TestLinkC> & network, const Node::Ptr & nodeA, const Node::Ptr & nodeB,
+ GlobalPosition2D centre) :
+ TestLinkC {network, nodeA, nodeB, centre,
+ {vector_yaw(difference(nodeA->pos.xy(), centre)), vector_yaw(difference(nodeB->pos.xy(), centre))}}
+ {
+ }
+
+ TestLinkC(NetworkLinkHolder<TestLinkC> &, const Node::Ptr & nodeA, const Node::Ptr & nodeB,
+ GlobalPosition2D centre, Arc arc) :
+ Link {{.node = nodeA, .dir = normalize(arc.first + half_pi)},
+ {.node = nodeB, .dir = normalize(arc.second - half_pi)},
+ // Wrong, but OK for testing, just 10% longer than a straight line
+ (glm::length(difference(nodeA->pos, nodeB->pos)) * 1.1F)},
+ LinkCurve {centre || nodeA->pos.z, glm::length(difference(centre, nodeA->pos.xy())), arc}
{
}
};
@@ -53,24 +75,11 @@ namespace {
}
template<> NetworkLinkHolder<TestLinkS>::NetworkLinkHolder() = default;
+template<> NetworkLinkHolder<TestLinkC>::NetworkLinkHolder() = default;
namespace {
- struct TestNetwork : public NetworkOf<TestLink, TestLinkS> {
- TestNetwork() : NetworkOf<TestLink, TestLinkS> {RESDIR "rails.jpg"}
- {
- // 0 1 2
- // p000 <-> p100 <-> p200 <-> p300
- // \ | /
- // \ 5 /
- // 3 | 4
- // \-> p110 <-/
- addLink<TestLinkS>(P000, P100, 1.F);
- addLink<TestLinkS>(P100, P200, 1.F);
- addLink<TestLinkS>(P200, P300, 1.F);
- addLink<TestLinkS>(P000, P110, 2.F);
- addLink<TestLinkS>(P200, P110, 2.F);
- addLink<TestLinkS>(P100, P110, 1.F);
- }
+ struct EmptyNetwork : public NetworkOf<TestLink, TestLinkS, TestLinkC> {
+ EmptyNetwork() : NetworkOf<TestLink, TestLinkS, TestLinkC> {RESDIR "rails.jpg"} { }
void
render(const SceneShader &, const Frustum &) const override
@@ -90,6 +99,24 @@ namespace {
}
};
+ struct TestNetwork : public EmptyNetwork {
+ TestNetwork()
+ {
+ // 0 1 2
+ // p000 <-> p100 <-> p200 <-> p300
+ // \ | /
+ // \ 5 /
+ // 3 | 4
+ // \-> p110 <-/
+ addLink<TestLinkS>(P000, P100, 1.F, 0);
+ addLink<TestLinkS>(P100, P200, 1.F, 0);
+ addLink<TestLinkS>(P200, P300, 1.F, 0);
+ addLink<TestLinkS>(P000, P110, 2.F, 0);
+ addLink<TestLinkS>(P200, P110, 2.F, 0);
+ addLink<TestLinkS>(P100, P110, 1.F, 0);
+ }
+ };
+
constexpr auto VALID_NODES = std::array<GlobalPosition3D, 4>({
P000,
P100,
@@ -224,6 +251,173 @@ BOOST_AUTO_TEST_CASE(RouteToDownStream3to300)
BOOST_AUTO_TEST_SUITE_END()
+BOOST_FIXTURE_TEST_SUITE(en, EmptyNetwork)
+
+using GenCurveDefsData = std::tuple<GlobalPosition3D, GlobalPosition3D, Angle, GenCurveDef>;
+
+BOOST_DATA_TEST_CASE(GenCurveDefs,
+ boost::unit_test::data::make<GenCurveDefsData>({
+ {{0, 0, 0}, {1000, 1000, 0}, 0, {{1000, 1000, 0}, {0, 0, 0}, {1000, 0}}},
+ {{0, 0, 0}, {-1000, 1000, 0}, 0, {{0, 0, 0}, {-1000, 1000, 0}, {-1000, 0}}},
+ {{0, 0, 0}, {0, 1000, 0}, half_pi, {{0, 0, 0}, {0, 1000, 0}, {0, 500}}},
+ {{0, 0, 0}, {0, 1000, 0}, -half_pi, {{0, 1000, 0}, {0, 0, 0}, {0, 500}}},
+ }),
+ start, end, startDir, exp)
+{
+ BOOST_CHECK_EQUAL(genCurveDef(start, end, startDir), exp);
+}
+
+BOOST_AUTO_TEST_CASE(NetworkCreateStraight)
+{
+ const auto link = create(CreationDefinition {
+ .fromEnd = {.position = {0, 0, 0}, .direction = {}},
+ .toEnd = {.position = {0, 1000, 0}, .direction = {}},
+ });
+ BOOST_REQUIRE_EQUAL(link.size(), 1);
+ BOOST_CHECK(links.empty());
+ BOOST_CHECK(nodes.empty());
+
+ BOOST_CHECK_IF(straight, std::dynamic_pointer_cast<TestLinkS>(link.front())) {
+ BOOST_CHECK_CLOSE(straight->length, 1000, 1);
+ BOOST_CHECK_CLOSE_VECI(straight->ends.front().node->pos, GlobalPosition3D(0, 0, 0));
+ BOOST_CHECK_CLOSE_VECI(straight->ends.back().node->pos, GlobalPosition3D(0, 1000, 0));
+ }
+
+ add(nullptr, link.front());
+ BOOST_CHECK_EQUAL(links.size(), 1);
+ BOOST_CHECK_EQUAL(nodes.size(), 2);
+}
+
+BOOST_AUTO_TEST_CASE(NetworkCreateExtendingCurve)
+{
+ const auto link = create(CreationDefinition {
+ .fromEnd = {.position = {0, 0, 0}, .direction = half_pi},
+ .toEnd = {.position = {0, 1000, 0}, .direction = {}},
+ });
+ BOOST_REQUIRE_EQUAL(link.size(), 1);
+ BOOST_CHECK(links.empty());
+ BOOST_CHECK(nodes.empty());
+
+ BOOST_CHECK_IF(curve, std::dynamic_pointer_cast<TestLinkC>(link.front())) {
+ BOOST_CHECK_CLOSE(curve->length, 1100, 1);
+ BOOST_CHECK_CLOSE(curve->radius, 500, 1);
+ BOOST_CHECK_CLOSE_VECI(curve->centreBase, GlobalPosition3D(0, 500, 0));
+ BOOST_CHECK_CLOSE_VECI(curve->ends.front().node->pos, GlobalPosition3D(0, 0, 0));
+ BOOST_CHECK_CLOSE(curve->ends.front().dir, -half_pi, 1);
+ BOOST_CHECK_CLOSE_VECI(curve->ends.back().node->pos, GlobalPosition3D(0, 1000, 0));
+ BOOST_CHECK_CLOSE(curve->ends.back().dir, -half_pi, 1);
+ }
+
+ add(nullptr, link.front());
+ BOOST_CHECK_EQUAL(links.size(), 1);
+ BOOST_CHECK_EQUAL(nodes.size(), 2);
+}
+
+BOOST_AUTO_TEST_CASE(NetworkCreateExtendeeCurve)
+{
+ const auto link = create(CreationDefinition {
+ .fromEnd = {.position = {0, 0, 0}, .direction = {}},
+ .toEnd = {.position = {0, 1000, 0}, .direction = half_pi},
+ });
+ BOOST_REQUIRE_EQUAL(link.size(), 1);
+ BOOST_CHECK(links.empty());
+ BOOST_CHECK(nodes.empty());
+
+ BOOST_CHECK_IF(curve, std::dynamic_pointer_cast<TestLinkC>(link.front())) {
+ BOOST_CHECK_CLOSE(curve->length, 1100, 1);
+ BOOST_CHECK_CLOSE(curve->radius, 500, 1);
+ BOOST_CHECK_CLOSE_VECI(curve->centreBase, GlobalPosition3D(0, 500, 0));
+ BOOST_CHECK_CLOSE_VECI(curve->ends.front().node->pos, GlobalPosition3D(0, 0, 0));
+ BOOST_CHECK_CLOSE(curve->ends.front().dir, -half_pi, 1);
+ BOOST_CHECK_CLOSE_VECI(curve->ends.back().node->pos, GlobalPosition3D(0, 1000, 0));
+ BOOST_CHECK_CLOSE(curve->ends.back().dir, -half_pi, 1);
+ }
+
+ add(nullptr, link.front());
+ BOOST_CHECK_EQUAL(links.size(), 1);
+ BOOST_CHECK_EQUAL(nodes.size(), 2);
+}
+
+BOOST_AUTO_TEST_CASE(NetworkCreateBiarcPair)
+{
+ const auto link = create(CreationDefinition {
+ .fromEnd = {.position = {0, 0, 0}, .direction = pi},
+ .toEnd = {.position = {1000, 1000, 0}, .direction = 0},
+ });
+ BOOST_REQUIRE_EQUAL(link.size(), 2);
+ BOOST_CHECK(links.empty());
+ BOOST_CHECK(nodes.empty());
+
+ BOOST_CHECK_IF(firstCurve, std::dynamic_pointer_cast<TestLinkC>(link.front())) {
+ BOOST_CHECK_CLOSE(firstCurve->length, 777, 1);
+ BOOST_CHECK_CLOSE(firstCurve->radius, 500, 1);
+ BOOST_CHECK_CLOSE_VECI(firstCurve->centreBase, GlobalPosition3D(500, 0, 0));
+ BOOST_CHECK_CLOSE_VECI(firstCurve->ends.front().node->pos, GlobalPosition3D(0, 0, 0));
+ BOOST_CHECK_CLOSE(firstCurve->ends.front().dir, 0, 1);
+ BOOST_CHECK_CLOSE_VECI(firstCurve->ends.back().node->pos, GlobalPosition3D(500, 500, 0));
+ BOOST_CHECK_CLOSE(firstCurve->ends.back().dir, -half_pi, 1);
+ }
+
+ BOOST_CHECK_IF(secondCurve, std::dynamic_pointer_cast<TestLinkC>(link.back())) {
+ BOOST_CHECK_CLOSE(secondCurve->length, 777, 1);
+ BOOST_CHECK_CLOSE(secondCurve->radius, 500, 1);
+ BOOST_CHECK_CLOSE_VECI(secondCurve->centreBase, GlobalPosition3D(500, 1000, 0));
+ BOOST_CHECK_CLOSE_VECI(secondCurve->ends.front().node->pos, GlobalPosition3D(1000, 1000, 0));
+ BOOST_CHECK_CLOSE(secondCurve->ends.front().dir, pi, 1);
+ BOOST_CHECK_CLOSE_VECI(secondCurve->ends.back().node->pos, GlobalPosition3D(500, 500, 0));
+ BOOST_CHECK_CLOSE(secondCurve->ends.back().dir, half_pi, 1);
+ }
+
+ add(nullptr, link.front());
+ add(nullptr, link.back());
+ BOOST_CHECK_EQUAL(links.size(), 2);
+ BOOST_CHECK_EQUAL(nodes.size(), 3);
+ BOOST_CHECK_EQUAL(link.front()->ends.back().nexts.front().first.lock(), link.back());
+ BOOST_CHECK_EQUAL(link.back()->ends.back().nexts.front().first.lock(), link.front());
+}
+
+BOOST_AUTO_TEST_CASE(NetworkCreateBiarcPairEqTan)
+{
+ // This could be achieved with a single curve, but not there yet
+ const auto link = create(CreationDefinition {
+ .fromEnd = {.position = {0, 0, 0}, .direction = 0},
+ .toEnd = {.position = {1000, 0, 0}, .direction = 0},
+ });
+ BOOST_REQUIRE_EQUAL(link.size(), 2);
+ BOOST_CHECK(links.empty());
+ BOOST_CHECK(nodes.empty());
+
+ BOOST_CHECK_IF(firstCurve, std::dynamic_pointer_cast<TestLinkC>(link.front())) {
+ BOOST_CHECK_CLOSE_VECI(firstCurve->centreBase, GlobalPosition3D(500, 0, 0));
+ }
+
+ BOOST_CHECK_IF(secondCurve, std::dynamic_pointer_cast<TestLinkC>(link.back())) {
+ BOOST_CHECK_CLOSE_VECI(secondCurve->centreBase, GlobalPosition3D(500, 0, 0));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(NetworkCreateBiarcPairEqTanPerp)
+{
+ // This creates an equal pair of semi-circle arcs
+ const auto link = create(CreationDefinition {
+ .fromEnd = {.position = {0, 0, 0}, .direction = 0},
+ .toEnd = {.position = {1000, 0, 0}, .direction = pi},
+ });
+ BOOST_REQUIRE_EQUAL(link.size(), 2);
+ BOOST_CHECK(links.empty());
+ BOOST_CHECK(nodes.empty());
+
+ BOOST_CHECK_IF(firstCurve, std::dynamic_pointer_cast<TestLinkC>(link.front())) {
+ BOOST_CHECK_CLOSE_VECI(firstCurve->centreBase, GlobalPosition3D(250, 0, 0));
+ }
+
+ BOOST_CHECK_IF(secondCurve, std::dynamic_pointer_cast<TestLinkC>(link.back())) {
+ BOOST_CHECK_CLOSE_VECI(secondCurve->centreBase, GlobalPosition3D(750, 0, 0));
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
BOOST_FIXTURE_TEST_CASE(TestRailNetwork, RailLinks)
{
// 0 1 2