OpenVDB 13.0.0

Loading...
Searching...
No Matches
Mat3.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4#ifndef OPENVDB_MATH_MAT3_H_HAS_BEEN_INCLUDED
5#define OPENVDB_MATH_MAT3_H_HAS_BEEN_INCLUDED
6
7#include <openvdb/Exceptions.h>
8#include <openvdb/util/Assert.h>
9#include "Vec3.h"
10#include "Mat.h"
11#include <algorithm> // for std::copy()
12#include <cmath>
13#include <iomanip>
14
15
16 namespace openvdb {
17 OPENVDB_USE_VERSION_NAMESPACE
18 namespace OPENVDB_VERSION_NAME {
19 namespace math {
20
21 template<typename T> class Vec3;
22 template<typename T> class Mat4;
23 template<typename T> class Quat;
24
25/// @class Mat3 Mat3.h
26/// @brief 3x3 matrix class.
27 template<typename T>
28 class Mat3: public Mat<3, T>
29{
30 public:
31 /// Data type held by the matrix.
32 using value_type = T;
33 using ValueType = T;
34 using MyBase = Mat<3, T>;
35
36 /// Trivial constructor, the matrix is NOT initialized
37 /// @note destructor, copy constructor, assignment operator and
38 /// move constructor are left to be defined by the compiler (default)
39 Mat3() = default;
40
41 /// Constructor given the quaternion rotation, e.g. Mat3f m(q);
42 /// The quaternion is normalized and used to construct the matrix
43 Mat3(const Quat<T> &q)
44 { setToRotation(q); }
45
46
47 /// Constructor given array of elements, the ordering is in row major form:
48 /** @verbatim
49 a b c
50 d e f
51 g h i
52 @endverbatim */
53 template<typename Source>
54 Mat3(Source a, Source b, Source c,
55 Source d, Source e, Source f,
56 Source g, Source h, Source i)
57 {
58 MyBase::mm[0] = static_cast<T>(a);
59 MyBase::mm[1] = static_cast<T>(b);
60 MyBase::mm[2] = static_cast<T>(c);
61 MyBase::mm[3] = static_cast<T>(d);
62 MyBase::mm[4] = static_cast<T>(e);
63 MyBase::mm[5] = static_cast<T>(f);
64 MyBase::mm[6] = static_cast<T>(g);
65 MyBase::mm[7] = static_cast<T>(h);
66 MyBase::mm[8] = static_cast<T>(i);
67 } // constructor1Test
68
69 /// Construct matrix from rows or columns vectors (defaults to rows
70 /// for historical reasons)
71 template<typename Source>
72 Mat3(const Vec3<Source> &v1, const Vec3<Source> &v2, const Vec3<Source> &v3, bool rows = true)
73 {
74 if (rows) {
75 this->setRows(v1, v2, v3);
76 } else {
77 this->setColumns(v1, v2, v3);
78 }
79 }
80
81 /// Constructor given array of elements, the ordering is in row major form:\n
82 /// a[0] a[1] a[2]\n
83 /// a[3] a[4] a[5]\n
84 /// a[6] a[7] a[8]\n
85 template<typename Source>
86 Mat3(Source *a)
87 {
88 MyBase::mm[0] = static_cast<T>(a[0]);
89 MyBase::mm[1] = static_cast<T>(a[1]);
90 MyBase::mm[2] = static_cast<T>(a[2]);
91 MyBase::mm[3] = static_cast<T>(a[3]);
92 MyBase::mm[4] = static_cast<T>(a[4]);
93 MyBase::mm[5] = static_cast<T>(a[5]);
94 MyBase::mm[6] = static_cast<T>(a[6]);
95 MyBase::mm[7] = static_cast<T>(a[7]);
96 MyBase::mm[8] = static_cast<T>(a[8]);
97 } // constructor1Test
98
99 /// Conversion constructor
100 template<typename Source>
101 explicit Mat3(const Mat3<Source> &m)
102 {
103 for (int i=0; i<3; ++i) {
104 for (int j=0; j<3; ++j) {
105 MyBase::mm[i*3 + j] = static_cast<T>(m[i][j]);
106 }
107 }
108 }
109
110 /// Conversion from Mat4 (copies top left)
111 explicit Mat3(const Mat4<T> &m)
112 {
113 for (int i=0; i<3; ++i) {
114 for (int j=0; j<3; ++j) {
115 MyBase::mm[i*3 + j] = m[i][j];
116 }
117 }
118 }
119
120 /// Predefined constant for identity matrix
121 static const Mat3<T>& identity() {
122 static const Mat3<T> sIdentity = Mat3<T>(
123 1, 0, 0,
124 0, 1, 0,
125 0, 0, 1
126 );
127 return sIdentity;
128 }
129
130 /// Predefined constant for zero matrix
131 static const Mat3<T>& zero() {
132 static const Mat3<T> sZero = Mat3<T>(
133 0, 0, 0,
134 0, 0, 0,
135 0, 0, 0
136 );
137 return sZero;
138 }
139
140 /// Set ith row to vector v
141 void setRow(int i, const Vec3<T> &v)
142 {
143 OPENVDB_ASSERT(i>=0 && i<3);
144 int i3 = i * 3;
145
146 MyBase::mm[i3+0] = v[0];
147 MyBase::mm[i3+1] = v[1];
148 MyBase::mm[i3+2] = v[2];
149 } // rowColumnTest
150
151 /// Get ith row, e.g. Vec3d v = m.row(1);
152 Vec3<T> row(int i) const
153 {
154 OPENVDB_ASSERT(i>=0 && i<3);
155 return Vec3<T>((*this)(i,0), (*this)(i,1), (*this)(i,2));
156 } // rowColumnTest
157
158 /// Set jth column to vector v
159 void setCol(int j, const Vec3<T>& v)
160 {
161 OPENVDB_ASSERT(j>=0 && j<3);
162 MyBase::mm[0+j] = v[0];
163 MyBase::mm[3+j] = v[1];
164 MyBase::mm[6+j] = v[2];
165 } // rowColumnTest
166
167 /// Get jth column, e.g. Vec3d v = m.col(0);
168 Vec3<T> col(int j) const
169 {
170 OPENVDB_ASSERT(j>=0 && j<3);
171 return Vec3<T>((*this)(0,j), (*this)(1,j), (*this)(2,j));
172 } // rowColumnTest
173
174 /// Alternative indexed reference to the elements
175 /// Note that the indices are row first and column second.
176 /// e.g. m(0,0) = 1;
177 T& operator()(int i, int j)
178 {
179 OPENVDB_ASSERT(i>=0 && i<3);
180 OPENVDB_ASSERT(j>=0 && j<3);
181 return MyBase::mm[3*i+j];
182 } // trivial
183
184 /// Alternative indexed constant reference to the elements,
185 /// Note that the indices are row first and column second.
186 /// e.g. float f = m(1,0);
187 T operator()(int i, int j) const
188 {
189 OPENVDB_ASSERT(i>=0 && i<3);
190 OPENVDB_ASSERT(j>=0 && j<3);
191 return MyBase::mm[3*i+j];
192 } // trivial
193
194 /// Set the rows of this matrix to the vectors v1, v2, v3
195 void setRows(const Vec3<T> &v1, const Vec3<T> &v2, const Vec3<T> &v3)
196 {
197 MyBase::mm[0] = v1[0];
198 MyBase::mm[1] = v1[1];
199 MyBase::mm[2] = v1[2];
200 MyBase::mm[3] = v2[0];
201 MyBase::mm[4] = v2[1];
202 MyBase::mm[5] = v2[2];
203 MyBase::mm[6] = v3[0];
204 MyBase::mm[7] = v3[1];
205 MyBase::mm[8] = v3[2];
206 } // setRows
207
208 /// Set the columns of this matrix to the vectors v1, v2, v3
209 void setColumns(const Vec3<T> &v1, const Vec3<T> &v2, const Vec3<T> &v3)
210 {
211 MyBase::mm[0] = v1[0];
212 MyBase::mm[1] = v2[0];
213 MyBase::mm[2] = v3[0];
214 MyBase::mm[3] = v1[1];
215 MyBase::mm[4] = v2[1];
216 MyBase::mm[5] = v3[1];
217 MyBase::mm[6] = v1[2];
218 MyBase::mm[7] = v2[2];
219 MyBase::mm[8] = v3[2];
220 } // setColumns
221
222 /// Set diagonal and symmetric triangular components
223 void setSymmetric(const Vec3<T> &vdiag, const Vec3<T> &vtri)
224 {
225 MyBase::mm[0] = vdiag[0];
226 MyBase::mm[1] = vtri[0];
227 MyBase::mm[2] = vtri[1];
228 MyBase::mm[3] = vtri[0];
229 MyBase::mm[4] = vdiag[1];
230 MyBase::mm[5] = vtri[2];
231 MyBase::mm[6] = vtri[1];
232 MyBase::mm[7] = vtri[2];
233 MyBase::mm[8] = vdiag[2];
234 } // setSymmetricTest
235
236 /// Return a matrix with the prescribed diagonal and symmetric triangular components.
237 static Mat3 symmetric(const Vec3<T> &vdiag, const Vec3<T> &vtri)
238 {
239 return Mat3(
240 vdiag[0], vtri[0], vtri[1],
241 vtri[0], vdiag[1], vtri[2],
242 vtri[1], vtri[2], vdiag[2]
243 );
244 }
245
246 /// Set the matrix as cross product of the given vector
247 void setSkew(const Vec3<T> &v)
248 {*this = skew(v);}
249
250 /// @brief Set this matrix to the rotation matrix specified by the quaternion
251 /// @details The quaternion is normalized and used to construct the matrix.
252 /// Note that the matrix is transposed to match post-multiplication semantics.
253 void setToRotation(const Quat<T> &q)
254 {*this = rotation<Mat3<T> >(q);}
255
256 /// @brief Set this matrix to the rotation specified by @a axis and @a angle
257 /// @details The axis must be unit vector
258 void setToRotation(const Vec3<T> &axis, T angle)
259 {*this = rotation<Mat3<T> >(axis, angle);}
260
261 /// Set this matrix to zero
262 void setZero()
263 {
264 MyBase::mm[0] = 0;
265 MyBase::mm[1] = 0;
266 MyBase::mm[2] = 0;
267 MyBase::mm[3] = 0;
268 MyBase::mm[4] = 0;
269 MyBase::mm[5] = 0;
270 MyBase::mm[6] = 0;
271 MyBase::mm[7] = 0;
272 MyBase::mm[8] = 0;
273 } // trivial
274
275 /// Set this matrix to identity
276 void setIdentity()
277 {
278 MyBase::mm[0] = 1;
279 MyBase::mm[1] = 0;
280 MyBase::mm[2] = 0;
281 MyBase::mm[3] = 0;
282 MyBase::mm[4] = 1;
283 MyBase::mm[5] = 0;
284 MyBase::mm[6] = 0;
285 MyBase::mm[7] = 0;
286 MyBase::mm[8] = 1;
287 } // trivial
288
289 /// Assignment operator
290 template<typename Source>
291 const Mat3& operator=(const Mat3<Source> &m)
292 {
293 const Source *src = m.asPointer();
294
295 // don't suppress type conversion warnings
296 std::copy(src, (src + this->numElements()), MyBase::mm);
297 return *this;
298 } // opEqualToTest
299
300 /// Return @c true if this matrix is equivalent to @a m within a tolerance of @a eps.
301 bool eq(const Mat3 &m, T eps=T(1.0e-8)) const
302 {
303 return (isApproxEqual(MyBase::mm[0],m.mm[0],eps) &&
304 isApproxEqual(MyBase::mm[1],m.mm[1],eps) &&
305 isApproxEqual(MyBase::mm[2],m.mm[2],eps) &&
306 isApproxEqual(MyBase::mm[3],m.mm[3],eps) &&
307 isApproxEqual(MyBase::mm[4],m.mm[4],eps) &&
308 isApproxEqual(MyBase::mm[5],m.mm[5],eps) &&
309 isApproxEqual(MyBase::mm[6],m.mm[6],eps) &&
310 isApproxEqual(MyBase::mm[7],m.mm[7],eps) &&
311 isApproxEqual(MyBase::mm[8],m.mm[8],eps));
312 } // trivial
313
314 /// Negation operator, for e.g. m1 = -m2;
315 Mat3<T> operator-() const
316 {
317 return Mat3<T>(
318 -MyBase::mm[0], -MyBase::mm[1], -MyBase::mm[2],
319 -MyBase::mm[3], -MyBase::mm[4], -MyBase::mm[5],
320 -MyBase::mm[6], -MyBase::mm[7], -MyBase::mm[8]
321 );
322 } // trivial
323
324 /// Multiplication operator, e.g. M = scalar * M;
325 // friend Mat3 operator*(T scalar, const Mat3& m) {
326 // return m*scalar;
327 // }
328
329 /// Multiply each element of this matrix by @a scalar.
330 template <typename S>
331 const Mat3<T>& operator*=(S scalar)
332 {
333 MyBase::mm[0] *= scalar;
334 MyBase::mm[1] *= scalar;
335 MyBase::mm[2] *= scalar;
336 MyBase::mm[3] *= scalar;
337 MyBase::mm[4] *= scalar;
338 MyBase::mm[5] *= scalar;
339 MyBase::mm[6] *= scalar;
340 MyBase::mm[7] *= scalar;
341 MyBase::mm[8] *= scalar;
342 return *this;
343 }
344
345 /// Add each element of the given matrix to the corresponding element of this matrix.
346 template <typename S>
347 const Mat3<T> &operator+=(const Mat3<S> &m1)
348 {
349 const S *s = m1.asPointer();
350
351 MyBase::mm[0] += s[0];
352 MyBase::mm[1] += s[1];
353 MyBase::mm[2] += s[2];
354 MyBase::mm[3] += s[3];
355 MyBase::mm[4] += s[4];
356 MyBase::mm[5] += s[5];
357 MyBase::mm[6] += s[6];
358 MyBase::mm[7] += s[7];
359 MyBase::mm[8] += s[8];
360 return *this;
361 }
362
363 /// Subtract each element of the given matrix from the corresponding element of this matrix.
364 template <typename S>
365 const Mat3<T> &operator-=(const Mat3<S> &m1)
366 {
367 const S *s = m1.asPointer();
368
369 MyBase::mm[0] -= s[0];
370 MyBase::mm[1] -= s[1];
371 MyBase::mm[2] -= s[2];
372 MyBase::mm[3] -= s[3];
373 MyBase::mm[4] -= s[4];
374 MyBase::mm[5] -= s[5];
375 MyBase::mm[6] -= s[6];
376 MyBase::mm[7] -= s[7];
377 MyBase::mm[8] -= s[8];
378 return *this;
379 }
380
381 /// Multiply this matrix by the given matrix.
382 template <typename S>
383 const Mat3<T> &operator*=(const Mat3<S> &m1)
384 {
385 Mat3<T> m0(*this);
386 const T* s0 = m0.asPointer();
387 const S* s1 = m1.asPointer();
388
389 MyBase::mm[0] = static_cast<T>(s0[0] * s1[0] +
390 s0[1] * s1[3] +
391 s0[2] * s1[6]);
392 MyBase::mm[1] = static_cast<T>(s0[0] * s1[1] +
393 s0[1] * s1[4] +
394 s0[2] * s1[7]);
395 MyBase::mm[2] = static_cast<T>(s0[0] * s1[2] +
396 s0[1] * s1[5] +
397 s0[2] * s1[8]);
398
399 MyBase::mm[3] = static_cast<T>(s0[3] * s1[0] +
400 s0[4] * s1[3] +
401 s0[5] * s1[6]);
402 MyBase::mm[4] = static_cast<T>(s0[3] * s1[1] +
403 s0[4] * s1[4] +
404 s0[5] * s1[7]);
405 MyBase::mm[5] = static_cast<T>(s0[3] * s1[2] +
406 s0[4] * s1[5] +
407 s0[5] * s1[8]);
408
409 MyBase::mm[6] = static_cast<T>(s0[6] * s1[0] +
410 s0[7] * s1[3] +
411 s0[8] * s1[6]);
412 MyBase::mm[7] = static_cast<T>(s0[6] * s1[1] +
413 s0[7] * s1[4] +
414 s0[8] * s1[7]);
415 MyBase::mm[8] = static_cast<T>(s0[6] * s1[2] +
416 s0[7] * s1[5] +
417 s0[8] * s1[8]);
418
419 return *this;
420 }
421
422 /// @brief Return the cofactor matrix of this matrix.
423 [[nodiscard]] Mat3 cofactor() const
424 {
425 return Mat3<T>(
426 MyBase::mm[4] * MyBase::mm[8] - MyBase::mm[5] * MyBase::mm[7],
427 MyBase::mm[5] * MyBase::mm[6] - MyBase::mm[3] * MyBase::mm[8],
428 MyBase::mm[3] * MyBase::mm[7] - MyBase::mm[4] * MyBase::mm[6],
429 MyBase::mm[2] * MyBase::mm[7] - MyBase::mm[1] * MyBase::mm[8],
430 MyBase::mm[0] * MyBase::mm[8] - MyBase::mm[2] * MyBase::mm[6],
431 MyBase::mm[1] * MyBase::mm[6] - MyBase::mm[0] * MyBase::mm[7],
432 MyBase::mm[1] * MyBase::mm[5] - MyBase::mm[2] * MyBase::mm[4],
433 MyBase::mm[2] * MyBase::mm[3] - MyBase::mm[0] * MyBase::mm[5],
434 MyBase::mm[0] * MyBase::mm[4] - MyBase::mm[1] * MyBase::mm[3]);
435 }
436
437 /// Return the adjoint of this matrix, i.e., the transpose of its cofactor.
438 [[nodiscard]] Mat3 adjoint() const
439 {
440 return Mat3<T>(
441 MyBase::mm[4] * MyBase::mm[8] - MyBase::mm[5] * MyBase::mm[7],
442 MyBase::mm[2] * MyBase::mm[7] - MyBase::mm[1] * MyBase::mm[8],
443 MyBase::mm[1] * MyBase::mm[5] - MyBase::mm[2] * MyBase::mm[4],
444 MyBase::mm[5] * MyBase::mm[6] - MyBase::mm[3] * MyBase::mm[8],
445 MyBase::mm[0] * MyBase::mm[8] - MyBase::mm[2] * MyBase::mm[6],
446 MyBase::mm[2] * MyBase::mm[3] - MyBase::mm[0] * MyBase::mm[5],
447 MyBase::mm[3] * MyBase::mm[7] - MyBase::mm[4] * MyBase::mm[6],
448 MyBase::mm[1] * MyBase::mm[6] - MyBase::mm[0] * MyBase::mm[7],
449 MyBase::mm[0] * MyBase::mm[4] - MyBase::mm[1] * MyBase::mm[3]);
450
451 } // adjointTest
452
453 /// returns transpose of this
454 Mat3 transpose() const
455 {
456 return Mat3<T>(
457 MyBase::mm[0], MyBase::mm[3], MyBase::mm[6],
458 MyBase::mm[1], MyBase::mm[4], MyBase::mm[7],
459 MyBase::mm[2], MyBase::mm[5], MyBase::mm[8]);
460
461 } // transposeTest
462
463 /// returns inverse of this
464 /// @throws ArithmeticError if singular
465 [[nodiscard]] Mat3 inverse(T tolerance = 0) const
466 {
467 Mat3<T> inv(this->adjoint());
468
469 const T det = inv.mm[0]*MyBase::mm[0] + inv.mm[1]*MyBase::mm[3] + inv.mm[2]*MyBase::mm[6];
470
471 // If the determinant is 0, m was singular and the result will be invalid.
472 if (isApproxEqual(det,T(0.0),tolerance)) {
473 OPENVDB_THROW(ArithmeticError, "Inversion of singular 3x3 matrix");
474 }
475 return inv * (T(1)/det);
476 } // invertTest
477
478 /// Determinant of matrix
479 T det() const
480 {
481 const T co00 = MyBase::mm[4]*MyBase::mm[8] - MyBase::mm[5]*MyBase::mm[7];
482 const T co10 = MyBase::mm[5]*MyBase::mm[6] - MyBase::mm[3]*MyBase::mm[8];
483 const T co20 = MyBase::mm[3]*MyBase::mm[7] - MyBase::mm[4]*MyBase::mm[6];
484 return MyBase::mm[0]*co00 + MyBase::mm[1]*co10 + MyBase::mm[2]*co20;
485 } // determinantTest
486
487 /// Trace of matrix
488 T trace() const
489 {
490 return MyBase::mm[0]+MyBase::mm[4]+MyBase::mm[8];
491 }
492
493 /// This function snaps a specific axis to a specific direction,
494 /// preserving scaling. It does this using minimum energy, thus
495 /// posing a unique solution if basis & direction arent parralel.
496 /// Direction need not be unit.
497 Mat3 snapBasis(Axis axis, const Vec3<T> &direction)
498 {
499 return snapMatBasis(*this, axis, direction);
500 }
501
502 /// Return the transformed vector by this matrix.
503 /// This function is equivalent to post-multiplying the matrix.
504 template<typename T0>
505 Vec3<T0> transform(const Vec3<T0> &v) const
506 {
507 return static_cast< Vec3<T0> >(v * *this);
508 } // xformVectorTest
509
510 /// Return the transformed vector by transpose of this matrix.
511 /// This function is equivalent to pre-multiplying the matrix.
512 template<typename T0>
513 Vec3<T0> pretransform(const Vec3<T0> &v) const
514 {
515 return static_cast< Vec3<T0> >(*this * v);
516 } // xformTVectorTest
517
518
519 /// @brief Treat @a diag as a diagonal matrix and return the product
520 /// of this matrix with @a diag (from the right).
521 [[nodiscard]] Mat3 timesDiagonal(const Vec3<T>& diag) const
522 {
523 Mat3 ret(*this);
524
525 ret.mm[0] *= diag(0);
526 ret.mm[1] *= diag(1);
527 ret.mm[2] *= diag(2);
528 ret.mm[3] *= diag(0);
529 ret.mm[4] *= diag(1);
530 ret.mm[5] *= diag(2);
531 ret.mm[6] *= diag(0);
532 ret.mm[7] *= diag(1);
533 ret.mm[8] *= diag(2);
534 return ret;
535 }
536}; // class Mat3
537
538
539/// @relates Mat3
540/// @brief Equality operator, does exact floating point comparisons
541 template <typename T0, typename T1>
542 bool operator==(const Mat3<T0> &m0, const Mat3<T1> &m1)
543{
544 const T0 *t0 = m0.asPointer();
545 const T1 *t1 = m1.asPointer();
546
547 for (int i=0; i<9; ++i) {
548 if (!isExactlyEqual(t0[i], t1[i])) return false;
549 }
550 return true;
551}
552
553/// @relates Mat3
554/// @brief Inequality operator, does exact floating point comparisons
555 template <typename T0, typename T1>
556 bool operator!=(const Mat3<T0> &m0, const Mat3<T1> &m1) { return !(m0 == m1); }
557
558/// @relates Mat3
559/// @brief Multiply each element of the given matrix by @a scalar and return the result.
560 template <typename S, typename T>
561 Mat3<typename promote<S, T>::type> operator*(S scalar, const Mat3<T> &m)
562{ return m*scalar; }
563
564/// @relates Mat3
565/// @brief Multiply each element of the given matrix by @a scalar and return the result.
566 template <typename S, typename T>
567 Mat3<typename promote<S, T>::type> operator*(const Mat3<T> &m, S scalar)
568{
569 Mat3<typename promote<S, T>::type> result(m);
570 result *= scalar;
571 return result;
572}
573
574/// @relates Mat3
575/// @brief Add corresponding elements of @a m0 and @a m1 and return the result.
576 template <typename T0, typename T1>
577 Mat3<typename promote<T0, T1>::type> operator+(const Mat3<T0> &m0, const Mat3<T1> &m1)
578{
579 Mat3<typename promote<T0, T1>::type> result(m0);
580 result += m1;
581 return result;
582}
583
584/// @relates Mat3
585/// @brief Subtract corresponding elements of @a m0 and @a m1 and return the result.
586 template <typename T0, typename T1>
587 Mat3<typename promote<T0, T1>::type> operator-(const Mat3<T0> &m0, const Mat3<T1> &m1)
588{
589 Mat3<typename promote<T0, T1>::type> result(m0);
590 result -= m1;
591 return result;
592}
593
594
595/// @brief Multiply @a m0 by @a m1 and return the resulting matrix.
596 template <typename T0, typename T1>
597 Mat3<typename promote<T0, T1>::type>operator*(const Mat3<T0> &m0, const Mat3<T1> &m1)
598{
599 Mat3<typename promote<T0, T1>::type> result(m0);
600 result *= m1;
601 return result;
602}
603
604/// @relates Mat3
605/// @brief Multiply @a _m by @a _v and return the resulting vector.
606 template<typename T, typename MT>
607 inline Vec3<typename promote<T, MT>::type>
608 operator*(const Mat3<MT> &_m, const Vec3<T> &_v)
609{
610 MT const *m = _m.asPointer();
611 return Vec3<typename promote<T, MT>::type>(
612 _v[0]*m[0] + _v[1]*m[1] + _v[2]*m[2],
613 _v[0]*m[3] + _v[1]*m[4] + _v[2]*m[5],
614 _v[0]*m[6] + _v[1]*m[7] + _v[2]*m[8]);
615}
616
617/// @relates Mat3
618/// @brief Multiply @a _v by @a _m and return the resulting vector.
619 template<typename T, typename MT>
620 inline Vec3<typename promote<T, MT>::type>
621 operator*(const Vec3<T> &_v, const Mat3<MT> &_m)
622{
623 MT const *m = _m.asPointer();
624 return Vec3<typename promote<T, MT>::type>(
625 _v[0]*m[0] + _v[1]*m[3] + _v[2]*m[6],
626 _v[0]*m[1] + _v[1]*m[4] + _v[2]*m[7],
627 _v[0]*m[2] + _v[1]*m[5] + _v[2]*m[8]);
628}
629
630/// @relates Mat3
631/// @brief Multiply @a _v by @a _m and replace @a _v with the resulting vector.
632 template<typename T, typename MT>
633 inline Vec3<T> &operator *= (Vec3<T> &_v, const Mat3<MT> &_m)
634{
635 Vec3<T> mult = _v * _m;
636 _v = mult;
637 return _v;
638}
639
640/// Returns outer product of v1, v2, i.e. v1 v2^T if v1 and v2 are
641/// column vectors, e.g. M = Mat3f::outerproduct(v1,v2);
642 template <typename T>
643 Mat3<T> outerProduct(const Vec3<T>& v1, const Vec3<T>& v2)
644{
645 return Mat3<T>(v1[0]*v2[0], v1[0]*v2[1], v1[0]*v2[2],
646 v1[1]*v2[0], v1[1]*v2[1], v1[1]*v2[2],
647 v1[2]*v2[0], v1[2]*v2[1], v1[2]*v2[2]);
648}// outerProduct
649
650
651/// Interpolate the rotation between m1 and m2 using Mat::powSolve.
652/// Unlike slerp, translation is not treated independently.
653/// This results in smoother animation results.
654 template<typename T, typename T0>
655 Mat3<T> powLerp(const Mat3<T0> &m1, const Mat3<T0> &m2, T t)
656{
657 Mat3<T> x = m1.inverse() * m2;
658 powSolve(x, x, t);
659 Mat3<T> m = m1 * x;
660 return m;
661}
662
663
664 namespace mat3_internal {
665
666 template<typename T>
667 inline void
668 pivot(int i, int j, Mat3<T>& S, Vec3<T>& D, Mat3<T>& Q)
669{
670 const int& n = Mat3<T>::size; // should be 3
671 T temp;
672 /// scratch variables used in pivoting
673 double cotan_of_2_theta;
674 double tan_of_theta;
675 double cosin_of_theta;
676 double sin_of_theta;
677 double z;
678
679 double Sij = S(i,j);
680
681 double Sjj_minus_Sii = D[j] - D[i];
682
683 if (std::abs(Sjj_minus_Sii) * (10*math::Tolerance<T>::value()) > std::abs(Sij)) {
684 tan_of_theta = Sij / Sjj_minus_Sii;
685 } else {
686 /// pivot on Sij
687 cotan_of_2_theta = 0.5*Sjj_minus_Sii / Sij ;
688
689 if (cotan_of_2_theta < 0.) {
690 tan_of_theta =
691 -1./(std::sqrt(1. + cotan_of_2_theta*cotan_of_2_theta) - cotan_of_2_theta);
692 } else {
693 tan_of_theta =
694 1./(std::sqrt(1. + cotan_of_2_theta*cotan_of_2_theta) + cotan_of_2_theta);
695 }
696 }
697
698 cosin_of_theta = 1./std::sqrt( 1. + tan_of_theta * tan_of_theta);
699 sin_of_theta = cosin_of_theta * tan_of_theta;
700 z = tan_of_theta * Sij;
701 S(i,j) = 0;
702 D[i] -= T(z);
703 D[j] += T(z);
704 for (int k = 0; k < i; ++k) {
705 temp = S(k,i);
706 S(k,i) = T(cosin_of_theta * temp - sin_of_theta * S(k,j));
707 S(k,j) = T(sin_of_theta * temp + cosin_of_theta * S(k,j));
708 }
709 for (int k = i+1; k < j; ++k) {
710 temp = S(i,k);
711 S(i,k) = T(cosin_of_theta * temp - sin_of_theta * S(k,j));
712 S(k,j) = T(sin_of_theta * temp + cosin_of_theta * S(k,j));
713 }
714 for (int k = j+1; k < n; ++k) {
715 temp = S(i,k);
716 S(i,k) = T(cosin_of_theta * temp - sin_of_theta * S(j,k));
717 S(j,k) = T(sin_of_theta * temp + cosin_of_theta * S(j,k));
718 }
719 for (int k = 0; k < n; ++k) {
720 temp = Q(k,i);
721 Q(k,i) = T(cosin_of_theta * temp - sin_of_theta * Q(k,j));
722 Q(k,j) = T(sin_of_theta * temp + cosin_of_theta * Q(k,j));
723 }
724}
725
726} // namespace mat3_internal
727
728
729/// @brief Use Jacobi iterations to decompose a symmetric 3x3 matrix
730/// (diagonalize and compute eigenvectors)
731/// @details This is based on the "Efficient numerical diagonalization of Hermitian 3x3 matrices"
732/// Joachim Kopp. arXiv.org preprint: physics/0610206
733/// with the addition of largest pivot
734 template<typename T>
735 inline bool
736 diagonalizeSymmetricMatrix(const Mat3<T>& input, Mat3<T>& Q, Vec3<T>& D,
737 unsigned int MAX_ITERATIONS=250)
738{
739 /// use Givens rotation matrix to eliminate off-diagonal entries.
740 /// initialize the rotation matrix as idenity
741 Q = Mat3<T>::identity();
742 int n = Mat3<T>::size; // should be 3
743
744 /// temp matrix. Assumed to be symmetric
745 Mat3<T> S(input);
746
747 for (int i = 0; i < n; ++i) {
748 D[i] = S(i,i);
749 }
750
751 unsigned int iterations(0);
752 /// Just iterate over all the non-diagonal enteries
753 /// using the largest as a pivot.
754 do {
755 /// check for absolute convergence
756 /// are symmetric off diagonals all zero
757 double er = 0;
758 for (int i = 0; i < n; ++i) {
759 for (int j = i+1; j < n; ++j) {
760 er += std::abs(S(i,j));
761 }
762 }
763 if (std::abs(er) < math::Tolerance<T>::value()) {
764 return true;
765 }
766 iterations++;
767
768 T max_element = 0;
769 int ip = 0;
770 int jp = 0;
771 /// loop over all the off-diagonals above the diagonal
772 for (int i = 0; i < n; ++i) {
773 for (int j = i+1; j < n; ++j){
774
775 if ( std::abs(D[i]) * (10*math::Tolerance<T>::value()) > std::abs(S(i,j))) {
776 /// value too small to pivot on
777 S(i,j) = 0;
778 }
779 if (std::abs(S(i,j)) > max_element) {
780 max_element = std::abs(S(i,j));
781 ip = i;
782 jp = j;
783 }
784 }
785 }
786 mat3_internal::pivot(ip, jp, S, D, Q);
787 } while (iterations < MAX_ITERATIONS);
788
789 return false;
790}
791
792 template<typename T>
793 inline Mat3<T>
794 Abs(const Mat3<T>& m)
795{
796 Mat3<T> out;
797 const T* ip = m.asPointer();
798 T* op = out.asPointer();
799 for (unsigned i = 0; i < 9; ++i, ++op, ++ip) *op = math::Abs(*ip);
800 return out;
801}
802
803 template<typename Type1, typename Type2>
804 inline Mat3<Type1>
805 cwiseAdd(const Mat3<Type1>& m, const Type2 s)
806{
807 Mat3<Type1> out;
808 const Type1* ip = m.asPointer();
809 Type1* op = out.asPointer();
810 for (unsigned i = 0; i < 9; ++i, ++op, ++ip) {
811 OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
812 *op = *ip + s;
813 OPENVDB_NO_TYPE_CONVERSION_WARNING_END
814 }
815 return out;
816}
817
818 template<typename T>
819 inline bool
820 cwiseLessThan(const Mat3<T>& m0, const Mat3<T>& m1)
821{
822 return cwiseLessThan<3, T>(m0, m1);
823}
824
825 template<typename T>
826 inline bool
827 cwiseGreaterThan(const Mat3<T>& m0, const Mat3<T>& m1)
828{
829 return cwiseGreaterThan<3, T>(m0, m1);
830}
831
832 using Mat3s = Mat3<float>;
833 using Mat3d = Mat3<double>;
834 using Mat3f = Mat3d;
835
836 OPENVDB_IS_POD(Mat3s)
837 OPENVDB_IS_POD(Mat3d)
838
839} // namespace math
840
841
842 template<> inline math::Mat3s zeroVal<math::Mat3s>() { return math::Mat3s::zero(); }
843 template<> inline math::Mat3d zeroVal<math::Mat3d>() { return math::Mat3d::zero(); }
844
845} // namespace OPENVDB_VERSION_NAME
846} // namespace openvdb
847
848#endif // OPENVDB_MATH_MAT3_H_HAS_BEEN_INCLUDED
Assert.h
OPENVDB_ASSERT
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Mat.h
OPENVDB_IS_POD
#define OPENVDB_IS_POD(Type)
Definition Math.h:57
OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
Bracket code with OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN/_END, to inhibit warnings about type conve...
Definition Platform.h:244
OPENVDB_NO_TYPE_CONVERSION_WARNING_END
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition Platform.h:245
Vec3.h
openvdb::v13_0::ArithmeticError
Definition Exceptions.h:56
openvdb::v13_0::math::Mat3
3x3 matrix class.
Definition Mat3.h:29
openvdb::v13_0::math::Mat3::Mat3
Mat3(Source *a)
Definition Mat3.h:86
openvdb::v13_0::math::Mat3::Mat3
Mat3(const Mat4< T > &m)
Conversion from Mat4 (copies top left).
Definition Mat3.h:111
openvdb::v13_0::math::Mat3::eq
bool eq(const Mat3 &m, T eps=T(1.0e-8)) const
Return true if this matrix is equivalent to m within a tolerance of eps.
Definition Mat3.h:301
openvdb::v13_0::math::Mat3::operator-=
const Mat3< T > & operator-=(const Mat3< S > &m1)
Subtract each element of the given matrix from the corresponding element of this matrix.
Definition Mat3.h:365
openvdb::v13_0::math::Mat3< Real >::setRows
void setRows(const Vec3< Real > &v1, const Vec3< Real > &v2, const Vec3< Real > &v3)
Definition Mat3.h:195
openvdb::v13_0::math::Mat3::operator*
Mat3< typename promote< S, T >::type > operator*(S scalar, const Mat3< T > &m)
Multiply each element of the given matrix by scalar and return the result.
Definition Mat3.h:561
openvdb::v13_0::math::Mat3::operator!=
bool operator!=(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Inequality operator, does exact floating point comparisons.
Definition Mat3.h:556
openvdb::v13_0::math::Mat3::Mat3
Mat3()=default
openvdb::v13_0::math::Mat3::operator+
Mat3< typename promote< T0, T1 >::type > operator+(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Add corresponding elements of m0 and m1 and return the result.
Definition Mat3.h:577
openvdb::v13_0::math::Mat3::operator*
Mat3< typename promote< S, T >::type > operator*(const Mat3< T > &m, S scalar)
Multiply each element of the given matrix by scalar and return the result.
Definition Mat3.h:567
openvdb::v13_0::math::Mat3::setIdentity
void setIdentity()
Set this matrix to identity.
Definition Mat3.h:276
openvdb::v13_0::math::Mat3::Mat3
Mat3(Source a, Source b, Source c, Source d, Source e, Source f, Source g, Source h, Source i)
Constructor given array of elements, the ordering is in row major form:
Definition Mat3.h:54
openvdb::v13_0::math::Mat3::Mat3
Mat3(const Mat3< Source > &m)
Conversion constructor.
Definition Mat3.h:101
openvdb::v13_0::math::Mat3::setToRotation
void setToRotation(const Vec3< T > &axis, T angle)
Set this matrix to the rotation specified by axis and angle.
Definition Mat3.h:258
openvdb::v13_0::math::Mat3::setZero
void setZero()
Set this matrix to zero.
Definition Mat3.h:262
openvdb::v13_0::math::Mat3::operator=
const Mat3 & operator=(const Mat3< Source > &m)
Assignment operator.
Definition Mat3.h:291
openvdb::v13_0::math::Mat3::Mat3
Mat3(const Quat< T > &q)
Definition Mat3.h:43
openvdb::v13_0::math::Mat3::operator+=
const Mat3< T > & operator+=(const Mat3< S > &m1)
Add each element of the given matrix to the corresponding element of this matrix.
Definition Mat3.h:347
openvdb::v13_0::math::Mat3::pretransform
Vec3< T0 > pretransform(const Vec3< T0 > &v) const
Definition Mat3.h:513
openvdb::v13_0::math::Mat3< Real >::setToRotation
void setToRotation(const Quat< Real > &q)
Definition Mat3.h:253
openvdb::v13_0::math::Mat3::inverse
Mat3 inverse(T tolerance=0) const
Definition Mat3.h:465
openvdb::v13_0::math::Mat3::trace
T trace() const
Trace of matrix.
Definition Mat3.h:488
openvdb::v13_0::math::Mat3::operator-
Mat3< T > operator-() const
Negation operator, for e.g. m1 = -m2;.
Definition Mat3.h:315
openvdb::v13_0::math::Mat3::setCol
void setCol(int j, const Vec3< T > &v)
Set jth column to vector v.
Definition Mat3.h:159
openvdb::v13_0::math::Mat3::adjoint
Mat3 adjoint() const
Return the adjoint of this matrix, i.e., the transpose of its cofactor.
Definition Mat3.h:438
openvdb::v13_0::math::Mat3::setSkew
void setSkew(const Vec3< T > &v)
Set the matrix as cross product of the given vector.
Definition Mat3.h:247
openvdb::v13_0::math::Mat3::operator*=
const Mat3< T > & operator*=(S scalar)
Multiplication operator, e.g. M = scalar * M;.
Definition Mat3.h:331
openvdb::v13_0::math::Mat3< Real >::MyBase
Mat< 3, Real > MyBase
Definition Mat3.h:34
openvdb::v13_0::math::Mat3::operator*
Vec3< typename promote< T, MT >::type > operator*(const Mat3< MT > &_m, const Vec3< T > &_v)
Multiply _m by _v and return the resulting vector.
Definition Mat3.h:608
openvdb::v13_0::math::Mat3::snapBasis
Mat3 snapBasis(Axis axis, const Vec3< T > &direction)
Definition Mat3.h:497
openvdb::v13_0::math::Mat3::transpose
Mat3 transpose() const
returns transpose of this
Definition Mat3.h:454
openvdb::v13_0::math::Mat3::timesDiagonal
Mat3 timesDiagonal(const Vec3< T > &diag) const
Treat diag as a diagonal matrix and return the product of this matrix with diag (from the right).
Definition Mat3.h:521
openvdb::v13_0::math::Mat3< Real >::det
Real det() const
Definition Mat3.h:479
openvdb::v13_0::math::Mat3::zero
static const Mat3< T > & zero()
Predefined constant for zero matrix.
Definition Mat3.h:131
openvdb::v13_0::math::Mat3::col
Vec3< T > col(int j) const
Get jth column, e.g. Vec3d v = m.col(0);.
Definition Mat3.h:168
openvdb::v13_0::math::Mat3::operator()
T & operator()(int i, int j)
Definition Mat3.h:177
openvdb::v13_0::math::Mat3::symmetric
static Mat3 symmetric(const Vec3< T > &vdiag, const Vec3< T > &vtri)
Return a matrix with the prescribed diagonal and symmetric triangular components.
Definition Mat3.h:237
openvdb::v13_0::math::Mat3::transform
Vec3< T0 > transform(const Vec3< T0 > &v) const
Definition Mat3.h:505
openvdb::v13_0::math::Mat3::identity
static const Mat3< T > & identity()
Predefined constant for identity matrix.
Definition Mat3.h:121
openvdb::v13_0::math::Mat3::operator()
T operator()(int i, int j) const
Definition Mat3.h:187
openvdb::v13_0::math::Mat3::operator==
bool operator==(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Equality operator, does exact floating point comparisons.
Definition Mat3.h:542
openvdb::v13_0::math::Mat3::operator*=
const Mat3< T > & operator*=(const Mat3< S > &m1)
Multiply this matrix by the given matrix.
Definition Mat3.h:383
openvdb::v13_0::math::Mat3::row
Vec3< T > row(int i) const
Get ith row, e.g. Vec3d v = m.row(1);.
Definition Mat3.h:152
openvdb::v13_0::math::Mat3::setRow
void setRow(int i, const Vec3< T > &v)
Set ith row to vector v.
Definition Mat3.h:141
openvdb::v13_0::math::Mat3::operator*
Vec3< typename promote< T, MT >::type > operator*(const Vec3< T > &_v, const Mat3< MT > &_m)
Multiply _v by _m and return the resulting vector.
Definition Mat3.h:621
openvdb::v13_0::math::Mat3< Real >::ValueType
Real ValueType
Definition Mat3.h:33
openvdb::v13_0::math::Mat3< Real >::setColumns
void setColumns(const Vec3< Real > &v1, const Vec3< Real > &v2, const Vec3< Real > &v3)
Definition Mat3.h:209
openvdb::v13_0::math::Mat3::cofactor
Mat3 cofactor() const
Return the cofactor matrix of this matrix.
Definition Mat3.h:423
openvdb::v13_0::math::Mat3::operator-
Mat3< typename promote< T0, T1 >::type > operator-(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Subtract corresponding elements of m0 and m1 and return the result.
Definition Mat3.h:587
openvdb::v13_0::math::Mat3::Mat3
Mat3(const Vec3< Source > &v1, const Vec3< Source > &v2, const Vec3< Source > &v3, bool rows=true)
Definition Mat3.h:72
openvdb::v13_0::math::Mat3::setSymmetric
void setSymmetric(const Vec3< T > &vdiag, const Vec3< T > &vtri)
Set diagonal and symmetric triangular components.
Definition Mat3.h:223
openvdb::v13_0::math::Mat3< Real >::value_type
Real value_type
Definition Mat3.h:32
openvdb::v13_0::math::Mat4
4x4 -matrix class.
Definition Mat4.h:31
openvdb::v13_0::math::Mat::mm
T mm[SIZE *SIZE]
Definition Mat.h:160
openvdb::v13_0::math::Mat< 3, T >::Mat
Mat()=default
openvdb::v13_0::math::Mat::asPointer
T * asPointer()
Direct access to the internal data.
Definition Mat.h:101
openvdb::v13_0::math::Mat< 3, T >::size
@ size
Definition Mat.h:31
openvdb::v13_0::math::Mat3< Real >::numElements
static unsigned numElements()
Definition Mat.h:41
openvdb::v13_0::math::Quat
Definition Quat.h:80
openvdb::v13_0::math::Vec3
Definition Vec3.h:25
openvdb::v13_0::math::mat3_internal
Definition Mat3.h:664
openvdb::v13_0::math::mat3_internal::pivot
void pivot(int i, int j, Mat3< T > &S, Vec3< T > &D, Mat3< T > &Q)
Definition Mat3.h:668
openvdb::v13_0::math::snapMatBasis
MatType snapMatBasis(const MatType &source, Axis axis, const Vec3< typename MatType::value_type > &direction)
This function snaps a specific axis to a specific direction, preserving scaling.
Definition Mat.h:751
openvdb::v13_0::math::diagonalizeSymmetricMatrix
bool diagonalizeSymmetricMatrix(const Mat3< T > &input, Mat3< T > &Q, Vec3< T > &D, unsigned int MAX_ITERATIONS=250)
Use Jacobi iterations to decompose a symmetric 3x3 matrix (diagonalize and compute eigenvectors).
Definition Mat3.h:736
openvdb::v13_0::math::operator*
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition Mat3.h:597
openvdb::v13_0::math::Mat3d
Mat3< double > Mat3d
Definition Mat3.h:833
openvdb::v13_0::math::cwiseLessThan
bool cwiseLessThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition Mat.h:1015
openvdb::v13_0::math::isApproxEqual
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition Math.h:431
openvdb::v13_0::math::Mat3s
Mat3< float > Mat3s
Definition Mat3.h:832
openvdb::v13_0::math::rotation
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the rotation matrix specified by the given quaternion.
Definition Mat.h:172
openvdb::v13_0::math::powLerp
Mat3< T > powLerp(const Mat3< T0 > &m1, const Mat3< T0 > &m2, T t)
Definition Mat3.h:655
openvdb::v13_0::math::Mat3f
Mat3d Mat3f
Definition Mat3.h:834
openvdb::v13_0::math::Abs
Coord Abs(const Coord &xyz)
Definition Coord.h:518
openvdb::v13_0::math::outerProduct
Mat3< T > outerProduct(const Vec3< T > &v1, const Vec3< T > &v2)
Definition Mat3.h:643
openvdb::v13_0::math::angle
T angle(const Vec2< T > &v1, const Vec2< T > &v2)
Definition Vec2.h:446
openvdb::v13_0::math::powSolve
void powSolve(const MatType &aA, MatType &aB, double aPower, double aTol=0.01)
Definition Mat.h:822
openvdb::v13_0::math::isExactlyEqual
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition Math.h:468
openvdb::v13_0::math::cwiseAdd
auto cwiseAdd(const Vec3H &v, const float s)
Definition Types.h:761
openvdb::v13_0::math::skew
MatType skew(const Vec3< typename MatType::value_type > &skew)
Return a matrix as the cross product of the given vector.
Definition Mat.h:708
openvdb::v13_0::math::Axis
Axis
Definition Math.h:972
openvdb::v13_0::math::cwiseGreaterThan
bool cwiseGreaterThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition Mat.h:1029
openvdb::v13_0::zeroVal
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:71
openvdb
Definition Exceptions.h:13
Exceptions.h
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
openvdb::v13_0::math::Tolerance::value
static T value()
Definition Math.h:159
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218