Developer Documentation
Matrix3x3T.hh
1 #ifndef ACG_MATH_MATRIX3X3T_HH_
2 #define ACG_MATH_MATRIX3X3T_HH_
3 
4 #include <array>
5 #include <ostream>
6 #include <ACG/Math/VectorT.hh>
7 #include <algorithm>
8 #include <cmath>
9 #include <utility>
10 
11 #if defined(_MSC_VER) && _MSC_VER < 1900
12 #define constexpr
13 typedef unsigned char uint_fast8_t;
14 #endif
15 
16 namespace ACG {
17 
21 template<typename Scalar>
22 class Matrix3x3T {
23  public:
24  typedef typename OpenMesh::VectorT<Scalar, 3> Vec3;
25 
26  static Matrix3x3T<Scalar> fromColumns(Vec3 c1, Vec3 c2, Vec3 c3) {
27  return Matrix3x3T<Scalar> {{
28  c1[0], c2[0], c3[0],
29  c1[1], c2[1], c3[1],
30  c1[2], c2[2], c3[2],
31  }};
32  }
33 
34  static Matrix3x3T<Scalar> fromRows(Vec3 r1, Vec3 r2, Vec3 r3) {
35  return Matrix3x3T<Scalar> {{
36  r1[0], r1[1], r1[2],
37  r2[0], r2[1], r2[2],
38  r3[0], r3[1], r3[2]
39  }};
40  }
41 
42  static constexpr Matrix3x3T<Scalar> identity() {
43  return {{
44  1, 0, 0,
45  0, 1, 0,
46  0, 0, 1
47  }};
48  }
49 
50  static constexpr Matrix3x3T<Scalar> zero() {
51  return {{
52  0, 0, 0,
53  0, 0, 0,
54  0, 0, 0
55  }};
56  }
57 
58  public:
59  Matrix3x3T() = default;
60 
64  constexpr Matrix3x3T(std::array<Scalar, 9> row_major) :
65  values_(std::move(row_major)) {}
66 
67  constexpr bool operator==(const Matrix3x3T &rhs) const {
68  return values_ == rhs.values_;
69  }
70 
71  //Matrix3x3T(std::initializer_list<Scalar> row_major) {
72  // static_assert(row_major.size() == 9, "Need exactly 9 values.");
73  // std::copy(row_major.begin(), row_major.end(), this->begin());
74  //}
75 
77  constexpr static uint_fast8_t indexof(uint_fast8_t r, uint_fast8_t c) {
78  return r*3+c;
79  }
80 
81  constexpr const Scalar &operator() (uint_fast8_t r, uint_fast8_t c) const {
82  return values_[indexof(r, c)];
83  }
84 
85  Scalar &operator() (uint_fast8_t r, uint_fast8_t c) {
86  return values_[indexof(r, c)];
87  }
88 
90  constexpr const Scalar &operator[] (uint_fast8_t i) const {
91  return values_[i];
92  }
93 
95  Scalar &operator[] (uint_fast8_t i) {
96  return values_[i];
97  }
98 
99  Vec3 getRow(uint_fast8_t r) const {
100  return Vec3((*this)(r,0), (*this)(r,1), (*this)(r,2));
101  }
102  void setRow(uint_fast8_t r, const Vec3 &v) {
103  for (uint_fast8_t c = 0; c < 3; ++c) {
104  (*this)(r, c) = v[c];
105  }
106  }
107  Vec3 getCol(uint_fast8_t c) const {
108  return Vec3((*this)(0,c), (*this)(1,c), (*this)(2,c));
109  }
110  void setCol(uint_fast8_t c, const Vec3 &v) {
111  for (uint_fast8_t r = 0; r < 3; ++r) {
112  (*this)(r, c) = v[r];
113  }
114  }
115 
116  constexpr Matrix3x3T operator*(const Matrix3x3T &rhs) const {
117  return Matrix3x3T {{
118  (*this)(0, 0) * rhs(0, 0) + (*this)(0, 1) * rhs(1, 0) + (*this)(0, 2) * rhs(2, 0),
119  (*this)(0, 0) * rhs(0, 1) + (*this)(0, 1) * rhs(1, 1) + (*this)(0, 2) * rhs(2, 1),
120  (*this)(0, 0) * rhs(0, 2) + (*this)(0, 1) * rhs(1, 2) + (*this)(0, 2) * rhs(2, 2),
121 
122  (*this)(1, 0) * rhs(0, 0) + (*this)(1, 1) * rhs(1, 0) + (*this)(1, 2) * rhs(2, 0),
123  (*this)(1, 0) * rhs(0, 1) + (*this)(1, 1) * rhs(1, 1) + (*this)(1, 2) * rhs(2, 1),
124  (*this)(1, 0) * rhs(0, 2) + (*this)(1, 1) * rhs(1, 2) + (*this)(1, 2) * rhs(2, 2),
125 
126  (*this)(2, 0) * rhs(0, 0) + (*this)(2, 1) * rhs(1, 0) + (*this)(2, 2) * rhs(2, 0),
127  (*this)(2, 0) * rhs(0, 1) + (*this)(2, 1) * rhs(1, 1) + (*this)(2, 2) * rhs(2, 1),
128  (*this)(2, 0) * rhs(0, 2) + (*this)(2, 1) * rhs(1, 2) + (*this)(2, 2) * rhs(2, 2),
129  }};
130  }
131 
132  template<typename OtherScalar>
133  constexpr auto operator*(const VectorT<OtherScalar,3> &rhs) const
135  {
136  return {
137  (*this)(0, 0) * rhs[0] + (*this)(0, 1) * rhs[1] + (*this)(0, 2) * rhs[2],
138  (*this)(1, 0) * rhs[0] + (*this)(1, 1) * rhs[1] + (*this)(1, 2) * rhs[2],
139  (*this)(2, 0) * rhs[0] + (*this)(2, 1) * rhs[1] + (*this)(2, 2) * rhs[2]
140  };
141  }
142 
143  template<typename OtherScalar>
144  constexpr friend auto operator*(VectorT<OtherScalar,3> v, const Matrix3x3T &rhs)
146  {
147  return {
148  rhs(0, 0) * v[0] + rhs(0, 1) * v[1] + rhs(0, 2) * v[2],
149  rhs(1, 0) * v[0] + rhs(1, 1) * v[1] + rhs(1, 2) * v[2],
150  rhs(2, 0) * v[0] + rhs(2, 1) * v[1] + rhs(2, 2) * v[2]
151  };
152  }
153 
154  constexpr Matrix3x3T operator*(Scalar c) const {
155  return Matrix3x3T {{
156  (*this)[0] * c, (*this)[1] * c, (*this)[2] * c,
157  (*this)[3] * c, (*this)[4] * c, (*this)[5] * c,
158  (*this)[6] * c, (*this)[7] * c, (*this)[8] * c,
159  }};
160  }
161 
162  constexpr friend Matrix3x3T operator*(Scalar c, const Matrix3x3T &rhs) {
163  return Matrix3x3T {{
164  rhs[0] * c, rhs[1] * c, rhs[2] * c,
165  rhs[3] * c, rhs[4] * c, rhs[5] * c,
166  rhs[6] * c, rhs[7] * c, rhs[8] * c,
167  }};
168  }
169 
170  constexpr Matrix3x3T operator+ (const Matrix3x3T &rhs) const {
171  return Matrix3x3T {{
172  (*this)[0] + rhs[0], (*this)[1] + rhs[1], (*this)[2] + rhs[2],
173  (*this)[3] + rhs[3], (*this)[4] + rhs[4], (*this)[5] + rhs[5],
174  (*this)[6] + rhs[6], (*this)[7] + rhs[7], (*this)[8] + rhs[8],
175  }};
176  }
177 
178  constexpr Matrix3x3T operator- (const Matrix3x3T &rhs) const {
179  return Matrix3x3T {{
180  (*this)[0] - rhs[0], (*this)[1] - rhs[1], (*this)[2] - rhs[2],
181  (*this)[3] - rhs[3], (*this)[4] - rhs[4], (*this)[5] - rhs[5],
182  (*this)[6] - rhs[6], (*this)[7] - rhs[7], (*this)[8] - rhs[8],
183  }};
184  }
185 
186  constexpr Matrix3x3T operator- () const {
187  return Matrix3x3T {{
188  -values_[0], -values_[1], -values_[2],
189  -values_[3], -values_[4], -values_[5],
190  -values_[6], -values_[7], -values_[8]
191  }};
192  }
193 
194  const Matrix3x3T &operator*=(const Matrix3x3T &rhs) {
195  (*this) = operator*(rhs);
196  return *this;
197  }
198 
199  constexpr Scalar det() const {
200  return (*this)(0, 0) * ((*this)(1, 1) * (*this)(2, 2) - (*this)(2, 1) * (*this)(1, 2)) -
201  (*this)(0, 1) * ((*this)(1, 0) * (*this)(2, 2) - (*this)(1, 2) * (*this)(2, 0)) +
202  (*this)(0, 2) * ((*this)(1, 0) * (*this)(2, 1) - (*this)(1, 1) * (*this)(2, 0));
203 
204  /*
205  return (*this)(0, 0) * (*this)(1, 1) * (*this)(2, 2) +
206  (*this)(1, 0) * (*this)(2, 1) * (*this)(0, 2) +
207  (*this)(2, 0) * (*this)(0, 1) * (*this)(1, 2) -
208  (*this)(0, 0) * (*this)(2, 1) * (*this)(1, 2) -
209  (*this)(2, 0) * (*this)(1, 1) * (*this)(0, 2) -
210  (*this)(1, 0) * (*this)(0, 1) * (*this)(2, 2)
211  */
212  }
213 
214  constexpr Scalar trace() const {
215  return (*this)[0] + (*this)[4] + (*this)[8];
216  }
217 
218  void transpose() {
219  std::swap(values_[1], values_[3]);
220  std::swap(values_[2], values_[6]);
221  std::swap(values_[5], values_[7]);
222  }
223 
224  constexpr Matrix3x3T transposed() const {
225  return Matrix3x3T {{
226  values_[0], values_[3], values_[6],
227  values_[1], values_[4], values_[7],
228  values_[2], values_[5], values_[8],
229  }};
230  }
231 
232  void invert() {
233  *this = inverse();
234  }
235 
236  Matrix3x3T inverse() const {
237  const Scalar invdet = 1.0 / det();
238  return Matrix3x3T {{
239  ((*this)(1, 1) * (*this)(2, 2) - (*this)(2, 1) * (*this)(1, 2)) * invdet,
240  ((*this)(0, 2) * (*this)(2, 1) - (*this)(0, 1) * (*this)(2, 2)) * invdet,
241  ((*this)(0, 1) * (*this)(1, 2) - (*this)(0, 2) * (*this)(1, 1)) * invdet,
242  ((*this)(1, 2) * (*this)(2, 0) - (*this)(1, 0) * (*this)(2, 2)) * invdet,
243  ((*this)(0, 0) * (*this)(2, 2) - (*this)(0, 2) * (*this)(2, 0)) * invdet,
244  ((*this)(1, 0) * (*this)(0, 2) - (*this)(0, 0) * (*this)(1, 2)) * invdet,
245  ((*this)(1, 0) * (*this)(2, 1) - (*this)(2, 0) * (*this)(1, 1)) * invdet,
246  ((*this)(2, 0) * (*this)(0, 1) - (*this)(0, 0) * (*this)(2, 1)) * invdet,
247  ((*this)(0, 0) * (*this)(1, 1) - (*this)(1, 0) * (*this)(0, 1)) * invdet,
248  }};
249  }
250 
251  constexpr Scalar frobeniusSquared() const {
252  return std::inner_product(
253  values_.begin(), values_.end(), values_.begin(), Scalar(0.0));
254  }
255 
256  constexpr double frobenius() const {
257  return std::sqrt(frobeniusSquared());
258  }
259 
260 
261  friend
262  std::ostream &operator<< (std::ostream &os, const Matrix3x3T &m) {
263  os << "[[" << m[0] << ", " << m[1] << ", " << m[2] << "], "
264  "[" << m[3] << ", " << m[4] << ", " << m[5] << "], "
265  "[" << m[6] << ", " << m[7] << ", " << m[8] << "]]";
266  return os;
267  }
268 
269  private:
270  std::array<Scalar, 9> values_;
271 };
272 
275 
276 } /* namespace ACG */
277 
278 #if defined(_MSC_VER) && _MSC_VER < 1900
279 #undef constexpr
280 #endif
281 
282 #endif /* ACG_MATH_MATRIX3X3T_HH_ */
static constexpr uint_fast8_t indexof(uint_fast8_t r, uint_fast8_t c)
Map row/column index to linearized index.
Definition: Matrix3x3T.hh:77
Namespace providing different geometric functions concerning angles.
STL namespace.
constexpr const Scalar & operator[](uint_fast8_t i) const
Linearized row major access.
Definition: Matrix3x3T.hh:90
constexpr Matrix3x3T(std::array< Scalar, 9 > row_major)
Definition: Matrix3x3T.hh:64