summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2025-01-01 16:00:35 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2025-01-01 16:00:35 +0000
commitc0d05b1ad0f2d82f9ce94437370648e7dfdd994e (patch)
tree47883cae257d6801bc8d9bfc2924ba2b323bdb27 /lib
parentWalk terrain along a curve - edge cases exist (diff)
downloadilt-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.h30
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);
}