summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2025-06-09 23:26:52 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2025-06-09 23:26:52 +0100
commit646b276a9ba766a7e2acfe2d35e83228afc0d1f7 (patch)
treebbe1f072748ee7e706e9bc95c7c6c21af44acc2e /lib
parentRemove the awful find_arcs_radius functions (diff)
downloadilt-646b276a9ba766a7e2acfe2d35e83228afc0d1f7.tar.bz2
ilt-646b276a9ba766a7e2acfe2d35e83228afc0d1f7.tar.xz
ilt-646b276a9ba766a7e2acfe2d35e83228afc0d1f7.zip
Handle edge casesbetter-network
...where extending a network results in something that can be a straight or collapsed into a single arc from a bi-arc.
Diffstat (limited to 'lib')
-rw-r--r--lib/maths.cpp9
-rw-r--r--lib/maths.h32
2 files changed, 24 insertions, 17 deletions
diff --git a/lib/maths.cpp b/lib/maths.cpp
index 000cea7..7dd313e 100644
--- a/lib/maths.cpp
+++ b/lib/maths.cpp
@@ -1,5 +1,6 @@
#include "maths.h"
#include <cmath>
+#include <functional>
#include <glm/glm.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtx/transform.hpp>
@@ -32,6 +33,7 @@ static_assert(pow(3, 1) == 3);
static_assert(pow(3, 2) == 9);
static_assert(pow(pi, 3) == 31.006278991699219F);
+#ifndef __clang__
static_assert(!linesIntersectAt<int>({0, 10}, {10, 10}, {10, 0}, {0, 0}).has_value());
static_assert(*linesIntersectAt<int>({0, 0}, {10, 10}, {10, 0}, {0, 10}) == GlobalPosition2D {5, 5});
static_assert(*linesIntersectAt<int>({300'000'000, 400'000'00}, {300'010'000, 400'010'00}, {310'010'000, 410'000'00},
@@ -43,6 +45,13 @@ constexpr auto EAST2D = RelativePosition2D(east);
static_assert(!linesIntersectAtDirs<int>({0, 0}, NORTH2D, {10, 10}, NORTH2D).has_value());
static_assert(linesIntersectAtDirs<int>({0, 0}, NORTH2D, {10, 10}, EAST2D) == GlobalPosition2D {0, 10});
static_assert(linesIntersectAtDirs<int>({0, 0}, EAST2D, {10, 10}, NORTH2D) == GlobalPosition2D {10, 0});
+
+static_assert(find_arc_centre<int>({0, 0}, -NORTH2D, {10, 10}) == std::make_pair<GlobalPosition2D>({10, 0}, 10.F));
+static_assert(find_arc_centre<int>({20, 0}, -NORTH2D, {10, 10}) == std::make_pair<GlobalPosition2D>({10, 0}, -10.F));
+static_assert(find_arc_centre<int>({10, 0}, -NORTH2D, {10, 10}).second == 0.F);
+static_assert(isWithinLimit(find_arc_centre<int>({0, 0}, pi + quarter_pi, {1000, 1000}).second, 0.F, 0.1F));
+#endif
+
// NOLINTEND(readability-magic-numbers)
float
diff --git a/lib/maths.h b/lib/maths.h
index 93a4322..09af048 100644
--- a/lib/maths.h
+++ b/lib/maths.h
@@ -427,38 +427,36 @@ linesIntersectAt(const glm::vec<2, T, Q> Aabs, const glm::vec<2, T, Q> Babs, con
template<std::floating_point T> constexpr auto EPSILON = 0.0001F;
template<std::floating_point T>
-auto
+[[nodiscard]] constexpr auto
isWithinLimit(T lhs, T rhs, T limit = EPSILON<T>)
{
return std::abs(lhs - rhs) <= limit;
}
-template<Arithmetic T, glm::qualifier Q = glm::defaultp>
-std::pair<glm::vec<2, T, Q>, bool>
-find_arc_centre(glm::vec<2, T, Q> start, Angle entrys, glm::vec<2, T, Q> end, Angle entrye)
+template<Arithmetic T, std::floating_point D, glm::qualifier Q = glm::defaultp>
+constexpr std::pair<glm::vec<2, T, Q>, D>
+find_arc_centre(glm::vec<2, T, Q> start, glm::vec<2, D, Q> entrys, glm::vec<2, T, Q> end)
{
if (start == end) {
- return {start, false};
+ return {start, 0};
}
- return find_arc_centre(start, sincos(entrys + half_pi), end, sincos(entrye - half_pi));
+ const auto diffEnds = difference(end, start);
+ const auto offset = entrys.x * diffEnds.y - entrys.y * diffEnds.x;
+ if (offset == 0.F) {
+ return {start, offset};
+ }
+ const auto midEnds = start + ((end - start) / 2);
+ const auto centre = linesIntersectAtDirs(start, vector_normal(entrys), midEnds, vector_normal(diffEnds));
+ return {*centre, offset};
}
template<Arithmetic T, glm::qualifier Q = glm::defaultp>
-std::pair<glm::vec<2, T, Q>, bool>
+constexpr std::pair<glm::vec<2, T, Q>, float>
find_arc_centre(glm::vec<2, T, Q> start, Angle entrys, glm::vec<2, T, Q> end)
{
- if (start == end) {
- return {start, false};
- }
- const auto startNormal = vector_normal(sincos(entrys) * 10'000.F);
- const auto diffEnds = difference(end, start);
- const auto midEnds = start + ((end - start) / 2);
- const auto diffNormal = vector_normal(diffEnds);
- const auto centre = linesIntersectAt(start, start + startNormal, midEnds, midEnds + diffNormal);
- return {*centre, normalize(vector_yaw(diffEnds) - entrys) < 0};
+ return find_arc_centre(start, sincos(entrys), end);
}
-
template<Arithmetic T>
auto
midpoint(const std::pair<T, T> & v)