diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-01-01 16:00:35 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-01-01 16:00:35 +0000 |
commit | c0d05b1ad0f2d82f9ce94437370648e7dfdd994e (patch) | |
tree | 47883cae257d6801bc8d9bfc2924ba2b323bdb27 /lib | |
parent | Walk terrain along a curve - edge cases exist (diff) | |
download | ilt-c0d05b1ad0f2d82f9ce94437370648e7dfdd994e.tar.bz2 ilt-c0d05b1ad0f2d82f9ce94437370648e7dfdd994e.tar.xz ilt-c0d05b1ad0f2d82f9ce94437370648e7dfdd994e.zip |
Return angle of intersection of arc with line
Diffstat (limited to 'lib')
-rw-r--r-- | lib/maths.h | 30 |
1 files changed, 15 insertions, 15 deletions
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<typename T, glm::qualifier Q = glm::defaultp> struct ArcSegment : publi PointType ep1; RelativeDistance radius; - [[nodiscard]] constexpr std::optional<glm::vec<2, T, Q>> crossesLineAt( + [[nodiscard]] constexpr std::optional<std::pair<glm::vec<2, T, Q>, 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<T, Q>::ArcSegment(PointType centre, PointType ep0, PointTyp } template<typename T, glm::qualifier Q> -[[nodiscard]] constexpr std::optional<glm::vec<2, T, Q>> +[[nodiscard]] constexpr std::optional<std::pair<glm::vec<2, T, Q>, Angle>> ArcSegment<T, Q>::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<T, Q>::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<std::pair<RelativePosition2D, Angle>, 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); } |