MeVisLab Toolbox Reference
mlQuaternion.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2007, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #ifndef ML_QUATERNION_H
14 #define ML_QUATERNION_H
15 
21 
22 // Resolves system dependencies and load project settings.
23 #include "mlLinearAlgebraSystem.h"
24 
25 // 3D double vector.
26 #include "mlVector3.h"
27 #include <mlErrorMacros.h>
28 #include <mlErrorOutput.h>
29 #include <mlPrintTemplateErrors.h>
30 
31 ML_LA_START_NAMESPACE
32 
33 //--------------------------------------------------------
37 //--------------------------------------------------------
38 template <typename DT>
40 {
41 
42 public:
43 
45  typedef DT value_type;
46 
47  //------------------------------------------------------
50  //------------------------------------------------------
51  union {
52  // We use a union to make the members accessible
53  // either
54  // - as named members qx, qy, qz, and qw,
55  // - as array[0..3] and
56  // - vector (qv, qw) via an access method qv().
57  // We also provide indexing operators [] on the array.
58  // Note:
59  // The real part qw is stored in the last component.
60 
61  //------------------------------------------------------
64  //------------------------------------------------------
65  struct {
66  DT qx;
67  DT qy;
68  DT qz;
69  DT qw;
70  };
71 
72  //------------------------------------------------------
79  //------------------------------------------------------
80  DT array[4];
81  };
83 
84 
85  //------------------------------------------------------
88  //------------------------------------------------------
90  inline TQuaternion() :
91  qx(0), qy(0), qz(0), qw(0) { }
92 
95  inline explicit TQuaternion(DT d) :
96  qx(0), qy(0), qz(0), qw(d)
97  {
98  }
99 
104  template <typename DT2>
105  inline explicit TQuaternion(const TQuaternion<DT2> &q2)
106  {
107  qx = static_cast<DT>(q2.qx);
108  qy = static_cast<DT>(q2.qy);
109  qz = static_cast<DT>(q2.qz);
110  qw = static_cast<DT>(q2.qw);
111  }
112 
114  TQuaternion(const TQuaternion &q2) = default;
115 
123  inline explicit TQuaternion(DT x, DT y, DT z, DT w)
124  {
125  qx = x;
126  qy = y;
127  qz = z;
128  qw = w;
129  }
130 
139  inline explicit TQuaternion(const FloatingPointVector<DT,4> &v)
140  {
141  qx = v[1];
142  qy = v[2];
143  qz = v[3];
144  qw = v[0];
145  }
146 
151  inline explicit TQuaternion(const FloatingPointVector<DT, 3, Vector3DataContainer<DT> > &v, DT w) :
152  qx(v[0]), qy(v[1]), qz(v[2]), qw(w)
153  {
154  }
155 
157 
158 
159  //-------------------------------------------------------------------------
162  //-------------------------------------------------------------------------
163 
167  {
168  return qv();
169  }
170 
172  inline DT getRealPart() const
173  {
174  return qw;
175  }
176 
185  {
186  return reinterpret_cast<const FloatingPointVector<DT, 3, Vector3DataContainer<DT> >&>(qx);
187  }
188 
194  {
195  return reinterpret_cast<FloatingPointVector<DT, 3, Vector3DataContainer<DT> >&>(qx);
196  }
197 
201  inline void set(const FloatingPointVector<DT, 3, Vector3DataContainer<DT> > &v, const DT w)
202  {
203  qx = v[0];
204  qy = v[1];
205  qz = v[2];
206  qw = w;
207  }
208 
211  inline void set(const DT x, const DT y, const DT z, const DT w)
212  {
213  qx = x;
214  qy = y;
215  qz = z;
216  qw = w;
217  }
218 
224  inline Tmat4<DT> getAsMat4(bool *isConvertible=nullptr) const
225  {
226  // Create return value.
227  Tmat4<DT> m;
228  // Check whether conversion is possible.
229  const DT n=norm();
230  if (0==n) {
231  if (!isConvertible){
232  printTemplateError("TQuaternion::getAsMat4() const, quaternion is not convertible to 4x4 matrix",
234  "Returning Quaterion");
235  }
236  else{
237  *isConvertible = false;
238  }
240  }
241  else{
242  // Conversion is possible.
243  const DT s = 2./n;
244  //s is a compressed factor
245  //it originates from the constant factor 2 and the normalization
246  //factor for the vector "1/sqrt(norm(vector))"
247  //To normalize the vector each component is divided by "1/sqrt(norm(vector))"
248  //So each vector component qx,qy,qz has to get its own factor to normalize
249  //the vector while calculating the matrix. However, as s is multiplied
250  //always to a pair of 2 multiplied vector components, the factor can be
251  //pulled in front of the addition (c.f. m11). As pairs of vector components
252  //are added, the sqrt vanishes and what is left is the factor 2./norm(vector)
253  //where norm is what is defined as "norm()" inside the mlQuaternion.h.
254 
255  // q0 = qw, first column.
256  const DT qxqx = qx*qx;
257  const DT qyqy = qy*qy;
258  const DT qzqz = qz*qz;
259 
260  const DT qxqy = qx*qy;
261  const DT qxqz = qx*qz;
262  const DT qxqw = qx*qw;
263 
264  const DT qyqz = qy*qz;
265  const DT qyqw = qy*qw;
266 
267  const DT qzqw = qz*qw;
268 
269  const DT m11 = 1 - s * (qyqy + qzqz);
270  const DT m12 = s * (qxqy - qzqw);
271  const DT m13 = s * (qxqz + qyqw);
272 
273  const DT m21 = s * (qxqy + qzqw);
274  const DT m22 = 1 - s * (qxqx + qzqz);
275  const DT m23 = s * (qyqz - qxqw);
276 
277  const DT m31 = s * (qxqz - qyqw);
278  const DT m32 = s * (qyqz + qxqw);
279  const DT m33 = 1 - s * (qxqx + qyqy);
280 
281  // Construct matrix from precomputed values
282  m.set(0);
283  m[0][0] = m11;
284  m[0][1] = m12;
285  m[0][2] = m13;
286  m[0][3] = 0.0;
287 
288  m[1][0] = m21;
289  m[1][1] = m22;
290  m[1][2] = m23;
291  m[1][3] = 0.0;
292 
293  m[2][0] = m31;
294  m[2][1] = m32;
295  m[2][2] = m33;
296  m[2][3] = 0.0;
297 
298  m[3][0] = 0.0;
299  m[3][1] = 0.0;
300  m[3][2] = 0.0;
301  m[3][3] = 1.0;
302 
303  if (isConvertible){ *isConvertible = true; }
304 
305  } // else
306  return m;
307  }
308 
310 
311 
312  //-------------------------------------------------------------------------
315  //-------------------------------------------------------------------------
316 
320  inline DT operator[](const size_t i) const { return array[i]; }
321 
325  inline DT &operator[](const size_t i) { return array[i]; }
326 
329  {
330  if (this != &q){
331  qx = q.qx;
332  qy = q.qy;
333  qz = q.qz;
334  qw = q.qw;
335  }
336  return *this;
337  }
339 
340 
341  //------------------------------------------------------
344  //------------------------------------------------------
345 
347  inline TQuaternion<DT> operator + (const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx+b.qx, qy+b.qy, qz+b.qz, qw+b.qw); }
349  inline TQuaternion<DT> &operator += (const TQuaternion<DT> &b) { qx+=b.qx; qy+=b.qy; qz+=b.qz; qw+=b.qw; return *this; }
350 
352  inline TQuaternion<DT> operator - (const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx-b.qx, qy-b.qy, qz-b.qz, qw-b.qw); }
354  inline TQuaternion<DT> &operator -= (const TQuaternion<DT> &b) { qx-=b.qx; qy-=b.qy; qz-=b.qz; qw-=b.qw; return *this; }
355 
357  inline TQuaternion<DT> operator * (const TQuaternion<DT> &b) const { return mult(b); }
359  inline TQuaternion<DT> &operator *= (const TQuaternion<DT> &b) { *this = mult(b); return *this; }
360 
363  {
364  TQuaternion<DT> retVal(*this);
365  ML_CHECK_FLOAT(d);
366  retVal /= d;
367  return retVal;
368  }
369 
372  {
373  ML_CHECK_FLOAT(d);
374  qx/=d; qy/=d; qz/=d; qw/=d;
375  return *this;
376  }
377 
378 
381  {
382  return TQuaternion<DT>(div(q));
383  }
384 
389  inline TQuaternion<DT> compDiv(const TQuaternion<DT> &b, bool *isError=nullptr) const
390  {
391  // Initialize return value with default quaternion.
392  TQuaternion<DT> retVal(0,0,0,1);
393  if (!isError){
394  // No error flag passed. Handle error if necessary.
395  ML_CHECK_FLOAT(b.qx);
396  ML_CHECK_FLOAT(b.qy);
397  ML_CHECK_FLOAT(b.qz);
398  ML_CHECK_FLOAT(b.qw);
399  retVal.set(qx/b.qx, qy/b.qy, qz/b.qz, qw/b.qw);
400  }
401  else{
402  // Error flag is available. Return *isError as true in case of error
403  *isError = (b.qx == 0) ||
404  (b.qy == 0) ||
405  (b.qz == 0) ||
406  (b.qw == 0);
407 
408  retVal = *isError ?
409  TQuaternion<DT>(b.qx != 0 ? qx/b.qx : qx,
410  b.qy != 0 ? qy/b.qy : qy,
411  b.qz != 0 ? qz/b.qz : qz,
412  b.qw != 0 ? qw/b.qw : qw) :
413  TQuaternion<DT>(qx/b.qx,
414  qy/b.qy,
415  qz/b.qz,
416  qw/b.qw);
417  }
418  return retVal;
419  }
420 
423  inline bool operator == (const TQuaternion<DT> &b) const { return MLValuesAreEqualWOM(qx, b.qx) &&
424  MLValuesAreEqualWOM(qy, b.qy) &&
425  MLValuesAreEqualWOM(qz, b.qz) &&
426  MLValuesAreEqualWOM(qw, b.qw); }
429  inline bool operator != (const TQuaternion<DT> &b) const { return !operator==(b); }
431 
432 
433 
435  inline DT dot(const TQuaternion<DT> &p) const { return qx*p.qx + qy*p.qy + qz*p.qz + qw*p.qw; }
436 
439  inline TQuaternion<DT> odd(const TQuaternion<DT> &p) const { return TQuaternion<DT>(qy*p.qz - qz*p.qy,
440  qz*p.qx - qx*p.qz,
441  qx*p.qy - qy*p.qx,
442  0); }
443 
446  inline TQuaternion<DT> even(const TQuaternion<DT> &p) const { return TQuaternion<DT>(qw*p.qx + qx*p.qw,
447  qw*p.qy + qy*p.qw,
448  qw*p.qz + qz*p.qw,
449  qw*p.qw - qx*p.qx - qy*p.qy - qz*p.qz); }
450 
452  inline TQuaternion<DT> mult(const TQuaternion<DT> &q) const { Tvec3<DT> img(qv()); Tvec3<DT> qimg(q.qv()); return TQuaternion<DT>(img.cross(qimg) + img*q.qw + qw*qimg, qw*q.qw - img.dot(qimg)); }
453 
455  inline TQuaternion<DT> euclideanMult(const TQuaternion<DT> &q) const { return conjugate().mult(q); }
456 
458  inline TQuaternion<DT> outer(const TQuaternion<DT> &q) const { return (euclideanMult(q) - q.euclideanMult(*this)) / 2; }
459 
460 
469  inline TQuaternion<DT> div(const TQuaternion<DT> &d, bool *isError=nullptr) const
470  {
471  // Initialize return value with default quaternion.
472  TQuaternion<DT> retVal(0,0,0,1);
473  if (d == TQuaternion<DT>(0,0,0,0)){
474  if (isError == nullptr){
475  // No error flag passed. Handle error if necessary.
476  printTemplateError("TQuaternion::div() const, quaternion is not divisible",
478  "Returning unchanged quaternion");
479  retVal.set(qx,qy,qz,qw);
480  }
481  else{
482  // Error flag pointer is available. Return *isError as true in case of error
483  *isError = true;
484  retVal.set(qx,qy,qz,qw);
485  }
486  }
487  else{
488  if (isError != nullptr){ *isError = false; }
489  retVal.set((d.qw*qx - d.qx*qw - d.qy*qz + d.qz*qy)/(d.qw*d.qw + d.qx*d.qx + d.qy*d.qy + d.qz*d.qz),
490  (d.qw*qy + d.qx*qz - d.qy*qw - d.qz*qx)/(d.qw*d.qw + d.qx*d.qx + d.qy*d.qy + d.qz*d.qz),
491  (d.qw*qz - d.qx*qy + d.qy*qx - d.qz*qw)/(d.qw*d.qw + d.qx*d.qx + d.qy*d.qy + d.qz*d.qz),
492  (d.qw*qw + d.qx*qx + d.qy*qy + d.qz*qz)/(d.qw*d.qw + d.qx*d.qx + d.qy*d.qy + d.qz*d.qz));
493  }
494  return retVal;
495  }
496 
497 
499  inline TQuaternion<DT> mult(DT s) const { return TQuaternion<DT>(qx*s, qy*s, qz*s, qw*s); }
500 
502  inline TQuaternion<DT> add(const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx+b.qx, qy+b.qy, qz+b.qz, qw+b.qw); }
503 
505  inline TQuaternion<DT> add(DT s) const { return TQuaternion<DT>(qx, qy, qz, qw+s); }
506 
508  inline TQuaternion<DT> conjugate() const { return TQuaternion<DT>(-qx, -qy, -qz, qw); }
509 
511  inline TQuaternion<DT> negate() const { return TQuaternion<DT>(-qx, -qy, -qz, -qw); }
512 
514  inline DT norm() const { return qx*qx + qy*qy + qz*qz + qw*qw; }
515 
516 
519  inline DT norm2() const { return static_cast<DT>(::sqrt(qx*qx + qy*qy + qz*qz + qw*qw)); }
520 
523  inline DT absoluteValue() const { return static_cast<DT>(::sqrt(norm())); }
524 
529  inline TQuaternion<DT> normalize(bool *isError=nullptr) const
530  {
531  // Initialize return value with default quaternion.
532  TQuaternion<DT> retVal(0,0,0,1);
533  const DT n=norm2();
534  if (MLValueIs0WOM(n)){
535  // Error! Check whether we have a pointer to a return error code value.
536  if (isError == nullptr){
537  // No, post an error.
538  printTemplateError("TQuaternion::normalize() const, quaternion can not be normalized",
540  "Returning default quaternion");
541  }
542  else{
543  // Yes, set return code.
544  *isError = true;
545  }
546  }
547  else{
548  // Non zero => no error.
549  if (isError){ *isError = false; }
550  retVal.set(qx/n, qy/n, qz/n, qw/n);
551  }
552  return retVal;
553  }
554 
561  inline TQuaternion<DT> arg(bool *isError=nullptr) const
562  {
563  // Initialize return value with default quaternion.
564  TQuaternion<DT> retVal(0,0,0,1);
565  // Norm2 must be non-zero to avoid divisions by zero.
566  const DT n=norm2();
567  if (MLValueIs0WOM(n)){
568  // Error! Check whether we have a pointer to a return error code value.
569  if (isError == nullptr){
570  // No, post an error.
571  printTemplateError("TQuaternion::arg() const, quaternion can not be normalized",
573  "Returning default quaternion");
574  }
575  else{
576  // Yes, set return code.
577  *isError = true;
578  }
579  }
580  else{
581  // Non zero => no error.
582  if (isError != nullptr){ *isError = false; }
583  retVal = acos(qw/n);
584  }
585  return retVal;
586  }
587 
592  inline TQuaternion<DT> sgn(bool *isError=nullptr) const
593  {
594  // Initialize return value with default quaternion.
595  TQuaternion<DT> retVal(0,0,0,1);
596  const DT absVal = absoluteValue();
597  if (isError != nullptr){
598  // Set error return value.
599  if (absVal==0){
600  *isError = true;
601  }
602  else{
603  // No error.
604  *isError = false;
605  retVal = *this / absVal;
606  }
607  }
608  else{
609  // Post error is absVal == 0.
610  ML_CHECK_FLOAT(absVal);
611  retVal = *this / absVal;
612  }
613  return retVal;
614  }
615 
621  inline TQuaternion<DT> inverse(bool* isInvertible=nullptr) const
622  {
623  // Initialize return value with default quaternion.
624  TQuaternion<DT> retVal(0,0,0,1);
625  const DT n=norm();
626  if (MLValueIs0WOM(n)) {
627  if (isInvertible==nullptr){
628  printTemplateError("TQuaternion::() const, quaternion is not invertable",
630  "Returning default quaternion");
631  }
632  else{
633  *isInvertible = false;
634  }
635  retVal = TQuaternion<DT>();
636  }
637  else{
638  if (isInvertible != nullptr){ *isInvertible = true; }
639  retVal = conjugate().mult(1/n);
640  }
641  return retVal;
642  }
643 
648  // return TQuaternion(::sqrt(norm2())*::sin(0.5*acos(qw/norm2()))*(1/qv().length())*Tvec3<DT>(qx,qy,qz),
649  inline TQuaternion<DT> sqrt(bool *isError=nullptr) const
650  {
651  // Initialize return value with default quaternion.
652  TQuaternion<DT> retVal(0,0,0,1);
653  // Precalculate constants and check for 0 division.
654  const DT n2 = norm2();
655  const DT lqv = qv().length();
656  if (MLValueIs0WOM(n2) || MLValueIs0WOM(lqv)){
657  // Error! Check whether we have a pointer to a return error code value.
658  if (isError == nullptr){
659  // No, post an error.
660  printTemplateError("TQuaternion::sqrt() const, sqrt of quaternion cannot be calculated",
662  "Returning default quaternion");
663  }
664  else{
665  // Yes, set return code.
666  *isError = true;
667  }
668  }
669  else{
670  // Calculate sqrt, lqv and n2 are non 0 here.
671  const DT sqrtSin = ::sqrt(n2)*::sin(0.5*acos(qw/n2));
672  const DT sqrtSinF = sqrtSin*(1/lqv);
673  retVal.set(sqrtSinF*qx, sqrtSinF*qy, sqrtSinF*qz, ::sqrt(n2) * ::cos(0.5*acos(qw/n2)));
674 
675  // Non zero => no error.
676  if (isError != nullptr){ *isError = false; }
677  }
678  return retVal;
679  }
680 
681 
685 
687  inline TQuaternion<DT> exp() const
688  {
689  // Initialize return value with default quaternion.
690  TQuaternion<DT> retVal(0,0,0,1);
691  const DT len = qv().length();
692  if (MLValueIs0WOM(len)){
693  retVal = TQuaternion<DT>(0,0,0,::cos(len)).mult(::exp(qw));
694  }
695  else{
696  retVal = TQuaternion<DT>((qv()/len) * static_cast<DT>(::sin(len)), ::cos(len)).mult(::exp(qw));
697  }
698  return retVal;
699  }
700 
701 
703  inline TQuaternion<DT> ln() const
704  {
705  // Initialize return value with default quaternion.
706  TQuaternion<DT> retVal(0,0,0,1);
707  const DT n2 = norm2();
708  const DT qvLen = qv().length();
709  if (MLValueIs0WOM(qvLen)){
710  retVal.set(0, 0, 0, log10(n2));
711  }
712  else{
713  // n2 is always non 0 if qvLen is non-zero, thus no check is necessary.
714  retVal.set(qv()/qvLen * static_cast<DT>(acos(qw/n2)), log10(n2));
715  }
716  return retVal;
717  }
718 
719 
721  inline TQuaternion<DT> pow(const TQuaternion<DT> &quat) const {return ln().mult(quat).exp(); }
722 
723 
727 
730  {
731  TQuaternion<DT> retVal;
732  const Tvec3<DT> &v = qv();
733  const DT len = v.length();
734  // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
735  // Then the quaternion method behaves like the normal function on real values.
736  retVal.set((!MLValueIs0WOM(len) ?
737  static_cast<DT>(::cos(qw)) * v / len * static_cast<DT>(::sinh(len)) :
738  Tvec3<DT>(0.0)),
739  ::sin(qw)*::cosh(len)
740  );
741  return retVal;
742  }
743 
746  {
747  TQuaternion<DT> retVal;
748  const Tvec3<DT> &v = qv();
749  const DT len = v.length();
750  // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
751  // Then the quaternion method behaves like the normal function on real values.
752  retVal.set((!MLValueIs0WOM(len) ?
753  static_cast<DT>(-1)*static_cast<DT>(::sin(qw))*qv()/len*static_cast<DT>(::sinh(len)) :
754  Tvec3<DT>(0.0)),
755  ::cos(qw)*::cosh(len)
756  );
757  return retVal;
758  }
759 
761  inline TQuaternion<DT> tan(bool *isError=nullptr) const { return sin().div(cos(), isError); }
762 
764  inline TQuaternion<DT> cotan(bool *isError=nullptr) const { return cos().div(sin(), isError); }
765 
766 
767 
771 
774  {
775  TQuaternion<DT> retVal;
776  const Tvec3<DT> &v = qv();
777  const DT len = v.length();
778  // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
779  // Then the quaternion method behaves like the normal function on real values.
780  retVal.set((!MLValueIs0WOM(len) ?
781  static_cast<DT>(::cosh(qw))*v/len*static_cast<DT>(::sin(len)) :
782  Tvec3<DT>(0.0)),
783  ::sinh(qw)*::cos(len)
784  );
785  return retVal;
786  }
787 
790  {
791  TQuaternion<DT> retVal;
792  const Tvec3<DT> &v = qv();
793  const DT len = v.length();
794  // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
795  // Then the quaternion method behaves like the normal function on real values.
796  retVal.set((!MLValueIs0WOM(len) ?
797  static_cast<DT>(::sinh(qw))*v/len*static_cast<DT>(::sin(len)) :
798  Tvec3<DT>(0.0)),
799  ::cosh(qw)*::cos(len)
800  );
801  return retVal;
802  }
803 
805  inline TQuaternion<DT> tanh(bool *isError=nullptr) const
806  {
807  return sinh().div(cosh(), isError);
808  }
809 
811  inline TQuaternion<DT> cotanh(bool *isError=nullptr) const
812  {
813  return cosh().div(sinh(), isError);
814  }
815 
816 
817 
821 
823  inline TQuaternion<DT> arcsinh() const { return add(mult(*this).add(TQuaternion<DT>( 1)).sqrt()).ln(); }
824 
826  inline TQuaternion<DT> arccosh() const { return add(mult(*this).add(TQuaternion<DT>(-1)).sqrt()).ln(); }
827 
829  inline TQuaternion<DT> arctanh() const { return TQuaternion<DT>((TQuaternion<DT>(qx,qy,qz,qw+1).ln()-TQuaternion<DT>(-qx, -qy, -qz, 1-qw).ln())/0.5); }
830 
831 
841  #define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR) \
842  TQuaternion<DT> retVal; \
843  { \
844  const Tvec3<DT> &v = qv(); \
845  const DT len = v.length(); \
846  if (MLValueIs0WOM(len)){ \
847  /* Error! Check whether we have a pointer to a return error code value. */ \
848  if (isError == NULL){ \
849  /* No, post an error. */ \
850  printTemplateError("TQuaternion::" FUNC_NAME "() const, " FUNC_NAME \
851  " of quaternion cannot be calculated", \
852  ML_BAD_PARAMETER, \
853  "Returning default quaternion"); \
854  } \
855  else{ \
856  /* Yes, set return code, retVal is left on default. */ \
857  *isError = true; \
858  } \
859  } \
860  else{ \
861  /* Define return values. */ \
862  if (isError != NULL){ *isError = false; } \
863  retVal = CALC_EXPR; \
864  } \
865  } \
866  return retVal; \
867 
868 
869 
871  #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arcsinh());
875 
877  TQuaternion<DT> arcsin(bool *isError=nullptr) const
878  {
880  }
881  #undef _ML_QUAT_CALC_EXP
882 
883 
884 
886  #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(arccosh());
888  TQuaternion<DT> arccos(bool *isError=nullptr) const
889  {
891  }
892  #undef _ML_QUAT_CALC_EXP
893 
894 
895 
897  #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arctanh());
899  TQuaternion<DT> arctan(bool *isError=nullptr) const
900  {
902  }
903  #undef _ML_QUAT_CALC_EXP
904 
905 
906  // Undefines _ML_QUATERNION_CALC_CHECKED, it is not needed anymore.
907  #undef _ML_QUATERNION_CALC_CHECKED
908 };
909 
910 
911 //-----------------------------------------------------------------------------------
914 //-----------------------------------------------------------------------------------
917 
920 
923 
927 
928 
929 ML_LA_END_NAMESPACE
930 
931 
932 
933 
934 //-------------------------------------------------------------------------
941 //-------------------------------------------------------------------------
942 #ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
943 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
944 ML_LA_START_NAMESPACE
945 #endif
946 
947 //-----------------------------
948 // Addition
949 //-----------------------------
951 template <typename DT>
952 inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
953  return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
954 }
955 
957 template <typename DT>
958 inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
959  return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
960 }
961 
963 template <typename DT>
964 inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
965  const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
966  return qa.operator+(qb);
967 }
968 
969 
970 
971 //-----------------------------
972 // Subtraction
973 //-----------------------------
975 template <typename DT>
976 inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
977  return ML_LA_NAMESPACE::TQuaternion<DT>(-q.qx, -q.qy, -q.qz, d-q.qw);
978 }
979 
981 template <typename DT>
982 inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
983  return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw-d);
984 }
985 
987 template <typename DT>
988 inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
989  const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
990  return qa.operator-(qb);
991 }
992 
993 
995 template <typename DT>
996 inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
997  return q.mult(d);
998 }
999 
1001 template <typename DT>
1002 inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
1003  return q.mult(d);
1004 }
1005 
1007 template <typename DT>
1008 inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
1009  const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
1010  return qa.operator*(qb);
1011 }
1013 
1014 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1015 ML_LA_END_NAMESPACE
1016 #endif
1017 
1018 #endif // _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
1019 
1020 
1021 
1022 //-------------------------------------------------------------------------
1029 //-------------------------------------------------------------------------
1030 #ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1031 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1032 ML_LA_START_NAMESPACE
1033 #endif
1034 
1037 #ifdef _ML_IMPLEMENT_QUATERNION_SQRT
1038 template <typename DT>
1039 inline ML_LA_NAMESPACE::TQuaternion<DT> sqrt (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sqrt(); }
1040 #endif
1041 
1043 template <typename DT>
1044 inline ML_LA_NAMESPACE::TQuaternion<DT> exp (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.exp(); }
1045 
1047 template <typename DT>
1048 inline ML_LA_NAMESPACE::TQuaternion<DT> ln (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.ln(); }
1049 
1051 template <typename DT>
1052 inline ML_LA_NAMESPACE::TQuaternion<DT> sin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sin(); }
1053 
1055 template <typename DT>
1056 inline ML_LA_NAMESPACE::TQuaternion<DT> cos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cos(); }
1057 
1059 template <typename DT>
1060 inline ML_LA_NAMESPACE::TQuaternion<DT> tan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tan(); }
1061 
1063 template <typename DT>
1064 inline ML_LA_NAMESPACE::TQuaternion<DT> cotan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotan(); }
1065 
1067 template <typename DT>
1068 inline ML_LA_NAMESPACE::TQuaternion<DT> sinh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sinh(); }
1069 
1071 template <typename DT>
1072 inline ML_LA_NAMESPACE::TQuaternion<DT> cosh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cosh(); }
1073 
1075 template <typename DT>
1076 inline ML_LA_NAMESPACE::TQuaternion<DT> tanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tanh(); }
1077 
1079 template <typename DT>
1080 inline ML_LA_NAMESPACE::TQuaternion<DT> cotanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotanh(); }
1081 
1083 template <typename DT>
1084 inline ML_LA_NAMESPACE::TQuaternion<DT> arcsinh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsinh(); }
1085 
1087 template <typename DT>
1088 inline ML_LA_NAMESPACE::TQuaternion<DT> arccosh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccosh(); }
1089 
1091 template <typename DT>
1092 inline ML_LA_NAMESPACE::TQuaternion<DT> arctanh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctanh(); }
1093 
1095 template <typename DT>
1096 inline ML_LA_NAMESPACE::TQuaternion<DT> arcsin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsin(); }
1097 
1099 template <typename DT>
1100 inline ML_LA_NAMESPACE::TQuaternion<DT> arccos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccos(); }
1101 
1103 template <typename DT>
1104 inline ML_LA_NAMESPACE::TQuaternion<DT> arctan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctan(); }
1105 
1106 
1107 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1108 ML_LA_END_NAMESPACE
1109 #endif
1110 
1111 #endif // _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1113 
1114 
1115 //-----------------------------------------------------------------------------------
1116 // Stream output for std::ostream and dyadic multiplication of TQuaternion and scalar.
1117 //-----------------------------------------------------------------------------------
1118 namespace std {
1119 
1121  template <typename DT>
1122  inline ostream& operator<<(ostream& s, const ML_NAMESPACE::TQuaternion<DT> &v){
1123  return s << "(" << v.qx << "," << v.qy << "," << v.qz << "," << v.qw << ")";
1124  }
1125 
1126 }
1127 
1128 
1129 #endif // __mlQuaternion_H
FloatingPointVector< T, 3, DataContainer > cross(const FloatingPointVector< T, 3, DataContainer > &b) const
Returns the cross product for elements, i.e., the returned vector is orthogonal to *this and b.
T length() const
Returns the length of the vector, i.e., norm2().
T operator*(const FloatingPointVector< T, size, DataContainer > &a, const FloatingPointVector< T, size, DataContainer > &b)
Dot product, returns a.dot(b).
T dot(const FloatingPointVector< T, size, DataContainer > &buffer) const
Returns the dot product, i.e., sum of all components multiplied with corresponding components of buff...
FloatingPointVector< T, size, DataContainer > operator+(FloatingPointVector< T, size, DataContainer > lhs, const FloatingPointVector< T, size, DataContainer > &rhs)
Return value is the component-wise addition of lhs and rhs.
FloatingPointVector< T, size, DataContainer > operator-(FloatingPointVector< T, size, DataContainer > lhs, const FloatingPointVector< T, size, DataContainer > &rhs)
Return value is the component-wise subtraction of rhs from lhs.
Declaration of complex type traits.
Definition: mlQuaternion.h:40
TQuaternion(DT d)
Builds a quaternion from a scalar by setting all elements to 0 and qw to the scalar; use explicitly t...
Definition: mlQuaternion.h:95
DT dot(const TQuaternion< DT > &p) const
Dot product, equivalent to four component vector dot product.
Definition: mlQuaternion.h:435
TQuaternion< DT > add(const TQuaternion< DT > &b) const
Adds another quaternion b to this one and returns the sum.
Definition: mlQuaternion.h:502
DT & operator[](const size_t i)
Indexing operator.
Definition: mlQuaternion.h:325
TQuaternion(DT x, DT y, DT z, DT w)
Creates a new TQuaternion with the DT values given.
Definition: mlQuaternion.h:123
DT qx
First element of imaginary part.
Definition: mlQuaternion.h:66
TQuaternion< DT > exp() const
Exponential and logarithmic functions: natural exponential, natural logarithm, power.
Definition: mlQuaternion.h:687
TQuaternion< DT > normalize(bool *isError=nullptr) const
Returns the normalization of the quaternion.
Definition: mlQuaternion.h:529
DT absoluteValue() const
Returns the absolute value of a quaternion, which is the scalar quantity that determines the length o...
Definition: mlQuaternion.h:523
TQuaternion< DT > cotanh(bool *isError=nullptr) const
Computes the hyperbolic cotangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:811
TQuaternion< DT > inverse(bool *isInvertible=nullptr) const
Computes and returns the inverse.
Definition: mlQuaternion.h:621
TQuaternion< DT > arctanh() const
Computes the inverse hyperbolic tangent.
Definition: mlQuaternion.h:829
TQuaternion< DT > div(const TQuaternion< DT > &d, bool *isError=nullptr) const
Divides a quaternion by another quaternion.
Definition: mlQuaternion.h:469
TQuaternion< DT > compDiv(const TQuaternion< DT > &b, bool *isError=nullptr) const
Divides each component by its corresponding component from b.
Definition: mlQuaternion.h:389
TQuaternion< DT > sqrt(bool *isError=nullptr) const
Computes the square root of a quaternion.
Definition: mlQuaternion.h:649
void set(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, const DT w)
Sets all quaternion elements from a vector and DT parameter.
Definition: mlQuaternion.h:201
TQuaternion< DT > sinh() const
Hyperbolic functions: Hyperbolic sine, hyperbolic cosine, hyperbolic tangent https://en....
Definition: mlQuaternion.h:773
TQuaternion< DT > tanh(bool *isError=nullptr) const
Computes the hyperbolic tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:805
TQuaternion< DT > cosh() const
Computes the hyperbolic cosine.
Definition: mlQuaternion.h:789
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv()
Returns a modifiable reference to the quaternion's imaginary part as vector object,...
Definition: mlQuaternion.h:193
TQuaternion< DT > conjugate() const
Computes the conjugate.
Definition: mlQuaternion.h:508
TQuaternion< DT > even(const TQuaternion< DT > &p) const
Even product, also known as Grassman inner product.
Definition: mlQuaternion.h:446
TQuaternion< DT > negate() const
Computes the negation.
Definition: mlQuaternion.h:511
TQuaternion< DT > euclideanMult(const TQuaternion< DT > &q) const
Euclidean product of this quaternion with another one (which is non-commutative).
Definition: mlQuaternion.h:455
TQuaternion< DT > arg(bool *isError=nullptr) const
Computes the quaternion argument.
Definition: mlQuaternion.h:561
TQuaternion< DT > arcsin(bool *isError=nullptr) const
Inverse trigonometric functions: Inverse sine, inverse cosine, inverse tangent.
Definition: mlQuaternion.h:877
DT norm() const
Computes the d-norm.
Definition: mlQuaternion.h:514
TQuaternion< DT > mult(DT s) const
Multiplies this quaternion with a scalar factor s.
Definition: mlQuaternion.h:499
TQuaternion()
Standard constructor that is setting all elements to 0.
Definition: mlQuaternion.h:90
TQuaternion< DT > cos() const
Computes the cosine.
Definition: mlQuaternion.h:745
DT qw
Real part.
Definition: mlQuaternion.h:69
TQuaternion< DT > odd(const TQuaternion< DT > &p) const
Odd product, also known as cross-product or Grassman outer product.
Definition: mlQuaternion.h:439
DT value_type
Scalar type used for qx, qy, qz, and qw.
Definition: mlQuaternion.h:45
TQuaternion< DT > cotan(bool *isError=nullptr) const
Computes the cotangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:764
TQuaternion< DT > tan(bool *isError=nullptr) const
Computes the tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:761
TQuaternion< DT > sin() const
Trigonometric functions: sine, cosine, tangent, cotangent.
Definition: mlQuaternion.h:729
TQuaternion< DT > outer(const TQuaternion< DT > &q) const
Euclidean outer product of this quaternion with another one.
Definition: mlQuaternion.h:458
void set(const DT x, const DT y, const DT z, const DT w)
Sets all quaternion elements qx, qy, qz, and qw from parameters x, y, z, and w, respectively.
Definition: mlQuaternion.h:211
TQuaternion< DT > mult(const TQuaternion< DT > &q) const
Multiplies this quaternion with another one (which is non-commutative). It is also called Grassman pr...
Definition: mlQuaternion.h:452
DT norm2() const
Computes the magnitude of the quaternion.
Definition: mlQuaternion.h:519
TQuaternion(const TQuaternion< DT2 > &q2)
Copy constructor from another TQuaternion of same or different type.
Definition: mlQuaternion.h:105
TQuaternion< DT > arcsinh() const
Inverse hyperbolic function: arcsinh, arccosh, arctanh.
Definition: mlQuaternion.h:823
TQuaternion< DT > ln() const
Computes the natural logarithm.
Definition: mlQuaternion.h:703
TQuaternion< DT > arctan(bool *isError=nullptr) const
Inverse tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:899
const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv() const
Returns a constant reference to the quaternion's imaginary part as vector object.
Definition: mlQuaternion.h:184
DT qz
Third element of imaginary part.
Definition: mlQuaternion.h:68
Tmat4< DT > getAsMat4(bool *isConvertible=nullptr) const
Converts this quaternion to a 4x4 matrix.
Definition: mlQuaternion.h:224
TQuaternion(const FloatingPointVector< DT, 4 > &v)
Creates a new TQuaternion from the four-dimensional parameter vector.
Definition: mlQuaternion.h:139
TQuaternion< DT > pow(const TQuaternion< DT > &quat) const
Computes the power of a quaternion.
Definition: mlQuaternion.h:721
DT operator[](const size_t i) const
Constant indexing operator.
Definition: mlQuaternion.h:320
TQuaternion< DT > & operator=(const TQuaternion< DT > &q)
Assignment operator.
Definition: mlQuaternion.h:328
TQuaternion< DT > arccos(bool *isError=nullptr) const
Inverse cosine; for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:888
TQuaternion(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, DT w)
Constructor with a vector and DT parameter.
Definition: mlQuaternion.h:151
TQuaternion< DT > sgn(bool *isError=nullptr) const
Returns the sign of the quaternion.
Definition: mlQuaternion.h:592
TQuaternion(const TQuaternion &q2)=default
Explicitly generating the default constructor to avoid a warning message with gcc9.
TQuaternion< DT > add(DT s) const
Adds a scalar s to the quaternion and returns the sum. It is equivalent to a 'scalar add' of s to the...
Definition: mlQuaternion.h:505
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > getImaginaryPart() const
Returns a copy of the quaternion's imaginary part.
Definition: mlQuaternion.h:166
TQuaternion< DT > arccosh() const
Computes the inverse hyperbolic cosine.
Definition: mlQuaternion.h:826
DT getRealPart() const
Returns a copy of the quaternion's real part, also called scalar() of a quaternion.
Definition: mlQuaternion.h:172
DT qy
Second element of imaginary part.
Definition: mlQuaternion.h:67
A 4x4 matrix class consisting of four row vectors.
Definition: mlMatrix4.h:36
void set(const DT val)
Sets all values to val.
Definition: mlMatrix4.h:265
Forward declarations to resolve header file dependencies.
Definition: mlVector3.h:66
Specialized base class for the FloatingPointVectorDataContainerBase.
Definition: mlVector3.h:34
bool MLValueIs0WOM(MLint8 a)
Returns true if value is 0; otherwise, it returns false.
bool MLValuesAreEqualWOM(MLint8 a, MLint8 b)
Returns true if values a and b are equal; otherwise, it returns false.
#define ML_BAD_PARAMETER
A bad/invalid parameter (or even an inappropriate image) has been passed to a module or an algorithm,...
Definition: mlTypeDefs.h:823
#define ML_CHECK_FLOAT(x)
MLEXPORT std::ostream & operator<<(std::ostream &s, const ml::Field &v)
Overloads the operator '<<' for stream output of Field objects.
#define _ML_QUAT_CALC_EXP
Internal helper macro - do not use.
Definition: mlQuaternion.h:897
#define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR)
Defines a code fragment that checks and handles operations for safe expression calculations.
Definition: mlQuaternion.h:841
ScopeGuard< Functor > operator+(ScopeGuardOnExit, Functor &&fn)
Definition: mlScopeGuard.h:82
FloatingPointVector< T, size, DataContainer > operator/(FloatingPointVector< T, size, DataContainer > lhs, MLdouble rhs)
Component-wise division of lhs by specialized rhs of type MLdouble.
void ML_UTILS_EXPORT printTemplateError(const char *location, MLErrorCode reason, const std::string_view &handling)
FloatingPointVector< T, size, DataContainer > & operator/=(FloatingPointVector< T, size, DataContainer > &op1, MLdouble value)
Arithmetic assignment: Component-wise division of *this by scalar value.
TQuaternion< MLdouble > Quaternion
Defines the default Quaternion type that is used by the ML; it uses double as component type.
Definition: mlQuaternion.h:925
FloatingPointVector< T, size, DataContainer > & operator-=(FloatingPointVector< T, size, DataContainer > &op1, const FloatingPointVector< T, size, DataContainer > &buffer)
Arithmetic assignment: Component-wise subtraction of buffer from *this.
TQuaternion< MLfloat > Quaternionf
A smaller Quaternion type as a specialization from TQuaternion.
Definition: mlQuaternion.h:916
bool operator==(const Tmat2< DT > &a, const Tmat2< DT > &b)
a == b ? Returns true if yes.
Definition: mlMatrix2.h:425
T operator*(const FloatingPointVector< T, size, DataContainer > &a, const FloatingPointVector< T, size, DataContainer > &b)
Dot product, returns a.dot(b).
bool operator!=(const Tmat2< DT > &a, const Tmat2< DT > &b)
a != b ? Returns true if yes.
Definition: mlMatrix2.h:433
TQuaternion< MLldouble > Quaternionld
A large Quaternion type for further extensions of the ML as a specialization from TQuaternion.
Definition: mlQuaternion.h:922
TQuaternion< MLdouble > Quaterniond
The default Quaternion type used in the ML as a specialization from TQuaternion.
Definition: mlQuaternion.h:919
FloatingPointVector< T, size, DataContainer > & operator+=(FloatingPointVector< T, size, DataContainer > &op1, const FloatingPointVector< T, size, DataContainer > &buffer)
Arithmetic assignment: Component-wise addition.
FloatingPointVector< T, size, DataContainer > operator-(FloatingPointVector< T, size, DataContainer > lhs, const FloatingPointVector< T, size, DataContainer > &rhs)
Return value is the component-wise subtraction of rhs from lhs.
FloatingPointVector< T, size, DataContainer > & operator*=(FloatingPointVector< T, size, DataContainer > &op1, MLdouble value)
Arithmetic assignment: Component-wise multiplication *this with specialized MLdouble scalar value.