From d8ee91b44e31cf1500926d37b7391e8c94bbf14a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 21 Dec 2024 03:30:18 +0000 Subject: Fix calculating radius and length of curved links --- test/test-network.cpp | 57 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 20 deletions(-) (limited to 'test/test-network.cpp') diff --git a/test/test-network.cpp b/test/test-network.cpp index 59eebae..ce25429 100644 --- a/test/test-network.cpp +++ b/test/test-network.cpp @@ -47,8 +47,8 @@ struct TestLinkS : public TestLink, public LinkStraight { } }; -constexpr GlobalPosition3D p000 {0, 0, 0}, p100 {10000, 0, 0}, p200 {20000, 0, 0}, p300 {30000, 0, 0}; -constexpr GlobalPosition3D p110 {10000, 10000, 0}; +constexpr GlobalPosition3D p000 {0, 0, 500}, p100 {10500, 0, 1000}, p200 {20100, 0, 2000}, p300 {30700, 0, 3000}; +constexpr GlobalPosition3D p110 {10300, 10400, 4000}; template<> NetworkLinkHolder::NetworkLinkHolder() = default; @@ -208,6 +208,14 @@ BOOST_AUTO_TEST_CASE(routeTo_downStream_3to300) BOOST_AUTO_TEST_SUITE_END() +namespace std { + std::ostream & + operator<<(std::ostream & s, const Link::End & e) + { + return s << std::format("End[dir: {}, loc: ({}, {}, {})]", e.dir, e.node->pos.x, e.node->pos.y, e.node->pos.z); + } +} + BOOST_FIXTURE_TEST_CASE(test_rail_network, RailLinks) { // 0 1 2 @@ -221,7 +229,7 @@ BOOST_FIXTURE_TEST_CASE(test_rail_network, RailLinks) // -------- auto l0 = addLinksBetween(p000, p100); BOOST_CHECK(dynamic_cast(l0.get())); - BOOST_CHECK_EQUAL(l0->length, 10000); + BOOST_CHECK_EQUAL(l0->length, glm::length(difference(p000, p100))); BOOST_CHECK_CLOSE(l0->ends[0].dir, half_pi, 0.1F); BOOST_CHECK_CLOSE(l0->ends[1].dir, -half_pi, 0.1F); BOOST_CHECK(l0->ends[0].nexts.empty()); @@ -229,7 +237,7 @@ BOOST_FIXTURE_TEST_CASE(test_rail_network, RailLinks) auto l1 = addLinksBetween(p200, p100); BOOST_CHECK(dynamic_cast(l1.get())); - BOOST_CHECK_EQUAL(l1->length, 10000); + BOOST_CHECK_EQUAL(l1->length, glm::length(difference(p200, p100))); BOOST_CHECK_CLOSE(l1->ends[0].dir, half_pi, 0.1F); BOOST_CHECK_CLOSE(l1->ends[1].dir, -half_pi, 0.1F); BOOST_CHECK(l0->ends[0].nexts.empty()); @@ -241,7 +249,7 @@ BOOST_FIXTURE_TEST_CASE(test_rail_network, RailLinks) auto l2 = addLinksBetween(p200, p300); BOOST_CHECK(dynamic_cast(l2.get())); - BOOST_CHECK_EQUAL(l2->length, 10000); + BOOST_CHECK_EQUAL(l2->length, glm::length(difference(p200, p300))); BOOST_CHECK_CLOSE(l2->ends[0].dir, half_pi, 0.1F); BOOST_CHECK_CLOSE(l2->ends[1].dir, -half_pi, 0.1F); BOOST_CHECK(l0->ends[0].nexts.empty()); @@ -251,19 +259,28 @@ BOOST_FIXTURE_TEST_CASE(test_rail_network, RailLinks) BOOST_CHECK_EQUAL(l2->ends[0].nexts.at(0).second, 1); BOOST_CHECK(l2->ends[1].nexts.empty()); - auto l3 = addLinksBetween(p000, p110); - BOOST_CHECK(dynamic_cast(l3.get())); - BOOST_CHECK_CLOSE(l3->length, (pi + half_pi) * 10000.F, 0.1F); - BOOST_CHECK_CLOSE(l3->ends[0].dir, -half_pi, 0.1F); - BOOST_CHECK_CLOSE(l3->ends[1].dir, 0, 0.1F); - BOOST_CHECK_EQUAL(l0->ends[0].nexts.at(0).first.lock(), l3); - BOOST_CHECK_EQUAL(l0->ends[0].nexts.at(0).second, 0); - BOOST_CHECK_EQUAL(l3->ends[0].nexts.at(0).first.lock(), l0); - BOOST_CHECK_EQUAL(l3->ends[0].nexts.at(0).second, 0); - BOOST_CHECK(l3->ends[1].nexts.empty()); - - auto l4 = addLinksBetween(p110, p300); - BOOST_CHECK_CLOSE(l4->length, 30400.F, 0.1F); - BOOST_CHECK_BETWEEN(l4->ends[0].dir, .23F, .24F); - BOOST_CHECK_CLOSE(l4->ends[1].dir, half_pi, 0.1F); + BOOST_CHECK_IF(l3, addLinksBetween(p000, p110)) { + BOOST_CHECK_IF(l3c, dynamic_cast(l3.get())) { + BOOST_CHECK_CLOSE(l3c->radius, 10'300.F, 0.1F); + BOOST_CHECK_CLOSE(l3c->arc.length(), pi + half_pi, 0.5F); + BOOST_CHECK_CLOSE(l3->length, 48'563.F, 0.1F); + BOOST_CHECK_CLOSE(l3->ends[0].dir, -half_pi, 0.5F); + BOOST_CHECK_CLOSE(l3->ends[1].dir, -0.0097F, 0.5F); + BOOST_CHECK_EQUAL(l0->ends[0].nexts.at(0).first.lock(), l3); + BOOST_CHECK_EQUAL(l0->ends[0].nexts.at(0).second, 0); + BOOST_CHECK_EQUAL(l3->ends[0].nexts.at(0).first.lock(), l0); + BOOST_CHECK_EQUAL(l3->ends[0].nexts.at(0).second, 0); + BOOST_CHECK(l3->ends[1].nexts.empty()); + } + } + + BOOST_CHECK_IF(l4, addLinksBetween(p110, p300)) { + BOOST_CHECK_IF(l4c, dynamic_cast(l4.get())) { + BOOST_CHECK_CLOSE(l4c->radius, 6950.F, 0.1F); + BOOST_CHECK_CLOSE(l4c->arc.length(), 4.456F, 0.1F); + BOOST_CHECK_CLOSE(l4->length, 30'981.F, 0.1F); + BOOST_CHECK_BETWEEN(l4->ends[0].dir, .25F, .26F); + BOOST_CHECK_CLOSE(l4->ends[1].dir, half_pi, 0.1F); + } + } } -- cgit v1.2.3 From 8b388c4ee59961f4d307c7f9f87641beffb76a53 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 22 Dec 2024 13:29:15 +0000 Subject: Expose network base width and surface --- game/network/network.h | 4 ++++ game/network/rail.cpp | 14 ++++++++++++++ game/network/rail.h | 3 +++ test/test-network.cpp | 12 ++++++++++++ 4 files changed, 33 insertions(+) (limited to 'test/test-network.cpp') diff --git a/game/network/network.h b/game/network/network.h index be0900b..f8739b8 100644 --- a/game/network/network.h +++ b/game/network/network.h @@ -14,6 +14,7 @@ #include class SceneShader; +class Surface; template class Ray; template using GenDef = std::tuple...>; @@ -47,6 +48,9 @@ public: [[nodiscard]] virtual float findNodeDirection(Node::AnyCPtr) const = 0; + [[nodiscard]] virtual const Surface * getBaseSurface() const = 0; + [[nodiscard]] virtual RelativeDistance getBaseWidth() const = 0; + protected: static void joinLinks(const Link::Ptr & l, const Link::Ptr & ol); static GenCurveDef genCurveDef(const GlobalPosition3D & start, const GlobalPosition3D & end, float startDir); diff --git a/game/network/rail.cpp b/game/network/rail.cpp index f226327..dc62cf3 100644 --- a/game/network/rail.cpp +++ b/game/network/rail.cpp @@ -1,4 +1,6 @@ #include "rail.h" +#include "game/gamestate.h" +#include "game/geoData.h" #include "network.h" #include // IWYU pragma: keep #include @@ -169,3 +171,15 @@ RailLinks::render(const SceneShader & shader) const glBindVertexArray(0); } } + +const Surface * +RailLinks::getBaseSurface() const +{ + return std::dynamic_pointer_cast(gameState->assets.at("terrain.surface.gravel")).get(); +} + +RelativeDistance +RailLinks::getBaseWidth() const +{ + return 5'700; +} diff --git a/game/network/rail.h b/game/network/rail.h index 0aae718..fa64eda 100644 --- a/game/network/rail.h +++ b/game/network/rail.h @@ -77,6 +77,9 @@ public: std::shared_ptr addLinksBetween(GlobalPosition3D start, GlobalPosition3D end); void render(const SceneShader &) const override; + [[nodiscard]] const Surface * getBaseSurface() const override; + [[nodiscard]] RelativeDistance getBaseWidth() const override; + private: void tick(TickDuration elapsed) override; }; diff --git a/test/test-network.cpp b/test/test-network.cpp index ce25429..5373dd5 100644 --- a/test/test-network.cpp +++ b/test/test-network.cpp @@ -73,6 +73,18 @@ struct TestNetwork : public NetworkOf { render(const SceneShader &) const override { } + + const Surface * + getBaseSurface() const override + { + return nullptr; + } + + RelativeDistance + getBaseWidth() const override + { + return 5'700; + } }; const auto VALID_NODES = boost::unit_test::data::make({ -- cgit v1.2.3 From 1aba027462a861f2c1155672792dbbe555d7dc0a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 13 Jan 2025 01:45:43 +0000 Subject: Add distance helper Works with integer positions, first template param allows forcing to N dimensions --- game/geoData.cpp | 7 ++++--- game/geoData.h | 2 +- game/network/network.cpp | 4 ++-- game/network/network.impl.h | 4 ++-- game/network/rail.cpp | 6 +++--- lib/maths.h | 9 ++++++++- lib/ray.h | 3 +-- lib/triangle.h | 2 +- test/test-network.cpp | 6 +++--- 9 files changed, 25 insertions(+), 18 deletions(-) (limited to 'test/test-network.cpp') diff --git a/game/geoData.cpp b/game/geoData.cpp index 1a4cd3b..448ff67 100644 --- a/game/geoData.cpp +++ b/game/geoData.cpp @@ -405,10 +405,11 @@ GeoData::difference(const HalfedgeHandle heh) const return ::difference(point(to_vertex_handle(heh)), point(from_vertex_handle(heh))); } +template [[nodiscard]] RelativeDistance GeoData::length(const HalfedgeHandle heh) const { - return glm::length(difference(heh)); + return ::distance(point(to_vertex_handle(heh)), point(from_vertex_handle(heh))); } [[nodiscard]] GlobalPosition3D @@ -468,7 +469,7 @@ GeoData::setHeights(const std::span triangleStrip, const const auto vertexDistFrom = [this](GlobalPosition2D p) { return [p, this](const VertexHandle v) { - return std::make_pair(v, glm::length(::difference(p, this->point(v).xy()))); + return std::make_pair(v, ::distance(p, this->point(v).xy())); }; }; const auto vertexDistFromE = [this](GlobalPosition2D p) { @@ -614,7 +615,7 @@ GeoData::setHeights(const std::span triangleStrip, const todoOutHalfEdges(toVertex); } else if (!toTriangle) { // point without the new strip, adjust vertically by limit - const auto maxOffset = static_cast(opts.maxSlope * glm::length(difference(heh).xy())); + const auto maxOffset = static_cast(opts.maxSlope * length<2>(heh)); const auto newHeight = std::clamp(toPoint.z, fromPoint.z - maxOffset, fromPoint.z + maxOffset); if (newHeight != toPoint.z) { toPoint.z = newHeight; diff --git a/game/geoData.h b/game/geoData.h index 7e4c28f..390a443 100644 --- a/game/geoData.h +++ b/game/geoData.h @@ -136,7 +136,7 @@ protected: [[nodiscard]] HalfedgeHandle findBoundaryStart() const; [[nodiscard]] RelativePosition3D difference(const HalfedgeHandle) const; - [[nodiscard]] RelativeDistance length(const HalfedgeHandle) const; + template [[nodiscard]] RelativeDistance length(const HalfedgeHandle) const; [[nodiscard]] GlobalPosition3D centre(const HalfedgeHandle) const; void updateAllVertexNormals(); diff --git a/game/network/network.cpp b/game/network/network.cpp index 1666c4d..e67942f 100644 --- a/game/network/network.cpp +++ b/game/network/network.cpp @@ -121,8 +121,8 @@ Network::genCurveDef(const GlobalPosition3D & start, const GlobalPosition3D & en endDir += pi; const auto flatStart {start.xy()}, flatEnd {end.xy()}; auto midheight = [&](auto mid) { - const auto sm = glm::length(RelativePosition2D(flatStart - mid)), - em = glm::length(RelativePosition2D(flatEnd - mid)); + const auto sm = ::distance<2>(flatStart, mid); + const auto em = ::distance<2>(flatEnd, mid); return start.z + GlobalDistance(RelativeDistance(end.z - start.z) * (sm / (sm + em))); }; if (const auto radii = find_arcs_radius(flatStart, startDir, flatEnd, endDir); radii.first < radii.second) { diff --git a/game/network/network.impl.h b/game/network/network.impl.h index ff29088..33b0a86 100644 --- a/game/network/network.impl.h +++ b/game/network/network.impl.h @@ -52,7 +52,7 @@ template Link::CCollection NetworkOf::candidateJoins(GlobalPosition3D start, GlobalPosition3D end) { - if (glm::length(RelativePosition3D(start - end)) < 2000.F) { + if (::distance(start, end) < 2000.F) { return {}; } const auto defs = genCurveDef( @@ -81,7 +81,7 @@ template Link::CCollection NetworkOf::addJoins(GlobalPosition3D start, GlobalPosition3D end) { - if (glm::length(RelativePosition3D(start - end)) < 2000.F) { + if (::distance(start, end) < 2000.F) { return {}; } const auto defs = genCurveDef(start, end, findNodeDirection(nodeAt(start)), findNodeDirection(nodeAt(end))); diff --git a/game/network/rail.cpp b/game/network/rail.cpp index 2820cca..d7de231 100644 --- a/game/network/rail.cpp +++ b/game/network/rail.cpp @@ -40,8 +40,8 @@ RailLinks::addLinksBetween(GlobalPosition3D start, GlobalPosition3D end) const auto flatStart {start.xy()}, flatEnd {end.xy()}; if (node2ins.second == NodeIs::InNetwork) { auto midheight = [&](auto mid) { - const auto sm = glm::length(RelativePosition2D(flatStart - mid)), - em = glm::length(RelativePosition2D(flatEnd - mid)); + const auto sm = ::distance<2>(flatStart, mid); + const auto em = ::distance<2>(flatEnd, mid); return start.z + GlobalDistance(RelativeDistance(end.z - start.z) * (sm / (sm + em))); }; const float dir2 = pi + findNodeDirection(node2ins.first); @@ -117,7 +117,7 @@ RailLinkStraight::RailLinkStraight( RailLinkCurve::RailLinkCurve( NetworkLinkHolder & instances, const Node::Ptr & a, const Node::Ptr & b, GlobalPosition2D c) : - RailLinkCurve(instances, a, b, c || a->pos.z, glm::length(difference(a->pos.xy(), c)), {c, a->pos, b->pos}) + RailLinkCurve(instances, a, b, c || a->pos.z, ::distance<2>(a->pos.xy(), c), {c, a->pos, b->pos}) { } diff --git a/lib/maths.h b/lib/maths.h index 17ca795..3d4f440 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -111,6 +111,13 @@ difference(const glm::vec & globalA, const glm::vec & globalB) return globalA - globalB; } +template +constexpr auto +distance(const glm::vec & pointA, const glm::vec & pointB) +{ + return glm::length(difference(pointA, pointB)); +} + glm::mat4 flat_orientation(const Rotation3D & diff); namespace { @@ -498,7 +505,7 @@ operator"" _degrees(long double degrees) // Late implementations due to dependencies template constexpr ArcSegment::ArcSegment(PointType centre, PointType ep0, PointType ep1) : - Arc {centre, ep0, ep1}, centre {centre}, ep0 {ep0}, ep1 {ep1}, radius {glm::length(difference(centre, ep0))} + Arc {centre, ep0, ep1}, centre {centre}, ep0 {ep0}, ep1 {ep1}, radius {::distance(centre, ep0)} { } diff --git a/lib/ray.h b/lib/ray.h index a831270..793e21e 100644 --- a/lib/ray.h +++ b/lib/ray.h @@ -27,8 +27,7 @@ public: const auto n2 = crossProduct(direction, n); const auto c1 = p1 + PositionType((glm::dot(RelativePosition3D(start - p1), n2) / glm::dot(d1, n2)) * d1); const auto difflength = glm::length(diff); - if (glm::length(RelativePosition3D(c1 - p1)) > difflength - || glm::length(RelativePosition3D(c1 - e1)) > difflength) { + if (::distance(c1, p1) > difflength || ::distance(c1, e1) > difflength) { return std::numeric_limits::infinity(); } return static_cast(glm::abs(glm::dot(n, RelativePosition3D(p1 - start)))); diff --git a/lib/triangle.h b/lib/triangle.h index d5547ab..e430653 100644 --- a/lib/triangle.h +++ b/lib/triangle.h @@ -48,7 +48,7 @@ struct Triangle : public glm::vec<3, glm::vec> { [[nodiscard]] constexpr auto height() { - return (area() * 2) / glm::length(difference(p(0), p(1))); + return (area() * 2) / ::distance(p(0), p(1)); } [[nodiscard]] constexpr Normal3D diff --git a/test/test-network.cpp b/test/test-network.cpp index 5373dd5..e7419b5 100644 --- a/test/test-network.cpp +++ b/test/test-network.cpp @@ -241,7 +241,7 @@ BOOST_FIXTURE_TEST_CASE(test_rail_network, RailLinks) // -------- auto l0 = addLinksBetween(p000, p100); BOOST_CHECK(dynamic_cast(l0.get())); - BOOST_CHECK_EQUAL(l0->length, glm::length(difference(p000, p100))); + BOOST_CHECK_EQUAL(l0->length, ::distance(p000, p100)); BOOST_CHECK_CLOSE(l0->ends[0].dir, half_pi, 0.1F); BOOST_CHECK_CLOSE(l0->ends[1].dir, -half_pi, 0.1F); BOOST_CHECK(l0->ends[0].nexts.empty()); @@ -249,7 +249,7 @@ BOOST_FIXTURE_TEST_CASE(test_rail_network, RailLinks) auto l1 = addLinksBetween(p200, p100); BOOST_CHECK(dynamic_cast(l1.get())); - BOOST_CHECK_EQUAL(l1->length, glm::length(difference(p200, p100))); + BOOST_CHECK_EQUAL(l1->length, ::distance(p200, p100)); BOOST_CHECK_CLOSE(l1->ends[0].dir, half_pi, 0.1F); BOOST_CHECK_CLOSE(l1->ends[1].dir, -half_pi, 0.1F); BOOST_CHECK(l0->ends[0].nexts.empty()); @@ -261,7 +261,7 @@ BOOST_FIXTURE_TEST_CASE(test_rail_network, RailLinks) auto l2 = addLinksBetween(p200, p300); BOOST_CHECK(dynamic_cast(l2.get())); - BOOST_CHECK_EQUAL(l2->length, glm::length(difference(p200, p300))); + BOOST_CHECK_EQUAL(l2->length, ::distance(p200, p300)); BOOST_CHECK_CLOSE(l2->ends[0].dir, half_pi, 0.1F); BOOST_CHECK_CLOSE(l2->ends[1].dir, -half_pi, 0.1F); BOOST_CHECK(l0->ends[0].nexts.empty()); -- cgit v1.2.3