blob: 32052363d70762baef271ce662d774edbb2130d9 [file] [log] [blame]
Brian Silverman10fb0f32016-03-13 17:05:21 -04001#ifndef AOS_VISION_MATH_VECTOR_H_
2#define AOS_VISION_MATH_VECTOR_H_
3
4#include <cmath>
5
6#include "Eigen/Dense"
7
8namespace aos {
9namespace vision {
10
11// Represents an n-dimensional vector of doubles with various convenient
12// shortcuts for common operations.
13//
14// This includes overloads of various arithmetic operators for convenience.
15// Multiplication by doubles is scalar multiplication and multiplication by
16// other vectors is element-wise.
17//
18// Accessing elements which don't exist for a given size vector, mixing sizes of
19// vectors in appropriately, etc are compile-time errors.
20template <int size>
21class Vector {
22 public:
Parker Schuh6691f192017-01-14 17:01:02 -080023 Vector() : data_(::Eigen::Matrix<double, 1, size>::Zero()) {}
Brian Silverman10fb0f32016-03-13 17:05:21 -040024
25 Vector(double x, double y) { Set(x, y); }
26
27 Vector(double x, double y, double z) { Set(x, y, z); }
28
29 double Get(int index) const { return data_(index); }
30 void Set(int index, double value) { data_(index) = value; }
31
32 void Set(double x, double y) {
33 static_assert(size == 2, "illegal size");
34 data_(0) = x;
35 data_(1) = y;
36 }
37 void Set(double x, double y, double z) {
38 static_assert(size == 3, "illegal size");
39 data_(0) = x;
40 data_(1) = y;
41 data_(2) = z;
42 }
43 void Set(double x, double y, double z, double w) {
44 static_assert(size == 4, "illegal size");
45 data_(0) = x;
46 data_(1) = y;
47 data_(2) = z;
48 data_(3) = w;
49 }
50
51 double x() const {
52 static_assert(size >= 1, "illegal size");
53 return data_(0);
54 }
55 void x(double xX) {
56 static_assert(size >= 1, "illegal size");
57 data_(0) = xX;
58 }
59
60 double y() const {
61 static_assert(size >= 2, "illegal size");
62 return data_(1);
63 }
64 void y(double yY) {
65 static_assert(size >= 2, "illegal size");
66 data_(1) = yY;
67 }
68
69 double z() const {
70 static_assert(size >= 3, "illegal size");
71 return data_(2);
72 }
73 void z(double zZ) {
74 static_assert(size >= 3, "illegal size");
75 data_(2) = zZ;
76 }
77
78 double w() const {
79 static_assert(size >= 4, "illegal size");
80 return data_(3);
81 }
82 void w(double wW) {
83 static_assert(size >= 4, "illegal size");
84 data_(3) = wW;
85 }
86
87 // Fast part of length.
88 double MagSqr() const { return data_.squaredNorm(); }
89
90 // Length of the vector.
91 double Mag() const { return data_.norm(); }
92
93 // Get underlying data structure
94 ::Eigen::Matrix<double, 1, size> GetData() const { return data_; }
95
96 // Set underlying data structure
97 void SetData(const ::Eigen::Matrix<double, 1, size> &other) { data_ = other; }
98
99 Vector<size> operator+(const Vector<size> &other) const {
100 Vector<size> nv = *this;
101 nv += other;
102 return nv;
103 }
104 Vector<size> operator+=(const Vector<size> &other) {
105 data_ += other.data_;
106 return *this;
107 }
108
109 Vector<size> operator-(const Vector<size> &other) const {
110 Vector<size> nv = *this;
111 nv -= other;
112 return nv;
113 }
114 Vector<size> operator-=(const Vector<size> &other) {
115 data_ -= other.data_;
116 return *this;
117 }
118
119 Vector<size> operator*(double other) {
120 Vector<size> nv = *this;
121 nv *= other;
122 return nv;
123 }
124 Vector<size> operator*=(double other) {
125 data_ *= other;
126 return *this;
127 }
128
129 Vector<size> operator*(const Vector<size> &other) const {
130 Vector<size> nv = *this;
131 nv *= other;
132 return nv;
133 }
134 Vector<size> operator*=(const Vector<size> &other) {
135 for (int i = 0; i < size; i++) {
136 Set(i, other.Get(i) * Get(i));
137 }
138 return *this;
139 }
140
141 bool operator==(const Vector<size> &other) const {
142 for (int i = 0; i < size; i++) {
143 if (Get(i) != other.Get(i)) {
144 return false;
145 }
146 }
147 return true;
148 }
149
150 double dot(const Vector<size> &other) const {
151 return data_.dot(other.GetData());
152 }
153
154 Vector<size> cross(const Vector<size> &other) const {
155 Vector<size> nv;
156 nv.SetData(data_.cross(other.GetData()));
157 return nv;
158 }
159
160 // Returns a vector in the same direction as this one with a magnitude of 1.
161 Vector<size> Normalized() const {
162 double mag = Mag();
163 Vector<size> nv;
164 for (int i = 0; i < size; i++) {
165 nv.Set(i, Get(i) / mag);
166 }
167 return nv;
168 }
169
170 // Returns the angle between this vector and the 0 vector.
171 // Only valid for 2-dimensional vectors.
172 double AngleToZero() const {
173 static_assert(size == 2, "illegal size");
174 return ::std::atan2(y(), x());
175 }
176
177 // Return the angle between this and other.
Parker Schuh6691f192017-01-14 17:01:02 -0800178 double AngleTo(const Vector<size> &other) const {
Brian Silverman10fb0f32016-03-13 17:05:21 -0400179 // cos(theta) = u.dot(v) / (u.magnitude() * v.magnitude())
180 return ::std::acos(dot(other) / (Mag() * other.Mag()));
181 }
182
183 // Returns the distance between this and other squared.
Parker Schuh6691f192017-01-14 17:01:02 -0800184 double SquaredDistanceTo(const Vector<size> &other) const {
Brian Silverman10fb0f32016-03-13 17:05:21 -0400185 Vector<size> tmp = *this - other;
186 return tmp.MagSqr();
187 }
188
189 private:
190 // The actual data.
191 ::Eigen::Matrix<double, 1, size> data_;
192};
193
194// Returns the cross product of two points.
195inline double PointsCrossProduct(const Vector<2> &a, const Vector<2> &b) {
196 return a.x() * b.y() - a.y() * b.x();
197}
Parker Schuh6691f192017-01-14 17:01:02 -0800198// scalar multiply
199template <int Size>
200inline Vector<Size> operator*(const double &lhs, Vector<Size> &rhs) {
201 Vector<Size> nv;
202 for (int i = 0; i < Size; i++) {
203 nv.Set(i, lhs * rhs.Get(i));
204 }
205 return nv;
206}
Brian Silverman10fb0f32016-03-13 17:05:21 -0400207
208} // namespace vision
209} // namespace aos
210
211#endif // AOS_VISION_MATH_VECTOR_H_