ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvGLMatrixTpl.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 // Local
11 #include "ecvSerializableObject.h"
12 
13 // cloudViewer
14 #include <CVConst.h>
15 #include <CVGeom.h>
16 #include <CVMath.h>
17 
18 #include <Eigen/Geometry>
19 
20 // Qt5/Qt6 Compatibility
21 #include <QtCompat.h>
22 
24 static const unsigned OPENGL_MATRIX_SIZE = 16;
25 
26 // Matrix element shortcuts in (line,column) order
27 #define CC_MAT_R11 m_mat[0]
28 #define CC_MAT_R21 m_mat[1]
29 #define CC_MAT_R31 m_mat[2]
30 #define CC_MAT_R41 m_mat[3]
31 
32 #define CC_MAT_R12 m_mat[4]
33 #define CC_MAT_R22 m_mat[5]
34 #define CC_MAT_R32 m_mat[6]
35 #define CC_MAT_R42 m_mat[7]
36 
37 #define CC_MAT_R13 m_mat[8]
38 #define CC_MAT_R23 m_mat[9]
39 #define CC_MAT_R33 m_mat[10]
40 #define CC_MAT_R43 m_mat[11]
41 
42 #define CC_MAT_R14 m_mat[12]
43 #define CC_MAT_R24 m_mat[13]
44 #define CC_MAT_R34 m_mat[14]
45 #define CC_MAT_R44 m_mat[15]
46 
48 
51 template <typename T>
53 public:
55  const Eigen::Matrix<double, 4, 4>& mat) {
56  return ccGLMatrixTpl<T>(mat.data());
57  }
58 
60  const Eigen::Matrix<T, 3, 3>& mat) {
61  ccGLMatrixTpl<T> rotMat;
62  rotMat.clearTranslation();
63  rotMat.setRotation(mat.data());
64  return rotMat;
65  }
66 
67  static inline Eigen::Matrix<T, 4, 4> ToEigenMatrix4(
68  const ccGLMatrixTpl<float>& mat) {
69  Eigen::Matrix4f matrix = Eigen::Matrix<float, 4, 4>(mat.data());
70  return matrix.cast<T>();
71  }
72  static inline Eigen::Matrix<T, 4, 4> ToEigenMatrix4(
73  const ccGLMatrixTpl<double>& mat) {
74  Eigen::Matrix4d matrix = Eigen::Matrix<double, 4, 4>(mat.data());
75  return matrix.cast<T>();
76  }
77 
78  static inline Eigen::Matrix<T, 3, 3> ToEigenMatrix3(
79  const ccGLMatrixTpl<float>& mat) {
80  Eigen::Matrix<T, 3, 3> m = Eigen::Matrix<T, 3, 3>::Zero();
81  const float* data = mat.data();
82 
83  m << data[0], data[4], data[8], data[1], data[5], data[9], data[2],
84  data[6], data[10];
85  return m;
86  }
87  static inline Eigen::Matrix<T, 3, 3> ToEigenMatrix3(
88  const ccGLMatrixTpl<double>& mat) {
89  Eigen::Matrix<T, 3, 3> m = Eigen::Matrix<T, 3, 3>::Zero();
90  const double* data = mat.data();
91 
92  m << data[0], data[4], data[8], data[1], data[5], data[9], data[2],
93  data[6], data[10];
94  return m;
95  }
96 
98  inline ccGLMatrixTpl(const Eigen::Matrix<float, 4, 4>& mat) { *this = mat; }
99  inline ccGLMatrixTpl(const Eigen::Matrix<double, 4, 4>& mat) {
100  *this = mat;
101  }
102 
103  inline ccGLMatrixTpl(const Eigen::Matrix<float, 3, 3>& mat) { *this = mat; }
104  inline ccGLMatrixTpl(const Eigen::Matrix<double, 3, 3>& mat) {
105  *this = mat;
106  }
107 
109  inline ccGLMatrixTpl<T>& operator=(const Eigen::Matrix<float, 4, 4>& mat) {
110  const float* data = mat.data();
111  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
112  m_mat[i] = static_cast<T>(data[i]);
113  return *this;
114  }
115  inline ccGLMatrixTpl<T>& operator=(const Eigen::Matrix<double, 4, 4>& mat) {
116  const double* data = mat.data();
117  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
118  m_mat[i] = static_cast<T>(data[i]);
119  return *this;
120  }
121 
122  inline ccGLMatrixTpl<T>& operator=(const Eigen::Matrix<float, 3, 3>& mat) {
123  setRotation(mat.data());
124  return *this;
125  }
126  inline ccGLMatrixTpl<T>& operator=(const Eigen::Matrix<double, 3, 3>& mat) {
127  setRotation(mat.data());
128  return *this;
129  }
130 
132 
135 
138  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
139  m_mat[i] = mat.m_mat[i];
140  }
141 
144  if (this != &mat) {
145  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
146  m_mat[i] = mat.m_mat[i];
147  }
148  return *this;
149  }
150 
152 
154  explicit ccGLMatrixTpl(const float* mat16f) {
155  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
156  m_mat[i] = static_cast<T>(mat16f[i]);
157  }
158 
160 
163  explicit ccGLMatrixTpl(const double* mat16d) {
164  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
165  m_mat[i] = static_cast<T>(mat16d[i]);
166  }
167 
169 
175  const Vector3Tpl<T>& Y,
176  const Vector3Tpl<T>& Z,
177  const Vector3Tpl<T>& Tr) {
178  CC_MAT_R11 = X.x;
179  CC_MAT_R21 = X.y;
180  CC_MAT_R31 = X.z;
181  CC_MAT_R41 = 0;
182  CC_MAT_R12 = Y.x;
183  CC_MAT_R22 = Y.y;
184  CC_MAT_R32 = Y.z;
185  CC_MAT_R42 = 0;
186  CC_MAT_R13 = Z.x;
187  CC_MAT_R23 = Z.y;
188  CC_MAT_R33 = Z.z;
189  CC_MAT_R43 = 0;
190  CC_MAT_R14 = Tr.x;
191  CC_MAT_R24 = Tr.y;
192  CC_MAT_R34 = Tr.z;
193  CC_MAT_R44 = static_cast<T>(1);
194  }
195 
197 
201  static ccGLMatrixTpl Interpolate(T coef,
202  const ccGLMatrixTpl<T>& glMat1,
203  const ccGLMatrixTpl<T>& glMat2) {
204  // we compute the transformation matrix between glMat1 and glMat2
205  ccGLMatrixTpl<T> invTrans1 = glMat1.inverse();
206  ccGLMatrixTpl<T> m12 = invTrans1 * glMat2;
207 
208  Vector3Tpl<T> axis, Tr;
209  T alpha;
210  m12.getParameters(alpha, axis, Tr);
211 
212  // we only have to interpolate the angle value
213  alpha *= coef;
214  // and the translation
215  Tr *= coef;
216 
217  // we build-up the resulting matrix
218  m12.initFromParameters(alpha, axis, Tr);
219 
220  // eventually we build-up resulting transformation
221  return glMat1 * m12;
222  }
223 
225 
231  const Vector3Tpl<T>& to) {
232  T c = from.dot(to);
233  T f = (c < 0 ? -c : c);
235 
237  1.0 - f)) //"from" and "to"-vector almost parallel
238  {
239  // "to" vector most nearly orthogonal to "from"
240  Vector3Tpl<T> x(0, 0, 0);
241  if (fabs(from.x) < fabs(from.y)) {
242  if (fabs(from.x) < fabs(from.z))
243  x.x = static_cast<T>(1);
244  else
245  x.z = static_cast<T>(1);
246  } else {
247  if (fabs(from.y) < fabs(from.z))
248  x.y = static_cast<T>(1);
249  else
250  x.z = static_cast<T>(1);
251  }
252 
253  Vector3Tpl<T> u = x - from;
254  Vector3Tpl<T> v = x - to;
255 
256  T c1 = 2 / u.dot(u);
257  T c2 = 2 / v.dot(v);
258  T c3 = c1 * c2 * u.dot(v);
259 
260  T* mat = result.data();
261  for (unsigned i = 0; i < 3; i++) {
262  for (unsigned j = 0; j < 3; j++) {
263  mat[i * 4 + j] = c3 * v.u[i] * u.u[j] -
264  c2 * v.u[i] * v.u[j] -
265  c1 * u.u[i] * u.u[j];
266  }
267  mat[i * 4 + i] += static_cast<T>(1);
268  }
269  } else // the most common case, unless "from"="to", or "from"=-"to"
270  {
271  // see Efficiently Building a Matrix to Rotate One Vector to Another
272  // T. Moller and J.F. Hugues (1999)
273  Vector3Tpl<T> v = from.cross(to);
274  T h = 1 / (1 + c);
275  T hvx = h * v.x;
276  T hvz = h * v.z;
277  T hvxy = hvx * v.y;
278  T hvxz = hvx * v.z;
279  T hvyz = hvz * v.y;
280 
281  T* mat = result.data();
282  mat[0] = c + hvx * v.x;
283  mat[1] = hvxy + v.z;
284  mat[2] = hvxz - v.y;
285 
286  mat[4] = hvxy - v.z;
287  mat[5] = c + h * v.y * v.y;
288  mat[6] = hvyz + v.x;
289 
290  mat[8] = hvxz + v.y;
291  mat[9] = hvyz - v.x;
292  mat[10] = c + hvz * v.z;
293  }
294 
295  return result;
296  }
297 
299 
302  template <class Tq>
303  static ccGLMatrixTpl<T> FromQuaternion(const Tq q[]) {
304  assert(q);
305 
306  ccGLMatrixTpl<T> rotMat;
307  T* mat = rotMat.data();
308 
309  // diagonal
310  {
311  Tq q00 = q[0] * q[0];
312  Tq q11 = q[1] * q[1];
313  Tq q22 = q[2] * q[2];
314  Tq q33 = q[3] * q[3];
315 
316  mat[0] = static_cast<T>(q00 + q11 - q22 - q33);
317  mat[5] = static_cast<T>(q00 - q11 + q22 - q33);
318  mat[10] = static_cast<T>(q00 - q11 - q22 + q33);
319  mat[15] = static_cast<T>(1);
320  }
321 
322  // non-diagonal elements
323  {
324  Tq q03 = q[0] * q[3];
325  Tq q13 = q[1] * q[3];
326  Tq q23 = q[2] * q[3];
327  Tq q02 = q[0] * q[2];
328  Tq q12 = q[1] * q[2];
329  Tq q01 = q[0] * q[1];
330 
331  mat[1] = static_cast<T>((q12 + q03) * 2);
332  mat[2] = static_cast<T>((q13 - q02) * 2);
333  mat[4] = static_cast<T>((q12 - q03) * 2);
334  mat[6] = static_cast<T>((q23 + q01) * 2);
335  mat[8] = static_cast<T>((q13 + q02) * 2);
336  mat[9] = static_cast<T>((q23 - q01) * 2);
337  }
338 
339  return rotMat;
340  }
341 
343 
346  static Eigen::Matrix<T, 3, 3> QuaternionToRotationMatrix(
347  const Eigen::Matrix<T, 4, 1>& qvec) {
348  const Eigen::Matrix<T, 4, 1> normalized_qvec =
349  NormalizeQuaternion(qvec);
350  const Eigen::Quaternion<T> quat(normalized_qvec(0), normalized_qvec(1),
351  normalized_qvec(2), normalized_qvec(3));
352  return quat.toRotationMatrix();
353  }
354 
356 
360  const Tuple4Tpl<T>& qvec) {
361  Eigen::Matrix<T, 4, 1> t_qvec;
362  t_qvec(0) = qvec.w;
363  t_qvec(1) = qvec.x;
364  t_qvec(2) = qvec.y;
365  t_qvec(3) = qvec.z;
366  const Eigen::Matrix<T, 4, 1> normalized_qvec =
367  NormalizeQuaternion(t_qvec);
368  const Eigen::Quaternion<T> quat(normalized_qvec(0), normalized_qvec(1),
369  normalized_qvec(2), normalized_qvec(3));
370  return FromEigenMatrix3(quat.toRotationMatrix());
371  }
372 
374 
377  static Eigen::Matrix<T, 4, 1> NormalizeQuaternion(
378  const Eigen::Matrix<T, 4, 1>& qvec) {
379  const T norm = qvec.norm();
380  if (norm == 0) {
381  // We do not just use (1, 0, 0, 0) because that is a constant and
382  // when used for automatic differentiation that would lead to a zero
383  // derivative.
384  return Eigen::Matrix<T, 4, 1>(static_cast<T>(1.0), qvec(1), qvec(2),
385  qvec(3));
386  } else {
387  return qvec / norm;
388  }
389  }
390 
392 
395  void toQuaternion(T q[]) const {
396  Eigen::Quaternion<T> t_q = Eigen::Quaternion<T>(ToEigenMatrix3(*this));
397  // t_q.normalize();
398  q[0] = t_q.w();
399  q[1] = t_q.x();
400  q[2] = t_q.y();
401  q[3] = t_q.z();
402  }
403 
405 
408  void toAngleAxis(T& alpha_rad, Vector3Tpl<T>& axis3D) const {
409  Eigen::AngleAxis<T> v = Eigen::AngleAxis<T>(ToEigenMatrix3(*this));
410  alpha_rad = v.angle();
411  axis3D.x = v.axis().x();
412  axis3D.y = v.axis().y();
413  axis3D.z = v.axis().z();
414  }
415 
417 
422  void toEulerAngle(T& rz, T& ry, T& rx) const {
423  Eigen::Matrix<T, 3, 1> euler_angles =
424  ToEigenMatrix3(*this).eulerAngles(2, 1, 0);
425  rz = euler_angles.z();
426  ry = euler_angles.y();
427  rx = euler_angles.x();
428  }
429 
431 
437  const Vector3Tpl<T>& up) {
438  // normalize forward
439  Vector3Tpl<T> uForward = forward;
440  uForward.normalize();
441 
442  // side = forward x up
443  Vector3Tpl<T> uSide = uForward.cross(up);
444  uSide.normalize();
445 
446  // recompute 'up' as: up = side x forward
447  Vector3Tpl<T> uUp = uSide.cross(uForward);
448  uUp.normalize();
449 
450  ccGLMatrixTpl<T> matrix;
451  {
452  T* mat = matrix.data();
453  mat[0] = uSide.x;
454  mat[4] = uSide.y;
455  mat[8] = uSide.z;
456  mat[12] = 0;
457  mat[1] = uUp.x;
458  mat[5] = uUp.y;
459  mat[9] = uUp.z;
460  mat[13] = 0;
461  mat[2] = -uForward.x;
462  mat[6] = -uForward.y;
463  mat[10] = -uForward.z;
464  mat[14] = 0;
465  mat[3] = 0;
466  mat[7] = 0;
467  mat[11] = 0;
468  mat[15] = static_cast<T>(1);
469  }
470  return matrix;
471  }
472 
474 
477  static ccGLMatrixTpl<T> FromString(const QString& matText, bool& success) {
478  QStringList valuesStr =
480  if (valuesStr.size() != OPENGL_MATRIX_SIZE) {
481  success = false;
482  return ccGLMatrixTpl<T>();
483  }
484 
485  ccGLMatrixTpl<T> matrix;
486  T* matValues = matrix.data();
487  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i) {
488  matValues[i] = static_cast<T>(
489  valuesStr[(i % 4) * 4 + (i >> 2)].toDouble(&success));
490  if (!success) return ccGLMatrixTpl<T>();
491  }
492 
493  success = true;
494  return matrix;
495  }
496 
498 
502  QString toString(int precision = 12, QChar separator = ' ') const {
503  QString str;
504  for (unsigned l = 0; l < 4; ++l) // lines
505  {
506  for (unsigned c = 0; c < 4; ++c) // columns
507  {
508  str.append(QString::number(m_mat[c * 4 + l], 'f', precision));
509  if (c != 3) str.append(separator);
510  }
511  if (l != 3) str.append("\n");
512  }
513  return str;
514  }
515 
517 
520  virtual bool toAsciiFile(QString filename, int precision = 12) const {
521  QFile fp(filename);
522  if (!fp.open(QFile::WriteOnly | QFile::Text)) return false;
523 
524  QTextStream stream(&fp);
525  stream.setRealNumberPrecision(precision);
526  stream.setRealNumberNotation(QTextStream::FixedNotation);
527  for (unsigned i = 0; i < 4; ++i) {
528  stream << m_mat[i] << " " << m_mat[i + 4] << " " << m_mat[i + 8]
529  << " " << m_mat[i + 12] << QtCompat::endl;
530  }
531 
532  return (fp.error() == QFile::NoError);
533  }
534 
536 
538  virtual bool fromAsciiFile(QString filename) {
539  QFile fp(filename);
540  if (!fp.open(QFile::ReadOnly | QFile::Text)) return false;
541 
542  QTextStream stream(&fp);
543 
544  for (unsigned i = 0; i < 4; ++i) {
545  stream >> m_mat[i];
546  stream >> m_mat[i + 4];
547  stream >> m_mat[i + 8];
548  stream >> m_mat[i + 12];
549  }
550 
551  return (fp.error() == QFile::NoError);
552  }
553 
556  ccGLMatrixTpl<T> newRotMat;
557  newRotMat.toIdentity();
558 
559  // we use a specific Euler angles convention here
560  if (CC_MAT_R13 >= 1) {
561  // simpler/faster to ignore this (very) specific case!
562  return newRotMat;
563  }
564  T phi = -asin(CC_MAT_R13);
565  T cos_phi = cos(phi);
566  T theta = atan2(CC_MAT_R23 / cos_phi, CC_MAT_R33 / cos_phi);
567 
568  newRotMat.CC_MAT_R22 = newRotMat.CC_MAT_R33 = cos(theta);
569  newRotMat.CC_MAT_R32 = newRotMat.CC_MAT_R23 = sin(theta);
570  newRotMat.CC_MAT_R23 *= static_cast<T>(-1);
571 
572  newRotMat.setTranslation(getTranslation());
573 
574  return newRotMat;
575  }
576 
579  ccGLMatrixTpl<T> newRotMat;
580  newRotMat.toIdentity();
581 
582  // we use a specific Euler angles convention here
583  if (CC_MAT_R32 >= 1) {
584  // simpler/faster to ignore this (very) specific case!
585  return newRotMat;
586  }
587  T theta = asin(CC_MAT_R32);
588  T cos_theta = cos(theta);
589  T phi = atan2(-CC_MAT_R31 / cos_theta, CC_MAT_R33 / cos_theta);
590 
591  newRotMat.CC_MAT_R11 = newRotMat.CC_MAT_R33 = cos(phi);
592  newRotMat.CC_MAT_R31 = newRotMat.CC_MAT_R13 = sin(phi);
593  newRotMat.CC_MAT_R31 *= static_cast<T>(-1);
594 
595  newRotMat.setTranslation(getTranslation());
596 
597  return newRotMat;
598  }
599 
602  // we can use the standard Euler angles convention here
603  T phi, theta, psi;
604  Vector3Tpl<T> Tr;
605  getParameters(phi, theta, psi, Tr);
606  assert(Tr.norm2() == 0);
607 
608  ccGLMatrixTpl<T> newRotMat;
609  newRotMat.initFromParameters(phi, 0, 0, Tr);
610 
611  return newRotMat;
612  }
613 
615 
617  inline virtual void toZero() {
618  memset(m_mat, 0, OPENGL_MATRIX_SIZE * sizeof(T));
619  }
620 
622  inline virtual void toIdentity() {
623  toZero();
624  CC_MAT_R11 = CC_MAT_R22 = CC_MAT_R33 = CC_MAT_R44 = static_cast<T>(1);
625  }
626 
628  inline virtual bool isIdentity() const {
629  for (unsigned l = 0; l < 4; ++l) { // lines
630  for (unsigned c = 0; c < 4; ++c) { // columns
631  if (m_mat[c * 4 + l] != static_cast<T>(l == c ? 1 : 0))
632  return false;
633  }
634  }
635  return true;
636  }
637 
639 
644 
648  void initFromParameters(T alpha_rad,
649  const Vector3Tpl<T>& axis3D,
650  const Vector3Tpl<T>& t3D) {
651  T cos_t = cos(alpha_rad);
652  T sin_t = sin(alpha_rad);
653  T inv_cos_t = static_cast<T>(1) - cos_t;
654 
655  // normalize rotation axis
656  Vector3Tpl<T> uAxis3D = axis3D;
657  uAxis3D.normalize();
658 
659  const T& l1 = uAxis3D.x;
660  const T& l2 = uAxis3D.y;
661  const T& l3 = uAxis3D.z;
662 
663  T l1_inv_cos_t = l1 * inv_cos_t;
664  T l3_inv_cos_t = l3 * inv_cos_t;
665 
666  // 1st column
667  CC_MAT_R11 = cos_t + l1 * l1_inv_cos_t;
668  CC_MAT_R21 = l2 * l1_inv_cos_t + l3 * sin_t;
669  CC_MAT_R31 = l3 * l1_inv_cos_t - l2 * sin_t;
670  CC_MAT_R41 = 0;
671 
672  // 2nd column
673  CC_MAT_R12 = l2 * l1_inv_cos_t - l3 * sin_t;
674  CC_MAT_R22 = cos_t + l2 * l2 * inv_cos_t;
675  CC_MAT_R32 = l2 * l3_inv_cos_t + l1 * sin_t;
676  CC_MAT_R42 = 0;
677 
678  // 3rd column
679  CC_MAT_R13 = l3 * l1_inv_cos_t + l2 * sin_t;
680  CC_MAT_R23 = l2 * l3_inv_cos_t - l1 * sin_t;
681  CC_MAT_R33 = cos_t + l3 * l3_inv_cos_t;
682  CC_MAT_R43 = 0;
683 
684  // 4th column
685  CC_MAT_R14 = t3D.x;
686  CC_MAT_R24 = t3D.y;
687  CC_MAT_R34 = t3D.z;
688  CC_MAT_R44 = static_cast<T>(1);
689  }
690 
692 
698  void initFromParameters(T phi_rad,
699  T theta_rad,
700  T psi_rad,
701  const Vector3Tpl<T>& t3D) {
702  T c1 = cos(phi_rad);
703  T c2 = cos(theta_rad);
704  T c3 = cos(psi_rad);
705 
706  T s1 = sin(phi_rad);
707  T s2 = sin(theta_rad);
708  T s3 = sin(psi_rad);
709 
710  // 1st column
711  CC_MAT_R11 = c2 * c1;
712  CC_MAT_R21 = c2 * s1;
713  CC_MAT_R31 = -s2;
714  CC_MAT_R41 = 0;
715 
716  // 2nd column
717  CC_MAT_R12 = s3 * s2 * c1 - c3 * s1;
718  CC_MAT_R22 = s3 * s2 * s1 + c3 * c1;
719  CC_MAT_R32 = s3 * c2;
720  CC_MAT_R42 = 0;
721 
722  // 3rd column
723  CC_MAT_R13 = c3 * s2 * c1 + s3 * s1;
724  CC_MAT_R23 = c3 * s2 * s1 - s3 * c1;
725  CC_MAT_R33 = c3 * c2;
726  CC_MAT_R43 = 0;
727 
728  // 4th column
729  CC_MAT_R14 = t3D.x;
730  CC_MAT_R24 = t3D.y;
731  CC_MAT_R34 = t3D.z;
732  CC_MAT_R44 = static_cast<T>(1.0);
733  }
734 
737 
741  void getParameters(T& alpha_rad,
742  Vector3Tpl<T>& axis3D,
743  Vector3Tpl<T>& t3D) const {
744  T trace = CC_MAT_R11 + CC_MAT_R22 + CC_MAT_R33;
745  T cos_t = (trace - 1) / 2;
746  if (fabs(cos_t) <= 1) {
747  alpha_rad = acos(cos_t); // result in [0;pi]
748  } else {
749  alpha_rad = 0;
750  }
751 
752  axis3D.x = CC_MAT_R32 - CC_MAT_R23;
753  axis3D.y = CC_MAT_R13 - CC_MAT_R31;
754  axis3D.z = CC_MAT_R21 - CC_MAT_R12;
755 
756  // normalize axis
757  T n2 = axis3D.norm2();
759  axis3D /= sqrt(n2);
760  } else {
761  // axis is too small!
762  axis3D = Vector3Tpl<T>(0, 0, 1);
763  }
764 
765  t3D.x = CC_MAT_R14;
766  t3D.y = CC_MAT_R24;
767  t3D.z = CC_MAT_R34;
768  }
769 
771 
777  void getParameters(T& phi_rad,
778  T& theta_rad,
779  T& psi_rad,
780  Vector3Tpl<T>& t3D) const {
781  if (fabs(CC_MAT_R31) != 1) {
782  theta_rad = -asin(CC_MAT_R31);
783  T cos_theta = cos(theta_rad);
784  psi_rad = atan2(CC_MAT_R32 / cos_theta, CC_MAT_R33 / cos_theta);
785  phi_rad = atan2(CC_MAT_R21 / cos_theta, CC_MAT_R11 / cos_theta);
786 
787  // Other solution
788  // theta = M_PI + asin(CC_MAT_R31);
789  // T cos_theta = cos(theta);
790  // psi = atan2(CC_MAT_R32 / cos_theta, CC_MAT_R33 / cos_theta);
791  // phi = atan2(CC_MAT_R21 / cos_theta, CC_MAT_R11 / cos_theta);
792  } else {
793  phi_rad = 0;
794 
795  if (CC_MAT_R31 == -1) {
796  theta_rad = static_cast<T>(M_PI_2);
797  psi_rad = atan2(CC_MAT_R12, CC_MAT_R13);
798  } else {
799  theta_rad = -static_cast<T>(M_PI_2);
800  psi_rad = -atan2(CC_MAT_R12, CC_MAT_R13);
801  }
802  }
803 
804  t3D.x = CC_MAT_R14;
805  t3D.y = CC_MAT_R24;
806  t3D.z = CC_MAT_R34;
807  }
808 
810  inline T* data() { return m_mat; }
811 
813  inline const T* data() const { return m_mat; }
814 
816 
819  inline T* getTranslation() { return m_mat + 12; }
820 
822 
825  inline const T* getTranslation() const { return m_mat + 12; }
826 
828 
831  return getColumnAsVec3D(3);
832  }
833 
835 
836  inline void setTranslation(const Vector3Tpl<float>& Tr) {
837  CC_MAT_R14 = static_cast<T>(Tr.x);
838  CC_MAT_R24 = static_cast<T>(Tr.y);
839  CC_MAT_R34 = static_cast<T>(Tr.z);
840  }
842 
843  inline void setTranslation(const Vector3Tpl<double>& Tr) {
844  CC_MAT_R14 = static_cast<T>(Tr.x);
845  CC_MAT_R24 = static_cast<T>(Tr.y);
846  CC_MAT_R34 = static_cast<T>(Tr.z);
847  }
848 
850 
852  void setTranslation(const float Tr[3]) {
853  CC_MAT_R14 = static_cast<T>(Tr[0]);
854  CC_MAT_R24 = static_cast<T>(Tr[1]);
855  CC_MAT_R34 = static_cast<T>(Tr[2]);
856  }
858 
860  void setTranslation(const double Tr[3]) {
861  CC_MAT_R14 = static_cast<T>(Tr[0]);
862  CC_MAT_R24 = static_cast<T>(Tr[1]);
863  CC_MAT_R34 = static_cast<T>(Tr[2]);
864  }
865 
867 
869  void setRotation(const float Rt[9]) {
870  CC_MAT_R11 = static_cast<T>(Rt[0]);
871  CC_MAT_R21 = static_cast<T>(Rt[1]);
872  CC_MAT_R31 = static_cast<T>(Rt[2]);
873 
874  CC_MAT_R12 = static_cast<T>(Rt[3]);
875  CC_MAT_R22 = static_cast<T>(Rt[4]);
876  CC_MAT_R32 = static_cast<T>(Rt[5]);
877 
878  CC_MAT_R13 = static_cast<T>(Rt[6]);
879  CC_MAT_R23 = static_cast<T>(Rt[7]);
880  CC_MAT_R33 = static_cast<T>(Rt[8]);
881  }
882 
884 
886  void setRotation(const double Rt[9]) {
887  CC_MAT_R11 = static_cast<T>(Rt[0]);
888  CC_MAT_R21 = static_cast<T>(Rt[1]);
889  CC_MAT_R31 = static_cast<T>(Rt[2]);
890 
891  CC_MAT_R12 = static_cast<T>(Rt[3]);
892  CC_MAT_R22 = static_cast<T>(Rt[4]);
893  CC_MAT_R32 = static_cast<T>(Rt[5]);
894 
895  CC_MAT_R13 = static_cast<T>(Rt[6]);
896  CC_MAT_R23 = static_cast<T>(Rt[7]);
897  CC_MAT_R33 = static_cast<T>(Rt[8]);
898  }
899 
901 
904  inline T* getColumn(unsigned index) { return m_mat + (index << 2); }
905 
907 
910  inline const T* getColumn(unsigned index) const {
911  return m_mat + (index << 2);
912  }
913 
915 
919  inline Vector3Tpl<T> getColumnAsVec3D(unsigned index) const {
920  return Vector3Tpl<T>::fromArray(getColumn(index));
921  }
922 
924 
927  inline void setColumn(unsigned index, const Vector3Tpl<T>& v) {
928  T* col = m_mat + (index << 2);
929  col[0] = v.x;
930  col[1] = v.y;
931  col[2] = v.z;
932  }
933 
935 
938  inline void setColumn(unsigned index, const Tuple4Tpl<T>& v) {
939  T* col = m_mat + (index << 2);
940  col[0] = v.x;
941  col[1] = v.y;
942  col[2] = v.z;
943  col[3] = v.w;
944  }
945 
949 
950  const T* A = m_mat;
951  const T* B = mat.m_mat;
952  T* C = result.m_mat;
953 
954  for (unsigned j = 0; j < 4; ++j, B += 4)
955  for (unsigned i = 0; i < 4; ++i)
956  *C++ = A[i] * B[0] + A[i + 4] * B[1] + A[i + 8] * B[2] +
957  A[i + 12] * B[3];
958 
959  return result;
960  }
961 
963  inline Vector3Tpl<float> operator*(const Vector3Tpl<float>& vec) const {
964  return Vector3Tpl<float>(applyX(vec), applyY(vec), applyZ(vec));
965  }
968  return Vector3Tpl<double>(applyX(vec), applyY(vec), applyZ(vec));
969  }
970 
972  inline Tuple4Tpl<float> operator*(const Tuple4Tpl<float>& vec) const {
973  return Tuple4Tpl<float>(applyX(vec), applyY(vec), applyZ(vec),
974  applyW(vec));
975  }
977  inline Tuple4Tpl<double> operator*(const Tuple4Tpl<double>& vec) const {
978  return Tuple4Tpl<double>(applyX(vec), applyY(vec), applyZ(vec),
979  applyW(vec));
980  }
981 
984  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
985  m_mat[i] += mat.m_mat[i];
986  return (*this);
987  }
988 
991  for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
992  m_mat[i] -= mat.m_mat[i];
993  return (*this);
994  }
995 
998  (*this) = (*this) * mat;
999  return (*this);
1000  }
1001 
1004  CC_MAT_R14 += static_cast<T>(Tr.x);
1005  CC_MAT_R24 += static_cast<T>(Tr.y);
1006  CC_MAT_R34 += static_cast<T>(Tr.z);
1007  return (*this);
1008  }
1011  CC_MAT_R14 += static_cast<T>(Tr.x);
1012  CC_MAT_R24 += static_cast<T>(Tr.y);
1013  CC_MAT_R34 += static_cast<T>(Tr.z);
1014  return (*this);
1015  }
1018  CC_MAT_R14 -= static_cast<T>(Tr.x);
1019  CC_MAT_R24 -= static_cast<T>(Tr.y);
1020  CC_MAT_R34 -= static_cast<T>(Tr.z);
1021  return (*this);
1022  }
1025  CC_MAT_R14 -= static_cast<T>(Tr.x);
1026  CC_MAT_R24 -= static_cast<T>(Tr.y);
1027  CC_MAT_R34 -= static_cast<T>(Tr.z);
1028  return (*this);
1029  }
1030 
1032  T operator()(unsigned row, unsigned col) const {
1033  return m_mat[(col << 2) + row];
1034  }
1035 
1037 
1039  inline void apply(float vec[3]) const {
1040  CCVector3 internal_vec(vec[0], vec[1], vec[2]);
1041  apply(internal_vec);
1042  vec[0] = internal_vec[0];
1043  vec[1] = internal_vec[1];
1044  vec[2] = internal_vec[2];
1045  }
1047 
1049  inline void apply(double vec[3]) const {
1050  CCVector3d internal_vec(vec[0], vec[1], vec[2]);
1051  apply(internal_vec);
1052  vec[0] = internal_vec[0];
1053  vec[1] = internal_vec[1];
1054  vec[2] = internal_vec[2];
1055  }
1056 
1058 
1060  inline void apply(Vector3Tpl<float>& vec) const { vec = (*this) * vec; }
1062 
1064  inline void apply(Vector3Tpl<double>& vec) const { vec = (*this) * vec; }
1065 
1067 
1069  inline void apply(Tuple4Tpl<float>& vec) const { vec = (*this) * vec; }
1071 
1073  inline void apply(Tuple4Tpl<double>& vec) const { vec = (*this) * vec; }
1074 
1076  inline float applyX(const Vector3Tpl<float>& vec) const {
1077  return static_cast<float>(CC_MAT_R11) * vec.x +
1078  static_cast<float>(CC_MAT_R12) * vec.y +
1079  static_cast<float>(CC_MAT_R13) * vec.z +
1080  static_cast<float>(CC_MAT_R14);
1081  }
1083  inline double applyX(const Vector3Tpl<double>& vec) const {
1084  return static_cast<double>(CC_MAT_R11) * vec.x +
1085  static_cast<double>(CC_MAT_R12) * vec.y +
1086  static_cast<double>(CC_MAT_R13) * vec.z +
1087  static_cast<double>(CC_MAT_R14);
1088  }
1089 
1091  inline float applyY(const Vector3Tpl<float>& vec) const {
1092  return static_cast<float>(CC_MAT_R21) * vec.x +
1093  static_cast<float>(CC_MAT_R22) * vec.y +
1094  static_cast<float>(CC_MAT_R23) * vec.z +
1095  static_cast<float>(CC_MAT_R24);
1096  }
1098  inline double applyY(const Vector3Tpl<double>& vec) const {
1099  return static_cast<double>(CC_MAT_R21) * vec.x +
1100  static_cast<double>(CC_MAT_R22) * vec.y +
1101  static_cast<double>(CC_MAT_R23) * vec.z +
1102  static_cast<double>(CC_MAT_R24);
1103  }
1104 
1106  inline float applyZ(const Vector3Tpl<float>& vec) const {
1107  return static_cast<float>(CC_MAT_R31) * vec.x +
1108  static_cast<float>(CC_MAT_R32) * vec.y +
1109  static_cast<float>(CC_MAT_R33) * vec.z +
1110  static_cast<float>(CC_MAT_R34);
1111  }
1113  inline double applyZ(const Vector3Tpl<double>& vec) const {
1114  return static_cast<double>(CC_MAT_R31) * vec.x +
1115  static_cast<double>(CC_MAT_R32) * vec.y +
1116  static_cast<double>(CC_MAT_R33) * vec.z +
1117  static_cast<double>(CC_MAT_R34);
1118  }
1119 
1121  inline float applyX(const Tuple4Tpl<float>& vec) const {
1122  return static_cast<float>(CC_MAT_R11) * vec.x +
1123  static_cast<float>(CC_MAT_R12) * vec.y +
1124  static_cast<float>(CC_MAT_R13) * vec.z +
1125  static_cast<float>(CC_MAT_R14) * vec.w;
1126  }
1128  inline double applyX(const Tuple4Tpl<double>& vec) const {
1129  return static_cast<double>(CC_MAT_R11) * vec.x +
1130  static_cast<double>(CC_MAT_R12) * vec.y +
1131  static_cast<double>(CC_MAT_R13) * vec.z +
1132  static_cast<double>(CC_MAT_R14) * vec.w;
1133  }
1134 
1136  inline float applyY(const Tuple4Tpl<float>& vec) const {
1137  return static_cast<float>(CC_MAT_R21) * vec.x +
1138  static_cast<float>(CC_MAT_R22) * vec.y +
1139  static_cast<float>(CC_MAT_R23) * vec.z +
1140  static_cast<float>(CC_MAT_R24) * vec.w;
1141  }
1143  inline double applyY(const Tuple4Tpl<double>& vec) const {
1144  return static_cast<double>(CC_MAT_R21) * vec.x +
1145  static_cast<double>(CC_MAT_R22) * vec.y +
1146  static_cast<double>(CC_MAT_R23) * vec.z +
1147  static_cast<double>(CC_MAT_R24) * vec.w;
1148  }
1149 
1151  inline float applyZ(const Tuple4Tpl<float>& vec) const {
1152  return static_cast<float>(CC_MAT_R31) * vec.x +
1153  static_cast<float>(CC_MAT_R32) * vec.y +
1154  static_cast<float>(CC_MAT_R33) * vec.z +
1155  static_cast<float>(CC_MAT_R34) * vec.w;
1156  }
1158  inline double applyZ(const Tuple4Tpl<double>& vec) const {
1159  return static_cast<double>(CC_MAT_R31) * vec.x +
1160  static_cast<double>(CC_MAT_R32) * vec.y +
1161  static_cast<double>(CC_MAT_R33) * vec.z +
1162  static_cast<double>(CC_MAT_R34) * vec.w;
1163  }
1164 
1166  inline float applyW(const Tuple4Tpl<float>& vec) const {
1167  return static_cast<float>(CC_MAT_R41) * vec.x +
1168  static_cast<float>(CC_MAT_R42) * vec.y +
1169  static_cast<float>(CC_MAT_R43) * vec.z +
1170  static_cast<float>(CC_MAT_R44) * vec.w;
1171  }
1174  inline double applyW(const Tuple4Tpl<double>& vec) const {
1175  return static_cast<double>(CC_MAT_R41) * vec.x +
1176  static_cast<double>(CC_MAT_R42) * vec.y +
1177  static_cast<double>(CC_MAT_R43) * vec.z +
1178  static_cast<double>(CC_MAT_R44) * vec.w;
1179  }
1180 
1182 
1184  inline void applyRotation(Vector3Tpl<float>& vec) const {
1185  float vx = vec.x;
1186  float vy = vec.y;
1187  float vz = vec.z;
1188 
1189  vec.x = static_cast<float>(CC_MAT_R11) * vx +
1190  static_cast<float>(CC_MAT_R12) * vy +
1191  static_cast<float>(CC_MAT_R13) * vz;
1192 
1193  vec.y = static_cast<float>(CC_MAT_R21) * vx +
1194  static_cast<float>(CC_MAT_R22) * vy +
1195  static_cast<float>(CC_MAT_R23) * vz;
1196 
1197  vec.z = static_cast<float>(CC_MAT_R31) * vx +
1198  static_cast<float>(CC_MAT_R32) * vy +
1199  static_cast<float>(CC_MAT_R33) * vz;
1200  }
1202 
1204  inline void applyRotation(Vector3Tpl<double>& vec) const {
1205  double vx = vec.x;
1206  double vy = vec.y;
1207  double vz = vec.z;
1208 
1209  vec.x = static_cast<double>(CC_MAT_R11) * vx +
1210  static_cast<double>(CC_MAT_R12) * vy +
1211  static_cast<double>(CC_MAT_R13) * vz;
1212 
1213  vec.y = static_cast<double>(CC_MAT_R21) * vx +
1214  static_cast<double>(CC_MAT_R22) * vy +
1215  static_cast<double>(CC_MAT_R23) * vz;
1216 
1217  vec.z = static_cast<double>(CC_MAT_R31) * vx +
1218  static_cast<double>(CC_MAT_R32) * vy +
1219  static_cast<double>(CC_MAT_R33) * vz;
1220  }
1221 
1223 
1225  inline void applyRotation(float vec[3]) const {
1226  float vx = vec[0];
1227  float vy = vec[1];
1228  float vz = vec[2];
1229 
1230  vec[0] = static_cast<float>(CC_MAT_R11) * vx +
1231  static_cast<float>(CC_MAT_R12) * vy +
1232  static_cast<float>(CC_MAT_R13) * vz;
1233 
1234  vec[1] = static_cast<float>(CC_MAT_R21) * vx +
1235  static_cast<float>(CC_MAT_R22) * vy +
1236  static_cast<float>(CC_MAT_R23) * vz;
1237 
1238  vec[2] = static_cast<float>(CC_MAT_R31) * vx +
1239  static_cast<float>(CC_MAT_R32) * vy +
1240  static_cast<float>(CC_MAT_R33) * vz;
1241  }
1243 
1245  inline void applyRotation(double vec[3]) const {
1246  double vx = vec[0];
1247  double vy = vec[1];
1248  double vz = vec[2];
1249 
1250  vec[0] = static_cast<double>(CC_MAT_R11) * vx +
1251  static_cast<double>(CC_MAT_R12) * vy +
1252  static_cast<double>(CC_MAT_R13) * vz;
1253 
1254  vec[1] = static_cast<double>(CC_MAT_R21) * vx +
1255  static_cast<double>(CC_MAT_R22) * vy +
1256  static_cast<double>(CC_MAT_R23) * vz;
1257 
1258  vec[2] = static_cast<double>(CC_MAT_R31) * vx +
1259  static_cast<double>(CC_MAT_R32) * vy +
1260  static_cast<double>(CC_MAT_R33) * vz;
1261  }
1262 
1264 
1269  // R(X-vec)+T+vec = R(X)+T + vec-R(vec)
1270  Vector3Tpl<T> Rvec = vec;
1271  applyRotation(Rvec);
1272  *this += (vec - Rvec);
1273  }
1274 
1276  void transpose() {
1283  }
1284 
1287  ccGLMatrixTpl<T> t(*this);
1288  t.transpose();
1289 
1290  return t;
1291  }
1292 
1294  void invert() {
1295  // inverse scale as well!
1296  // we use the first column == X (its norm should be 1 for an 'unscaled'
1297  // matrix ;)
1298  T s2 = getColumnAsVec3D(0).norm2();
1299 
1300  // we invert rotation
1304 
1305  if (s2 != 0 && s2 != 1) {
1306  CC_MAT_R11 /= s2;
1307  CC_MAT_R12 /= s2;
1308  CC_MAT_R13 /= s2;
1309  CC_MAT_R21 /= s2;
1310  CC_MAT_R22 /= s2;
1311  CC_MAT_R23 /= s2;
1312  CC_MAT_R31 /= s2;
1313  CC_MAT_R32 /= s2;
1314  CC_MAT_R33 /= s2;
1315  }
1316 
1317  // eventually we invert translation
1318  applyRotation(m_mat + 12);
1322  }
1323 
1326  ccGLMatrixTpl<T> t(*this);
1327  t.invert();
1328 
1329  return t;
1330  }
1331 
1333 
1335  inline void scale(T coef) {
1336  CC_MAT_R11 *= coef;
1337  CC_MAT_R12 *= coef;
1338  CC_MAT_R13 *= coef;
1339  CC_MAT_R14 *= coef;
1340  CC_MAT_R21 *= coef;
1341  CC_MAT_R22 *= coef;
1342  CC_MAT_R23 *= coef;
1343  CC_MAT_R24 *= coef;
1344  CC_MAT_R31 *= coef;
1345  CC_MAT_R32 *= coef;
1346  CC_MAT_R33 *= coef;
1347  CC_MAT_R34 *= coef;
1348  }
1349 
1351 
1354  void scaleLine(unsigned lineIndex, T coef) {
1355  assert(lineIndex < 4);
1356  m_mat[lineIndex] *= coef;
1357  m_mat[4 + lineIndex] *= coef;
1358  m_mat[8 + lineIndex] *= coef;
1359  m_mat[12 + lineIndex] *= coef;
1360  }
1361 
1363 
1365  inline void scaleRotation(T coef) {
1366  CC_MAT_R11 *= coef;
1367  CC_MAT_R12 *= coef;
1368  CC_MAT_R13 *= coef;
1369  CC_MAT_R21 *= coef;
1370  CC_MAT_R22 *= coef;
1371  CC_MAT_R23 *= coef;
1372  CC_MAT_R31 *= coef;
1373  CC_MAT_R32 *= coef;
1374  CC_MAT_R33 *= coef;
1375  }
1376 
1378 
1381  void scaleRow(unsigned rowIndex, T coef) {
1382  assert(rowIndex < 4);
1383  m_mat[rowIndex] *= coef;
1384  m_mat[4 + rowIndex] *= coef;
1385  m_mat[8 + rowIndex] *= coef;
1386  m_mat[12 + rowIndex] *= coef;
1387  }
1388 
1390 
1393  void scaleColumn(unsigned colIndex, T coef) {
1394  assert(colIndex < 4);
1395  T* col = getColumn(colIndex);
1396  col[0] *= coef;
1397  col[1] *= coef;
1398  col[2] *= coef;
1399  // col[3] *= coef;
1400  }
1401 
1402  // inherited from ccSerializableObject
1403  bool isSerializable() const override { return true; }
1404 
1405  bool toFile(QFile& out, short dataVersion) const override {
1406  assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
1407 
1408  // Version validation
1409  if (dataVersion < 20) {
1410  assert(false);
1411  return false;
1412  }
1413 
1414  // data (dataVersion>=20)
1415  if (out.write(reinterpret_cast<const char*>(m_mat),
1416  sizeof(T) * OPENGL_MATRIX_SIZE) < 0)
1417  return WriteError();
1418 
1419  return true;
1420  }
1421 
1422  short minimumFileVersion() const override {
1423  // ccGLMatrix data structure has been stable since version 20
1424  return 20;
1425  }
1426 
1427  bool fromFile(QFile& in,
1428  short dataVersion,
1429  int flags,
1430  LoadedIDMap& oldToNewIDMap) override {
1431  assert(in.isOpen() && (in.openMode() & QIODevice::ReadOnly));
1432 
1433  if (dataVersion < 20) return CorruptError();
1434 
1435  // data (dataVersion>=20)
1436  if (in.read(reinterpret_cast<char*>(m_mat),
1437  sizeof(T) * OPENGL_MATRIX_SIZE) < 0)
1438  return ReadError();
1439 
1440  return true;
1441  }
1442 
1443 protected:
1446 };
constexpr double M_PI_2
Pi/2.
Definition: CVConst.h:24
std::string filename
QStringList qtCompatSplitRegex(const QString &str, const QString &pattern, Qt::SplitBehavior behavior=Qt::KeepEmptyParts)
Definition: QtCompat.h:308
void * X
Definition: SmallVector.cpp:45
core::Tensor result
Definition: VtkUtils.cpp:76
Type y
Definition: CVGeom.h:137
Type u[3]
Definition: CVGeom.h:139
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
4-Tuple structure (templated version)
Definition: CVGeom.h:648
Type x
Definition: CVGeom.h:653
Type y
Definition: CVGeom.h:653
Type w
Definition: CVGeom.h:653
Type z
Definition: CVGeom.h:653
void normalize()
Sets vector norm to unity.
Definition: CVGeom.h:428
Type dot(const Vector3Tpl &v) const
Dot product.
Definition: CVGeom.h:408
Type norm2() const
Returns vector square norm.
Definition: CVGeom.h:417
Vector3Tpl cross(const Vector3Tpl &v) const
Cross product.
Definition: CVGeom.h:412
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
Definition: CVGeom.h:268
A 4x4 'transformation' matrix (column major order)
float applyY(const Tuple4Tpl< float > &vec) const
Get the resulting transformation along Y dimension (float version)
ccGLMatrixTpl< T > & operator+=(const ccGLMatrixTpl< T > &mat)
(in place) Addition operator
ccGLMatrixTpl(const Eigen::Matrix< float, 4, 4 > &mat)
Copy Function.
QString toString(int precision=12, QChar separator=' ') const
Returns matrix as a string.
static ccGLMatrixTpl< T > FromEigenMatrix3(const Eigen::Matrix< T, 3, 3 > &mat)
Vector3Tpl< T > getTranslationAsVec3D() const
Returns a copy of the translation as a CCVector3.
void getParameters(T &phi_rad, T &theta_rad, T &psi_rad, Vector3Tpl< T > &t3D) const
Returns equivalent parameters: 3 rotation angles and a translation.
void toQuaternion(T q[]) const
Converts to a quaternion from a rotation matrix.
ccGLMatrixTpl< T > & operator-=(const Vector3Tpl< double > &Tr)
(in place) Backward translation operator (double version)
ccGLMatrixTpl< T > zRotation() const
Returns the rotation component around Z only.
void setColumn(unsigned index, const Vector3Tpl< T > &v)
Sets the content of a given column.
bool isSerializable() const override
Returns whether object is serializable of not.
void toAngleAxis(T &alpha_rad, Vector3Tpl< T > &axis3D) const
Returns equivalent parameters: a rotation axis and an angle.
T operator()(unsigned row, unsigned col) const
Returns the value at a given position.
void apply(Tuple4Tpl< float > &vec) const
Applies transformation to a 4D vector (in place) - float version.
virtual void toZero()
Clears matrix.
ccGLMatrixTpl(const Vector3Tpl< T > &X, const Vector3Tpl< T > &Y, const Vector3Tpl< T > &Z, const Vector3Tpl< T > &Tr)
Constructor from 4 columns (X,Y,Z,T)
static ccGLMatrixTpl< T > FromEigenMatrix(const Eigen::Matrix< double, 4, 4 > &mat)
bool fromFile(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads data from binary stream.
ccGLMatrixTpl< T > transposed() const
Returns transposed matrix.
ccGLMatrixTpl(const float *mat16f)
Constructor from a float GL matrix array.
void setTranslation(const Vector3Tpl< double > &Tr)
Sets translation (double version)
void applyRotation(Vector3Tpl< float > &vec) const
Applies rotation only to a 3D vector (in place) - float version.
static ccGLMatrixTpl< T > FromQuaternion(const Tq q[])
Converts a quaternion to a rotation matrix.
static Eigen::Matrix< T, 3, 3 > ToEigenMatrix3(const ccGLMatrixTpl< double > &mat)
static ccGLMatrixTpl< T > FromToRotation(const Vector3Tpl< T > &from, const Vector3Tpl< T > &to)
Creates a transformation matrix that rotates a vector to another.
void applyRotation(float vec[3]) const
Applies rotation only to a 3D vector (in place) - float version.
void apply(Vector3Tpl< float > &vec) const
Applies transformation to a 3D vector (in place) - float version.
ccGLMatrixTpl(const Eigen::Matrix< double, 4, 4 > &mat)
ccGLMatrixTpl< T > & operator-=(const Vector3Tpl< float > &Tr)
(in place) Backward translation operator (float version)
void applyRotation(double vec[3]) const
Applies rotation only to a 3D vector (in place) - float version.
void setColumn(unsigned index, const Tuple4Tpl< T > &v)
Sets the content of a given column.
float applyX(const Tuple4Tpl< float > &vec) const
Get the resulting transformation along X dimension (float version)
ccGLMatrixTpl< T > & operator=(const ccGLMatrixTpl< T > &mat)
Copy assignment operator.
virtual bool isIdentity() const
Returns whether this matrix is equal to identity.
void scaleRow(unsigned rowIndex, T coef)
Scales one row of the matrix.
const T * data() const
Returns a const pointer to internal data.
void initFromParameters(T phi_rad, T theta_rad, T psi_rad, const Vector3Tpl< T > &t3D)
Inits transformation from 3 rotation angles and a translation.
T * getTranslation()
Retruns a pointer to internal translation.
T * data()
Returns a pointer to internal data.
void clearTranslation()
Clears translation.
const T * getTranslation() const
Retruns a const pointer to internal translation.
Vector3Tpl< float > operator*(const Vector3Tpl< float > &vec) const
Multiplication by a vector operator (float version)
float applyW(const Tuple4Tpl< float > &vec) const
Get the resulting transformation along the 4th dimension (float version)
ccGLMatrixTpl(const Eigen::Matrix< float, 3, 3 > &mat)
void setTranslation(const float Tr[3])
Sets translation from a float array.
void shiftRotationCenter(const Vector3Tpl< T > &vec)
Shifts rotation center.
float applyY(const Vector3Tpl< float > &vec) const
Get the resulting transformation along Y dimension (float version)
bool toFile(QFile &out, short dataVersion) const override
Saves data to binary stream.
Tuple4Tpl< float > operator*(const Tuple4Tpl< float > &vec) const
Multiplication by a 4D vector operator (float version)
static ccGLMatrixTpl< T > FromViewDirAndUpDir(const Vector3Tpl< T > &forward, const Vector3Tpl< T > &up)
Generates a 'viewing' matrix from a looking vector and a 'up' direction.
static Eigen::Matrix< T, 4, 1 > NormalizeQuaternion(const Eigen::Matrix< T, 4, 1 > &qvec)
Converts a quaternion to a rotation matrix.
ccGLMatrixTpl< T > & operator+=(const Vector3Tpl< double > &Tr)
(in place) Forward translation operator (double version)
void invert()
Inverts transformation.
void scaleColumn(unsigned colIndex, T coef)
Scales one column of the matrix.
ccGLMatrixTpl< T > & operator-=(const ccGLMatrixTpl< T > &mat)
(in place) Difference operator
Tuple4Tpl< double > operator*(const Tuple4Tpl< double > &vec) const
Multiplication by a 4D vector operator (double version)
double applyX(const Vector3Tpl< double > &vec) const
Get the resulting transformation along X dimension (double version)
ccGLMatrixTpl< T > operator*(const ccGLMatrixTpl< T > &mat) const
Multiplication by a matrix operator.
double applyY(const Tuple4Tpl< double > &vec) const
Get the resulting transformation along Y dimension (double version)
void apply(double vec[3]) const
Applies transformation to a 3D vector (in place) - double version.
void setRotation(const float Rt[9])
Sets Rotation from a float array.
static ccGLMatrixTpl Interpolate(T coef, const ccGLMatrixTpl< T > &glMat1, const ccGLMatrixTpl< T > &glMat2)
Interpolates two matrices at relative position 'coef'.
Vector3Tpl< double > operator*(const Vector3Tpl< double > &vec) const
Multiplication by a vector operator (double version)
void scaleLine(unsigned lineIndex, T coef)
Scales one line of the matrix.
static Eigen::Matrix< T, 4, 4 > ToEigenMatrix4(const ccGLMatrixTpl< double > &mat)
void applyRotation(Vector3Tpl< double > &vec) const
Applies rotation only to a 3D vector (in place) - double version.
static ccGLMatrixTpl< T > QuaternionToRotationMatrix(const Tuple4Tpl< T > &qvec)
Converts a quaternion to a rotation matrix.
virtual bool fromAsciiFile(QString filename)
Loads matrix from an ASCII file.
ccGLMatrixTpl(const double *mat16d)
Constructor from a double GL matrix array.
float applyZ(const Tuple4Tpl< float > &vec) const
Get the resulting transformation along Z dimension (float version)
void setRotation(const double Rt[9])
Sets Rotation from a double array.
ccGLMatrixTpl< T > inverse() const
Returns inverse transformation.
void apply(float vec[3]) const
Applies transformation to a 3D vector (in place) - float version.
void setTranslation(const double Tr[3])
Sets translation from a double array.
float applyX(const Vector3Tpl< float > &vec) const
Get the resulting transformation along X dimension (float version)
void setTranslation(const Vector3Tpl< float > &Tr)
Sets translation (float version)
void scaleRotation(T coef)
Scales the rotation part of the matrix.
ccGLMatrixTpl< T > & operator+=(const Vector3Tpl< float > &Tr)
(in place) Forward translation operator (float version)
Vector3Tpl< T > getColumnAsVec3D(unsigned index) const
Returns a copy of a given column as a CCVector3.
void toEulerAngle(T &rz, T &ry, T &rx) const
Returns equivalent parameters: 3 rotation angles.
const T * getColumn(unsigned index) const
Returns a const pointer to a given column.
void apply(Tuple4Tpl< double > &vec) const
Applies transformation to a 3D vector (in place) - double version.
double applyY(const Vector3Tpl< double > &vec) const
Get the resulting transformation along Y dimension (double version)
ccGLMatrixTpl< T > & operator=(const Eigen::Matrix< float, 3, 3 > &mat)
static Eigen::Matrix< T, 3, 3 > QuaternionToRotationMatrix(const Eigen::Matrix< T, 4, 1 > &qvec)
Converts a quaternion to a rotation matrix.
void scale(T coef)
Scales the whole matrix.
static ccGLMatrixTpl< T > FromString(const QString &matText, bool &success)
Converts a 'text' matrix to a ccGLMatrix.
ccGLMatrixTpl()
Default constructor.
short minimumFileVersion() const override
Returns the minimum file version required to save this instance.
void apply(Vector3Tpl< double > &vec) const
Applies transformation to a 3D vector (in place) - double version.
ccGLMatrixTpl< T > yRotation() const
Returns the rotation component around Y only.
ccGLMatrixTpl< T > & operator=(const Eigen::Matrix< double, 3, 3 > &mat)
void transpose()
Transposes matrix (in place)
ccGLMatrixTpl(const Eigen::Matrix< double, 3, 3 > &mat)
double applyZ(const Vector3Tpl< double > &vec) const
Get the resulting transformation along Z dimension (double version)
double applyX(const Tuple4Tpl< double > &vec) const
Get the resulting transformation along X dimension (double version)
void initFromParameters(T alpha_rad, const Vector3Tpl< T > &axis3D, const Vector3Tpl< T > &t3D)
Inits transformation from a rotation axis, an angle and a translation.
T m_mat[OPENGL_MATRIX_SIZE]
Internal 4x4 GL-style matrix data.
ccGLMatrixTpl(const ccGLMatrixTpl< T > &mat)
Copy constructor.
virtual void toIdentity()
Sets matrix to identity.
ccGLMatrixTpl< T > & operator=(const Eigen::Matrix< float, 4, 4 > &mat)
Assignment Function.
double applyW(const Tuple4Tpl< double > &vec) const
T * getColumn(unsigned index)
Returns a pointer to a given column.
ccGLMatrixTpl< T > & operator=(const Eigen::Matrix< double, 4, 4 > &mat)
double applyZ(const Tuple4Tpl< double > &vec) const
Get the resulting transformation along Z dimension (double version)
ccGLMatrixTpl< T > & operator*=(const ccGLMatrixTpl< T > &mat)
(in place) Multiplication operator
static Eigen::Matrix< T, 3, 3 > ToEigenMatrix3(const ccGLMatrixTpl< float > &mat)
float applyZ(const Vector3Tpl< float > &vec) const
Get the resulting transformation along Z dimension (float version)
static Eigen::Matrix< T, 4, 4 > ToEigenMatrix4(const ccGLMatrixTpl< float > &mat)
void getParameters(T &alpha_rad, Vector3Tpl< T > &axis3D, Vector3Tpl< T > &t3D) const
ccGLMatrixTpl< T > xRotation() const
Returns the rotation component around X only.
virtual bool toAsciiFile(QString filename, int precision=12) const
Saves matrix to an ASCII file.
Serializable object interface.
static bool CorruptError()
Sends a custom error message (corrupted file) and returns 'false'.
QMultiMap< unsigned, unsigned > LoadedIDMap
Map of loaded unique IDs (old ID --> new ID)
static bool ReadError()
Sends a custom error message (read error) and returns 'false'.
static bool WriteError()
Sends a custom error message (write error) and returns 'false'.
__host__ __device__ float2 fabs(float2 v)
Definition: cutil_math.h:1254
#define CC_MAT_R12
#define CC_MAT_R33
#define CC_MAT_R34
#define CC_MAT_R44
#define CC_MAT_R41
#define CC_MAT_R21
#define CC_MAT_R13
#define CC_MAT_R14
#define CC_MAT_R22
#define CC_MAT_R42
#define CC_MAT_R24
#define CC_MAT_R43
#define CC_MAT_R31
#define CC_MAT_R23
#define CC_MAT_R11
static const unsigned OPENGL_MATRIX_SIZE
Model view matrix size (OpenGL)
#define CC_MAT_R32
constexpr Qt::SplitBehavior SkipEmptyParts
Definition: QtCompat.h:302
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
bool GreaterThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
Definition: CVMath.h:37
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
Definition: CVMath.h:23
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
Definition: SmallVector.h:1370