blob: 5a3df11e60789f5132bebff31d3be5a93804c2e4 [file] [log] [blame]
James Kuszmaul0af658b2019-01-25 18:36:29 -08001#ifndef AOS_UTIL_MATH_H_
2#define AOS_UTIL_MATH_H_
3
4#include <cmath>
5
6#include "Eigen/Dense"
7
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08008namespace aos::math {
James Kuszmaul0af658b2019-01-25 18:36:29 -08009
10// Normalizes an angle to be in (-M_PI, M_PI]
11template <typename Scalar>
12constexpr Scalar NormalizeAngle(Scalar theta) {
13 // First clause takes care of getting theta into
14 // (-3 * M_PI, M_PI)
15 const int n_pi_pos = (theta + M_PI) / 2.0 / M_PI;
16 theta -= n_pi_pos * 2.0 * M_PI;
17 // Next we fix it to cut off the bottom half of the above
18 // range and bring us into (-M_PI, M_PI]
19 const int n_pi_neg = (theta - M_PI) / 2.0 / M_PI;
20 theta -= n_pi_neg * 2.0 * M_PI;
21 return theta;
22}
23
24// Calculate a - b and return the result in (-M_PI, M_PI]
25template <typename Scalar>
26constexpr Scalar DiffAngle(Scalar a, Scalar b) {
27 return NormalizeAngle(a - b);
28}
29
30// Returns whether points A, B, C are arranged in a counter-clockwise manner on
31// a 2-D plane.
32// Collinear points of any sort will cause this to return false.
33// Source: https://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
34// Mathod:
35// 3 points on a plane will form a triangle (unless they are collinear), e.g.:
36// A-------------------C
37// \ /
38// \ /
39// \ /
40// \ /
41// \ /
42// \ /
43// \ /
44// \ /
45// \ /
46// B
47// We are interested in whether A->B->C is the counter-clockwise direction
48// around the triangle (it is in this picture).
49// Essentially, we want to know whether the angle between A->B and A->C is
50// positive or negative.
51// For this, consider the cross-product, where we imagine a third z-axis
52// coming out of the page. The cross-product AB x AC will be positive if ABC
53// is counter-clockwise and negative if clockwise (and zero if collinear).
54// The z-component (which is the only non-zero component) of the cross-product
55// is AC.y * AB.x - AB.y * AC.x > 0, which turns into:
56// AC.y * AB.x > AB.y * AC.x
57// (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x)
58// which is exactly what we have below.
59template <typename Scalar>
60constexpr bool PointsAreCCW(const Eigen::Ref<Eigen::Matrix<Scalar, 2, 1>> &A,
61 const Eigen::Ref<Eigen::Matrix<Scalar, 2, 1>> &B,
62 const Eigen::Ref<Eigen::Matrix<Scalar, 2, 1>> &C) {
63 return (C.y() - A.y()) * (B.x() - A.x()) > (B.y() - A.y()) * (C.x() - A.x());
64}
65
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080066} // namespace aos::math
James Kuszmaul0af658b2019-01-25 18:36:29 -080067
68#endif // AOS_UTIL_MATH_H_