From f92c378423f81b4058c19f8fc3d7e631ceb8304d Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 15 Dec 2024 14:17:27 +0000 Subject: vector difference works with floating point Makes it a generic wrapper --- lib/maths.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/maths.h b/lib/maths.h index 3959896..b28fe01 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -79,8 +79,11 @@ operator-(const GlobalPosition & global, const CalcPosition & relative) return global - GlobalPosition(relative); } -template -constexpr RelativePosition +template +using DifferenceVector = glm::vec, T, float>, Q>; + +template +constexpr DifferenceVector difference(const glm::vec & globalA, const glm::vec & globalB) { return globalA - globalB; -- cgit v1.2.3 From 39985f36e807126b2c7b9ec6096bda3922903a54 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 15 Dec 2024 14:38:00 +0000 Subject: 2D triangle area support --- lib/triangle.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/triangle.h b/lib/triangle.h index 812bfab..5787094 100644 --- a/lib/triangle.h +++ b/lib/triangle.h @@ -31,6 +31,13 @@ struct Triangle : public glm::vec<3, glm::vec> { return glm::length(crossProduct(sideDifference(1), sideDifference(2))) / T {2}; } + [[nodiscard]] constexpr auto + area() const + requires(Dim == 2) + { + return std::abs((sideDifference(1).x * sideDifference(2).y) - (sideDifference(2).x * sideDifference(1).y)) / 2; + } + [[nodiscard]] constexpr Normal3D normal() const requires(Dim == 3) -- cgit v1.2.3 From ea393a85a572e94f4c76e79cbd16897f9eae55f5 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 15 Dec 2024 14:53:05 +0000 Subject: Triangle height support Point C from the line AB --- lib/triangle.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/triangle.h b/lib/triangle.h index 5787094..888481d 100644 --- a/lib/triangle.h +++ b/lib/triangle.h @@ -45,6 +45,12 @@ struct Triangle : public glm::vec<3, glm::vec> { return crossProduct(sideDifference(1), sideDifference(2)); } + [[nodiscard]] constexpr auto + height() + { + return (area() * 2) / glm::length(difference(p(0), p(1))); + } + [[nodiscard]] constexpr Normal3D nnormal() const requires(Dim == 3) -- cgit v1.2.3 From 5af54c1584a1ce7797dfcb9e75dfbb26bdfc6338 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 18 Dec 2024 14:50:21 +0000 Subject: 2D vector_normal to work on any arithmetic --- lib/maths.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/maths.h b/lib/maths.h index b28fe01..4223f14 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -223,7 +223,7 @@ vector_pitch(const glm::vec & diff) return std::atan(diff.z); } -template +template constexpr glm::vec<2, T, Q> vector_normal(const glm::vec<2, T, Q> & vector) { -- cgit v1.2.3 From 15754d6b61b0f00fa142ff55d87e8be09d2041c8 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 18 Dec 2024 17:12:56 +0000 Subject: Midpoint for integral vectors --- lib/maths.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/maths.h b/lib/maths.h index 4223f14..7f2d7b4 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -427,6 +427,13 @@ midpoint(const std::pair & v) return std::midpoint(v.first, v.second); } +template +auto +midpoint(const glm::vec & valueA, const glm::vec & valueB) +{ + return valueA + (valueB - valueA) / 2; +} + // std::pow is not constexpr template requires requires(T n) { n *= n; } -- cgit v1.2.3 From a007ffeed3cfa6af2cbe1053c330ad11927d58de Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 18 Dec 2024 17:24:02 +0000 Subject: Add sanity checking logic to GeoData --- lib/triangle.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib') diff --git a/lib/triangle.h b/lib/triangle.h index 888481d..d5547ab 100644 --- a/lib/triangle.h +++ b/lib/triangle.h @@ -83,6 +83,14 @@ struct Triangle : public glm::vec<3, glm::vec> { return 0.F; } + [[nodiscard]] constexpr auto + isUp() const + { + const auto edgeAB = sideDifference(1); + const auto edgeAC = sideDifference(2); + return edgeAB.x * edgeAC.y >= edgeAB.y * edgeAC.x; + } + [[nodiscard]] constexpr auto p(const glm::length_t idx) const { -- cgit v1.2.3 From 06e64d7ccf053dbb11547edf3ba986d096b50045 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 31 Dec 2024 12:52:10 +0000 Subject: Add ArcSegment Extends Arc, with method for determining intersection point with line segment --- lib/maths.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/stream_support.h | 11 +++++++++ 2 files changed, 79 insertions(+) (limited to 'lib') diff --git a/lib/maths.h b/lib/maths.h index 7f2d7b4..f43321a 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -1,6 +1,8 @@ #pragma once #include "config/types.h" +#include +#include #include #include #include @@ -36,6 +38,26 @@ struct Arc : public std::pair { } }; +template struct ArcSegment : public Arc { + using PointType = glm::vec<2, T, Q>; + + constexpr ArcSegment(PointType centre, PointType ep0, PointType ep1); + + PointType centre; + PointType ep0; + PointType ep1; + RelativeDistance radius; + + [[nodiscard]] constexpr std::optional> crossesLineAt( + const glm::vec<2, T, Q> & lineStart, const glm::vec<2, T, Q> & lineEnd) const; + + [[nodiscard]] constexpr bool + angleWithinArc(Angle angle) const + { + return first <= angle && angle <= second; + } +}; + constexpr const RelativePosition3D up {0, 0, 1}; // NOLINT(readability-identifier-length) constexpr const RelativePosition3D down {0, 0, -1}; constexpr const RelativePosition3D north {0, 1, 0}; @@ -471,3 +493,49 @@ operator"" _degrees(long double degrees) { return static_cast(degrees) * degreesToRads; } + +// 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))} +{ +} + +template +[[nodiscard]] constexpr std::optional> +ArcSegment::crossesLineAt(const glm::vec<2, T, Q> & lineStart, const glm::vec<2, T, Q> & lineEnd) const +{ + // Based on formulas from https://mathworld.wolfram.com/Circle-LineIntersection.html + const auto lineDiff = difference(lineEnd, lineStart); + const auto lineLen = glm::length(lineDiff); + const auto lineRelStart = difference(lineStart, centre); + const auto lineRelEnd = difference(lineEnd, centre); + const auto determinant = (lineRelStart.x * lineRelEnd.y) - (lineRelEnd.x * lineRelStart.y); + const auto discriminant = (radius * radius * lineLen * lineLen) - (determinant * determinant); + if (discriminant < 0) { + return std::nullopt; + } + + const auto rootDiscriminant = std::sqrt(discriminant); + const auto drdr = lineLen * lineLen; + const RelativeDistance sgn = (lineDiff.y < 0 ? -1 : 1); + std::array points { + RelativePosition2D {((determinant * lineDiff.y) + sgn * lineDiff.x * rootDiscriminant), + ((-determinant * lineDiff.x) + std::abs(lineDiff.y) * rootDiscriminant)} + / drdr, + RelativePosition2D {((determinant * lineDiff.y) - sgn * lineDiff.x * rootDiscriminant), + ((-determinant * lineDiff.x) - std::abs(lineDiff.y) * rootDiscriminant)} + / drdr, + }; + const auto end + = std::remove_if(points.begin(), points.end(), [this, lineRelStart, lineDiff, drdr](const auto point) { + const auto dot = glm::dot(lineDiff, point - lineRelStart); + return !angleWithinArc(vector_yaw(point)) || dot < 0 || dot > drdr; + }); + if (points.begin() == end) { + return std::nullopt; + } + return centre + *std::ranges::min_element(points.begin(), end, {}, [lineRelStart](const auto point) { + return glm::distance(lineRelStart, point); + }); +} diff --git a/lib/stream_support.h b/lib/stream_support.h index f21622a..f5c5e37 100644 --- a/lib/stream_support.h +++ b/lib/stream_support.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,16 @@ namespace std { { return s << EnumTypeDetails::typeName << "::" << EnumDetails::to_string(e).value(); } + + template + inline std::ostream & + operator<<(std::ostream & s, const std::optional & v) + { + if (v) { + return s << *v; + } + return s << "nullopt"; + } } template -- cgit v1.2.3 From c0d05b1ad0f2d82f9ce94437370648e7dfdd994e Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 1 Jan 2025 16:00:35 +0000 Subject: Return angle of intersection of arc with line --- lib/maths.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/maths.h b/lib/maths.h index f43321a..671313d 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -48,7 +48,7 @@ template struct ArcSegment : publi PointType ep1; RelativeDistance radius; - [[nodiscard]] constexpr std::optional> crossesLineAt( + [[nodiscard]] constexpr std::optional, Angle>> crossesLineAt( const glm::vec<2, T, Q> & lineStart, const glm::vec<2, T, Q> & lineEnd) const; [[nodiscard]] constexpr bool @@ -502,7 +502,7 @@ constexpr ArcSegment::ArcSegment(PointType centre, PointType ep0, PointTyp } template -[[nodiscard]] constexpr std::optional> +[[nodiscard]] constexpr std::optional, Angle>> ArcSegment::crossesLineAt(const glm::vec<2, T, Q> & lineStart, const glm::vec<2, T, Q> & lineEnd) const { // Based on formulas from https://mathworld.wolfram.com/Circle-LineIntersection.html @@ -519,23 +519,23 @@ ArcSegment::crossesLineAt(const glm::vec<2, T, Q> & lineStart, const glm:: const auto rootDiscriminant = std::sqrt(discriminant); const auto drdr = lineLen * lineLen; const RelativeDistance sgn = (lineDiff.y < 0 ? -1 : 1); - std::array points { - RelativePosition2D {((determinant * lineDiff.y) + sgn * lineDiff.x * rootDiscriminant), - ((-determinant * lineDiff.x) + std::abs(lineDiff.y) * rootDiscriminant)} - / drdr, - RelativePosition2D {((determinant * lineDiff.y) - sgn * lineDiff.x * rootDiscriminant), - ((-determinant * lineDiff.x) - std::abs(lineDiff.y) * rootDiscriminant)} - / drdr, - }; + std::array, 2> points; + std::ranges::transform(std::initializer_list {1, -1}, points.begin(), [&](RelativeDistance N) { + const auto point = RelativePosition2D {((determinant * lineDiff.y) + sgn * lineDiff.x * rootDiscriminant * N), + ((-determinant * lineDiff.x) + std::abs(lineDiff.y) * rootDiscriminant * N)} + / drdr; + return std::make_pair(point, vector_yaw(point)); + }); const auto end = std::remove_if(points.begin(), points.end(), [this, lineRelStart, lineDiff, drdr](const auto point) { - const auto dot = glm::dot(lineDiff, point - lineRelStart); - return !angleWithinArc(vector_yaw(point)) || dot < 0 || dot > drdr; - }); + const auto dot = glm::dot(lineDiff, point.first - lineRelStart); + return !angleWithinArc(point.second) || dot < 0 || dot > drdr; + }); if (points.begin() == end) { return std::nullopt; } - return centre + *std::ranges::min_element(points.begin(), end, {}, [lineRelStart](const auto point) { - return glm::distance(lineRelStart, point); + const auto first = *std::ranges::min_element(points.begin(), end, {}, [lineRelStart](const auto point) { + return glm::distance(lineRelStart, point.first); }); + return std::make_pair(centre + first.first, first.second); } -- cgit v1.2.3 From bc0bbe935942fa6c54f2e9e71f49351c85d7e956 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 5 Jan 2025 18:15:04 +0000 Subject: Add helper for merging close elements in a vector --- lib/collections.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'lib') diff --git a/lib/collections.h b/lib/collections.h index ea5d5dc..6f26eae 100644 --- a/lib/collections.h +++ b/lib/collections.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -224,3 +225,40 @@ strip_end(IterableCollection auto & cont) { return stripiter {cont.end()}; } + +template +void +mergeClose(std::vector & range, const Dist & dist, const Merger & merger, + decltype(dist(range.front(), range.front())) tolerance) +{ + using DistanceType = decltype(tolerance); + std::vector distances; + distances.reserve(range.size() - 1); + std::ranges::transform(range | std::views::pairwise, std::back_inserter(distances), [&dist](const auto & pair) { + return (std::apply(dist, pair)); + }); + while (distances.size() > 1) { + const auto closestPair = std::ranges::min_element(distances); + if (*closestPair > tolerance) { + return; + } + const auto offset = std::distance(distances.begin(), closestPair); + const auto idx = static_cast(offset); + if (closestPair == distances.begin()) { + // Remove second element + range.erase(range.begin() + 1); + distances.erase(distances.begin()); + } + else if (closestPair == --distances.end()) { + // Remove second from last element + range.erase(range.end() - 2); + distances.erase(distances.end() - 1); + } + else { + range[idx] = merger(range[idx], range[idx + 1]); + range.erase(range.begin() + offset + 1); + distances.erase(distances.begin() + offset); + } + distances[idx] = dist(range[idx], range[idx + 1]); + } +} -- cgit v1.2.3 From 6d16749c5c4950ca4480bc0908a602f38e21cea0 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 5 Jan 2025 19:18:40 +0000 Subject: Add helper for sorting sorted containers by a projection --- lib/sorting.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib') diff --git a/lib/sorting.h b/lib/sorting.h index 777de00..be5a7e2 100644 --- a/lib/sorting.h +++ b/lib/sorting.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -30,6 +31,14 @@ template struct PtrMemberSorter : public PtrSorter { } }; +template struct SortedBy { + auto + operator()(const auto & left, const auto & right) const + { + return (std::invoke(Proj, left) < std::invoke(Proj, right)); + } +}; + struct CompareBy { glm::length_t index; -- cgit v1.2.3 From 8f10ddbfffd0f7f60b6b9488a0d3b0c60d8d5131 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 6 Jan 2025 20:28:16 +0000 Subject: Add default Q = glm::defaultp to maths functions Makes getting a pointer to the function more trivial --- lib/maths.h | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/maths.h b/lib/maths.h index 671313d..17ca795 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -15,7 +15,7 @@ template concept Arithmetic = std::is_arithmetic_v; struct Arc : public std::pair { - template + template requires(Lc >= 2, Le >= 2) Arc(const glm::vec & centre, const glm::vec & e0p, const glm::vec & e1p) : Arc {RelativePosition2D {e0p.xy() - centre.xy()}, RelativePosition2D {e1p.xy() - centre.xy()}} @@ -101,10 +101,10 @@ operator-(const GlobalPosition & global, const CalcPosition & relative) return global - GlobalPosition(relative); } -template +template using DifferenceVector = glm::vec, T, float>, Q>; -template +template constexpr DifferenceVector difference(const glm::vec & globalA, const glm::vec & globalB) { @@ -147,7 +147,8 @@ namespace { } // Helper to lookup into a matrix given an xy vector coordinate - template + template constexpr auto & operator^(glm::mat & matrix, const glm::vec<2, I> rowCol) { @@ -155,7 +156,7 @@ namespace { } // Create a matrix for the angle, given the targets into the matrix - template + template constexpr auto rotation(const T angle, const glm::vec<2, I> cos1, const glm::vec<2, I> sin1, const glm::vec<2, I> cos2, const glm::vec<2, I> negSin1) @@ -245,7 +246,7 @@ vector_pitch(const glm::vec & diff) return std::atan(diff.z); } -template +template constexpr glm::vec<2, T, Q> vector_normal(const glm::vec<2, T, Q> & vector) { @@ -267,7 +268,7 @@ sq(T value) return value * value; } -template +template constexpr glm::vec<3, int64_t, Q> crossProduct(const glm::vec<3, int64_t, Q> & valueA, const glm::vec<3, int64_t, Q> & valueB) { @@ -278,14 +279,14 @@ crossProduct(const glm::vec<3, int64_t, Q> & valueA, const glm::vec<3, int64_t, }; } -template +template constexpr glm::vec<3, T, Q> crossProduct(const glm::vec<3, T, Q> & valueA, const glm::vec<3, T, Q> & valueB) { return crossProduct(valueA, valueB); } -template +template constexpr glm::vec<3, T, Q> crossProduct(const glm::vec<3, T, Q> & valueA, const glm::vec<3, T, Q> & valueB) { @@ -300,35 +301,35 @@ ratio(const Ta valueA, const Tb valueB) return static_cast((static_cast(valueA) / static_cast(valueB))); } -template +template constexpr auto ratio(const glm::vec<2, T, Q> & value) { return ratio(value.x, value.y); } -template +template constexpr auto perspective_divide(const glm::vec<4, T, Q> & value) { return value / value.w; } -template +template constexpr glm::vec operator||(const glm::vec valueA, const glm::vec valueB) { return {valueA, valueB}; } -template +template constexpr glm::vec operator||(const glm::vec valueA, const T valueB) { return {valueA, valueB}; } -template +template constexpr glm::vec perspectiveMultiply(const glm::vec & base, const glm::mat & mutation) { @@ -336,7 +337,7 @@ perspectiveMultiply(const glm::vec & base, const glm::mat +template constexpr glm::vec perspectiveApply(glm::vec & base, const glm::mat & mutation) { @@ -384,7 +385,7 @@ linesIntersectAt(const glm::vec<2, T, Q> Aabs, const glm::vec<2, T, Q> Babs, con return Aabs + CVec {(b1 * c2) / -determinant, (a1 * c2) / determinant}; } -template +template std::pair, bool> find_arc_centre(glm::vec<2, T, Q> start, Rotation2D startDir, glm::vec<2, T, Q> end, Rotation2D endDir) { @@ -397,7 +398,7 @@ find_arc_centre(glm::vec<2, T, Q> start, Rotation2D startDir, glm::vec<2, T, Q> throw std::runtime_error("no intersection"); } -template +template std::pair, bool> find_arc_centre(glm::vec<2, T, Q> start, Angle entrys, glm::vec<2, T, Q> end, Angle entrye) { @@ -407,7 +408,7 @@ find_arc_centre(glm::vec<2, T, Q> start, Angle entrys, glm::vec<2, T, Q> end, An return find_arc_centre(start, sincos(entrys + half_pi), end, sincos(entrye - half_pi)); } -template +template Angle find_arcs_radius(glm::vec<2, T, Q> start, Rotation2D ad, glm::vec<2, T, Q> end, Rotation2D bd) { @@ -432,7 +433,7 @@ find_arcs_radius(glm::vec<2, T, Q> start, Rotation2D ad, glm::vec<2, T, Q> end, / (2 * (sq(X) - 2 * X * Z + sq(Z) + sq(Y) - 2 * Y * W + sq(W) - 4)); } -template +template std::pair find_arcs_radius(glm::vec<2, T, Q> start, Angle entrys, glm::vec<2, T, Q> end, Angle entrye) { @@ -449,7 +450,7 @@ midpoint(const std::pair & v) return std::midpoint(v.first, v.second); } -template +template auto midpoint(const glm::vec & valueA, const glm::vec & valueB) { -- 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 --- lib/maths.h | 9 ++++++++- lib/ray.h | 3 +-- lib/triangle.h | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'lib') 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 -- cgit v1.2.3 From 62fd9391bbfde47177fb36434d9664e47f4cf656 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 9 Feb 2025 13:02:09 +0000 Subject: Initial commit setting terrain during network construction This is all in the wrong place, it shouldn't be part of the network interface. --- lib/collections.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib') diff --git a/lib/collections.h b/lib/collections.h index 6f26eae..fcd65d3 100644 --- a/lib/collections.h +++ b/lib/collections.h @@ -107,6 +107,15 @@ operator+=(std::vector & in, std::vector && src) return in; } +template +constexpr auto +operator+(std::vector in1, std::vector in2) +{ + in1.reserve(in1.size() + in2.size()); + std::move(in2.begin(), in2.end(), std::back_inserter(in1)); + return in1; +} + template [[nodiscard]] constexpr auto operator+(const std::vector & in, Vn && vn) -- cgit v1.2.3 From ecbb621171af0f20751bbc590453d00a7bd38320 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 9 Feb 2025 15:18:35 +0000 Subject: Move lots of geoData helpers into lib --- lib/maths.h | 46 +++++++++++++++++++++++++++++++++++++++++++--- lib/triangle.h | 27 +++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/maths.h b/lib/maths.h index 3d4f440..2049c78 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -14,6 +14,9 @@ template concept Arithmetic = std::is_arithmetic_v; +template using CalcType = std::conditional_t, T, int64_t>; +template using DifferenceType = std::conditional_t, T, float>; + struct Arc : public std::pair { template requires(Lc >= 2, Le >= 2) @@ -102,7 +105,7 @@ operator-(const GlobalPosition & global, const CalcPosition & relative) } template -using DifferenceVector = glm::vec, T, float>, Q>; +using DifferenceVector = glm::vec, Q>; template constexpr DifferenceVector @@ -111,6 +114,16 @@ difference(const glm::vec & globalA, const glm::vec & globalB) return globalA - globalB; } +template +using CalcVector = glm::vec, Q>; + +template +constexpr CalcVector +calcDifference(const glm::vec & globalA, const glm::vec & globalB) +{ + return globalA - globalB; +} + template constexpr auto distance(const glm::vec & pointA, const glm::vec & pointB) @@ -364,8 +377,6 @@ normalize(T ang) return ang; } -template using CalcType = std::conditional_t, T, int64_t>; - template [[nodiscard]] constexpr std::optional> linesIntersectAt(const glm::vec<2, T, Q> Aabs, const glm::vec<2, T, Q> Babs, const glm::vec<2, T, Q> Cabs, @@ -547,3 +558,32 @@ ArcSegment::crossesLineAt(const glm::vec<2, T, Q> & lineStart, const glm:: }); return std::make_pair(centre + first.first, first.second); } + +namespace { + template typename Op> + [[nodiscard]] constexpr auto + pointLineOp(const GlobalPosition2D point, const GlobalPosition2D end1, const GlobalPosition2D end2) + { + return Op {}(CalcDistance(end2.x - end1.x) * CalcDistance(point.y - end1.y), + CalcDistance(end2.y - end1.y) * CalcDistance(point.x - end1.x)); + } +} + +constexpr auto pointLeftOfLine = pointLineOp; +constexpr auto pointLeftOfOrOnLine = pointLineOp; + +[[nodiscard]] constexpr bool +linesCross(const GlobalPosition2D lineAend1, const GlobalPosition2D lineAend2, const GlobalPosition2D lineBend1, + const GlobalPosition2D lineBend2) +{ + return (pointLeftOfLine(lineAend2, lineBend1, lineBend2) == pointLeftOfLine(lineAend1, lineBend2, lineBend1)) + && (pointLeftOfLine(lineBend1, lineAend1, lineAend2) == pointLeftOfLine(lineBend2, lineAend2, lineAend1)); +} + +[[nodiscard]] constexpr bool +linesCrossLtR(const GlobalPosition2D lineAend1, const GlobalPosition2D lineAend2, const GlobalPosition2D lineBend1, + const GlobalPosition2D lineBend2) +{ + return pointLeftOfLine(lineAend2, lineBend1, lineBend2) && pointLeftOfLine(lineAend1, lineBend2, lineBend1) + && pointLeftOfLine(lineBend1, lineAend1, lineAend2) && pointLeftOfLine(lineBend2, lineAend2, lineAend1); +} diff --git a/lib/triangle.h b/lib/triangle.h index e430653..abd697c 100644 --- a/lib/triangle.h +++ b/lib/triangle.h @@ -64,6 +64,12 @@ struct Triangle : public glm::vec<3, glm::vec> { return difference(p(side), p(0)); } + [[nodiscard]] constexpr auto + calcSideDifference(glm::length_t side) const + { + return calcDifference(p(side), p(0)); + } + [[nodiscard]] constexpr auto angle(glm::length_t corner) const { @@ -126,4 +132,25 @@ struct Triangle : public glm::vec<3, glm::vec> { { return begin() + 3; } + + [[nodiscard]] + constexpr auto + positionOnPlane(const glm::vec<2, T, Q> coord2d) const + requires(Dim == 3) + { + const auto edgeCrossProduct = crossProduct(calcSideDifference(1), calcSideDifference(2)); + return coord2d + || static_cast( + ((edgeCrossProduct.x * p(0).x) + (edgeCrossProduct.y * p(0).y) + (edgeCrossProduct.z * p(0).z) + - (edgeCrossProduct.x * coord2d.x) - (edgeCrossProduct.y * coord2d.y)) + / edgeCrossProduct.z); + } + + [[nodiscard]] + constexpr bool + containsPoint(const GlobalPosition2D coord) const + { + return pointLeftOfOrOnLine(coord, p(0), p(1)) && pointLeftOfOrOnLine(coord, p(1), p(2)) + && pointLeftOfOrOnLine(coord, p(2), p(0)); + } }; -- cgit v1.2.3 From 98afc8feaed67a0c6d450d27ded25145476ac8ff Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Feb 2025 02:33:20 +0000 Subject: Add utility class to easily get nth field of tuple/pair for any types --- lib/util.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'lib') diff --git a/lib/util.h b/lib/util.h index 290492f..2674eaf 100644 --- a/lib/util.h +++ b/lib/util.h @@ -3,6 +3,7 @@ #include // IWYU pragma: keep #include #include +#include template constexpr auto @@ -12,3 +13,23 @@ transform_array(const std::array & in, auto && transform) std::transform(in.begin(), in.end(), out.begin(), transform); return out; } + +namespace { + template struct GetNth { + decltype(auto) + operator()(const auto & tup) const + { + if constexpr (sizeof...(N) == 1) { + return std::get(tup); + } + else { + return std::tie(std::get(tup)...); + } + } + }; +} + +template constexpr auto Nth = GetNth {}; +constexpr auto GetFirst = Nth<0>; +constexpr auto GetSecond = Nth<1>; +constexpr auto GetSwapped = Nth<0, 1>; -- cgit v1.2.3 From f26559dcd25b649d37a1a30e087b70b95f530954 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Feb 2025 23:53:46 +0000 Subject: Range adaptor to make triangle strip triples --- lib/collections.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'lib') diff --git a/lib/collections.h b/lib/collections.h index fcd65d3..c81bede 100644 --- a/lib/collections.h +++ b/lib/collections.h @@ -197,6 +197,14 @@ template struct stripiter { return *this; } + constexpr stripiter + operator++(int) + { + auto out {*this}; + ++*this; + return out; + } + constexpr stripiter & operator--() { @@ -205,6 +213,14 @@ template struct stripiter { return *this; } + constexpr stripiter + operator--(int) + { + auto out {*this}; + --*this; + return out; + } + constexpr auto operator-(const stripiter & other) const { @@ -235,6 +251,16 @@ strip_end(IterableCollection auto & cont) return stripiter {cont.end()}; } +struct TriangleTriplesImpl : public std::ranges::range_adaptor_closure { + decltype(auto) + operator()(const auto & triangleStrip) const + { + return std::views::iota(strip_begin(triangleStrip), strip_end(triangleStrip)); + } +}; + +constexpr TriangleTriplesImpl TriangleTriples; + template void mergeClose(std::vector & range, const Dist & dist, const Merger & merger, -- cgit v1.2.3 From 619983e949fde226cc7a3de0bc198fdcee3fe3b4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 15 Feb 2025 14:46:48 +0000 Subject: Fixes and tests to new range helpers --- lib/collections.h | 10 +++++++--- lib/util.h | 8 ++++---- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/collections.h b/lib/collections.h index c81bede..27eff0a 100644 --- a/lib/collections.h +++ b/lib/collections.h @@ -251,15 +251,19 @@ strip_end(IterableCollection auto & cont) return stripiter {cont.end()}; } -struct TriangleTriplesImpl : public std::ranges::range_adaptor_closure { +inline constexpr auto dereference = std::views::transform([](const auto & iter) -> decltype(auto) { + return *iter; +}); + +struct TriangleTriples : public std::ranges::range_adaptor_closure { decltype(auto) operator()(const auto & triangleStrip) const { - return std::views::iota(strip_begin(triangleStrip), strip_end(triangleStrip)); + return std::views::iota(strip_begin(triangleStrip), strip_end(triangleStrip)) | dereference; } }; -constexpr TriangleTriplesImpl TriangleTriples; +inline constexpr TriangleTriples triangleTriples; template void diff --git a/lib/util.h b/lib/util.h index 2674eaf..cd7971b 100644 --- a/lib/util.h +++ b/lib/util.h @@ -29,7 +29,7 @@ namespace { }; } -template constexpr auto Nth = GetNth {}; -constexpr auto GetFirst = Nth<0>; -constexpr auto GetSecond = Nth<1>; -constexpr auto GetSwapped = Nth<0, 1>; +template inline constexpr auto Nth = GetNth {}; +inline constexpr auto GetFirst = Nth<0>; +inline constexpr auto GetSecond = Nth<1>; +inline constexpr auto GetSwapped = Nth<0, 1>; -- cgit v1.2.3 From 127cbcfafd91dca1c4211cbb15a881d782747214 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 23 Feb 2025 23:55:58 +0000 Subject: Add CLOGf for formatting logger --- lib/stream_support.h | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/stream_support.h b/lib/stream_support.h index f5c5e37..5f276fd 100644 --- a/lib/stream_support.h +++ b/lib/stream_support.h @@ -115,3 +115,4 @@ namespace { } #define CLOG(x) clogImpl(x, #x) +#define CLOGf(...) clogImpl(std::format(__VA_ARGS__), "msg") -- cgit v1.2.3