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 
23 
24 // Resolves system dependencies and load project settings.
25 #include "mlLinearAlgebraSystem.h"
26 
27 // 3D double vector.
28 #include "mlVector3.h"
29 #include <mlErrorMacros.h>
30 #include <mlErrorOutput.h>
31 #include <mlPrintTemplateErrors.h>
32 
33 ML_LA_START_NAMESPACE
34 
35 //--------------------------------------------------------
39 //--------------------------------------------------------
40 template <typename DT>
42 {
43 
44 public:
45 
47  typedef DT value_type;
48 
49  //------------------------------------------------------
52  //------------------------------------------------------
53  union {
54  // We use a union to make the members accessible
55  // either
56  // - as named members qx, qy, qz and qw,
57  // - as array[0..3] and
58  // - vector (qv,qw) via an access method qv().
59  // We also provide indexing operators [] on the array.
60  // Note:
61  // The real part qw is stored in the last component.
62 
63  //------------------------------------------------------
66  //------------------------------------------------------
67  struct {
68  DT qx;
69  DT qy;
70  DT qz;
71  DT qw;
72  };
73 
74  //------------------------------------------------------
81  //------------------------------------------------------
82  DT array[4];
83  };
85 
86 
87  //------------------------------------------------------
90  //------------------------------------------------------
92  inline TQuaternion() :
93  qx(0), qy(0), qz(0), qw(0) { }
94 
97  inline explicit TQuaternion(DT d) :
98  qx(0), qy(0), qz(0), qw(d)
99  {
100  }
101 
106  template <typename DT2>
107  inline explicit TQuaternion(const TQuaternion<DT2> &q2)
108  {
109  qx = static_cast<DT>(q2.qx);
110  qy = static_cast<DT>(q2.qy);
111  qz = static_cast<DT>(q2.qz);
112  qw = static_cast<DT>(q2.qw);
113  }
114 
116  TQuaternion(const TQuaternion &q2) = default;
117 
125  inline explicit TQuaternion(DT x, DT y, DT z, DT w)
126  {
127  qx = x;
128  qy = y;
129  qz = z;
130  qw = w;
131  }
132 
141  inline explicit TQuaternion(const FloatingPointVector<DT,4> &v)
142  {
143  qx = v[1];
144  qy = v[2];
145  qz = v[3];
146  qw = v[0];
147  }
148 
153  inline explicit TQuaternion(const FloatingPointVector<DT, 3, Vector3DataContainer<DT> > &v, DT w) :
154  qx(v[0]), qy(v[1]), qz(v[2]), qw(w)
155  {
156  }
157 
159 
160 
161  //-------------------------------------------------------------------------
164  //-------------------------------------------------------------------------
165 
169  {
170  return qv();
171  }
172 
174  inline DT getRealPart() const
175  {
176  return qw;
177  }
178 
187  {
188  return reinterpret_cast<const FloatingPointVector<DT, 3, Vector3DataContainer<DT> >&>(qx);
189  }
190 
196  {
197  return reinterpret_cast<FloatingPointVector<DT, 3, Vector3DataContainer<DT> >&>(qx);
198  }
199 
203  inline void set(const FloatingPointVector<DT, 3, Vector3DataContainer<DT> > &v, const DT w)
204  {
205  qx = v[0];
206  qy = v[1];
207  qz = v[2];
208  qw = w;
209  }
210 
213  inline void set(const DT x, const DT y, const DT z, const DT w)
214  {
215  qx = x;
216  qy = y;
217  qz = z;
218  qw = w;
219  }
220 
226  inline Tmat4<DT> getAsMat4(bool *isConvertible=nullptr) const
227  {
228  // Create return value.
229  Tmat4<DT> m;
230  // Check whether conversion is possible.
231  const DT n=norm();
232  if (0==n) {
233  if (!isConvertible){
234  printTemplateError("TQuaternion::getAsMat4() const, quaternion is not convertible to 4x4 matrix",
236  "Returning Quaterion");
237  }
238  else{
239  *isConvertible = false;
240  }
242  }
243  else{
244  // Conversion is possible.
245  const DT s = 2./n;
246  //s is a compressed factor
247  //it originates from the constant factor 2 and the normalization
248  //factor for the vector "1/sqrt(norm(vector))"
249  //To normalize the vector each component is divided by "1/sqrt(norm(vector))"
250  //So each vector component qx,qy,qz has to get its own factor to normalize
251  //the vector while calculating the matrix. However, as s is multiplied
252  //always to a pair of 2 multiplied vector components, the factor can be
253  //pulled in front of the addition (c.f. m11). As pairs of vector components
254  //are added, the sqrt vanishes and what is left is the factor 2./norm(vector)
255  //where norm is what is defined as "norm()" inside the mlQuaternion.h.
256 
257  // q0 = qw, first column.
258  const DT qxqx = qx*qx;
259  const DT qyqy = qy*qy;
260  const DT qzqz = qz*qz;
261 
262  const DT qxqy = qx*qy;
263  const DT qxqz = qx*qz;
264  const DT qxqw = qx*qw;
265 
266  const DT qyqz = qy*qz;
267  const DT qyqw = qy*qw;
268 
269  const DT qzqw = qz*qw;
270 
271  const DT m11 = 1 - s * (qyqy + qzqz);
272  const DT m12 = s * (qxqy - qzqw);
273  const DT m13 = s * (qxqz + qyqw);
274 
275  const DT m21 = s * (qxqy + qzqw);
276  const DT m22 = 1 - s * (qxqx + qzqz);
277  const DT m23 = s * (qyqz - qxqw);
278 
279  const DT m31 = s * (qxqz - qyqw);
280  const DT m32 = s * (qyqz + qxqw);
281  const DT m33 = 1 - s * (qxqx + qyqy);
282 
283  // Construct matrix from precomputed values
284  m.set(0);
285  m[0][0] = m11;
286  m[0][1] = m12;
287  m[0][2] = m13;
288  m[0][3] = 0.0;
289 
290  m[1][0] = m21;
291  m[1][1] = m22;
292  m[1][2] = m23;
293  m[1][3] = 0.0;
294 
295  m[2][0] = m31;
296  m[2][1] = m32;
297  m[2][2] = m33;
298  m[2][3] = 0.0;
299 
300  m[3][0] = 0.0;
301  m[3][1] = 0.0;
302  m[3][2] = 0.0;
303  m[3][3] = 1.0;
304 
305  if (isConvertible){ *isConvertible = true; }
306 
307  } // else
308  return m;
309  }
310 
312 
313 
314  //-------------------------------------------------------------------------
317  //-------------------------------------------------------------------------
318 
322  inline DT operator[](const size_t i) const { return array[i]; }
323 
327  inline DT &operator[](const size_t i) { return array[i]; }
328 
331  {
332  if (this != &q){
333  qx = q.qx;
334  qy = q.qy;
335  qz = q.qz;
336  qw = q.qw;
337  }
338  return *this;
339  }
341 
342 
343  //------------------------------------------------------
346  //------------------------------------------------------
347 
349  inline TQuaternion<DT> operator + (const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx+b.qx, qy+b.qy, qz+b.qz, qw+b.qw); }
351  inline TQuaternion<DT> &operator += (const TQuaternion<DT> &b) { qx+=b.qx; qy+=b.qy; qz+=b.qz; qw+=b.qw; return *this; }
352 
354  inline TQuaternion<DT> operator - (const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx-b.qx, qy-b.qy, qz-b.qz, qw-b.qw); }
356  inline TQuaternion<DT> &operator -= (const TQuaternion<DT> &b) { qx-=b.qx; qy-=b.qy; qz-=b.qz; qw-=b.qw; return *this; }
357 
359  inline TQuaternion<DT> operator * (const TQuaternion<DT> &b) const { return mult(b); }
361  inline TQuaternion<DT> &operator *= (const TQuaternion<DT> &b) { *this = mult(b); return *this; }
362 
365  {
366  TQuaternion<DT> retVal(*this);
367  ML_CHECK_FLOAT(d);
368  retVal /= d;
369  return retVal;
370  }
371 
374  {
375  ML_CHECK_FLOAT(d);
376  qx/=d; qy/=d; qz/=d; qw/=d;
377  return *this;
378  }
379 
380 
383  {
384  return TQuaternion<DT>(div(q));
385  }
386 
391  inline TQuaternion<DT> compDiv(const TQuaternion<DT> &b, bool *isError=nullptr) const
392  {
393  // Initialize return value with default quaternion.
394  TQuaternion<DT> retVal(0,0,0,1);
395  if (!isError){
396  // No error flag passed. Handle error if necessary.
397  ML_CHECK_FLOAT(b.qx);
398  ML_CHECK_FLOAT(b.qy);
399  ML_CHECK_FLOAT(b.qz);
400  ML_CHECK_FLOAT(b.qw);
401  retVal.set(qx/b.qx, qy/b.qy, qz/b.qz, qw/b.qw);
402  }
403  else{
404  // Error flag is available. Return *isError as true in case of error
405  *isError = (b.qx == 0) ||
406  (b.qy == 0) ||
407  (b.qz == 0) ||
408  (b.qw == 0);
409 
410  retVal = *isError ?
411  TQuaternion<DT>(b.qx != 0 ? qx/b.qx : qx,
412  b.qy != 0 ? qy/b.qy : qy,
413  b.qz != 0 ? qz/b.qz : qz,
414  b.qw != 0 ? qw/b.qw : qw) :
415  TQuaternion<DT>(qx/b.qx,
416  qy/b.qy,
417  qz/b.qz,
418  qw/b.qw);
419  }
420  return retVal;
421  }
422 
425  inline bool operator == (const TQuaternion<DT> &b) const { return MLValuesAreEqualWOM(qx, b.qx) &&
426  MLValuesAreEqualWOM(qy, b.qy) &&
427  MLValuesAreEqualWOM(qz, b.qz) &&
428  MLValuesAreEqualWOM(qw, b.qw); }
431  inline bool operator != (const TQuaternion<DT> &b) const { return !operator==(b); }
433 
434 
435 
437  inline DT dot(const TQuaternion<DT> &p) const { return qx*p.qx + qy*p.qy + qz*p.qz + qw*p.qw; }
438 
441  inline TQuaternion<DT> odd(const TQuaternion<DT> &p) const { return TQuaternion<DT>(qy*p.qz - qz*p.qy,
442  qz*p.qx - qx*p.qz,
443  qx*p.qy - qy*p.qx,
444  0); }
445 
448  inline TQuaternion<DT> even(const TQuaternion<DT> &p) const { return TQuaternion<DT>(qw*p.qx + qx*p.qw,
449  qw*p.qy + qy*p.qw,
450  qw*p.qz + qz*p.qw,
451  qw*p.qw - qx*p.qx - qy*p.qy - qz*p.qz); }
452 
454  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)); }
455 
457  inline TQuaternion<DT> euclideanMult(const TQuaternion<DT> &q) const { return conjugate().mult(q); }
458 
460  inline TQuaternion<DT> outer(const TQuaternion<DT> &q) const { return (euclideanMult(q) - q.euclideanMult(*this)) / 2; }
461 
462 
471  inline TQuaternion<DT> div(const TQuaternion<DT> &d, bool *isError=nullptr) const
472  {
473  // Initialize return value with default quaternion.
474  TQuaternion<DT> retVal(0,0,0,1);
475  if (d == TQuaternion<DT>(0,0,0,0)){
476  if (isError == nullptr){
477  // No error flag passed. Handle error if necessary.
478  printTemplateError("TQuaternion::div() const, quaternion is not divisible",
480  "Returning unchanged quaternion");
481  retVal.set(qx,qy,qz,qw);
482  }
483  else{
484  // Error flag pointer is available. Return *isError as true in case of error
485  *isError = true;
486  retVal.set(qx,qy,qz,qw);
487  }
488  }
489  else{
490  if (isError != nullptr){ *isError = false; }
491  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),
492  (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),
493  (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),
494  (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));
495  }
496  return retVal;
497  }
498 
499 
501  inline TQuaternion<DT> mult(DT s) const { return TQuaternion<DT>(qx*s, qy*s, qz*s, qw*s); }
502 
504  inline TQuaternion<DT> add(const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx+b.qx, qy+b.qy, qz+b.qz, qw+b.qw); }
505 
507  inline TQuaternion<DT> add(DT s) const { return TQuaternion<DT>(qx, qy, qz, qw+s); }
508 
510  inline TQuaternion<DT> conjugate() const { return TQuaternion<DT>(-qx, -qy, -qz, qw); }
511 
513  inline TQuaternion<DT> negate() const { return TQuaternion<DT>(-qx, -qy, -qz, -qw); }
514 
516  inline DT norm() const { return qx*qx + qy*qy + qz*qz + qw*qw; }
517 
518 
521  inline DT norm2() const { return static_cast<DT>(::sqrt(qx*qx + qy*qy + qz*qz + qw*qw)); }
522 
525  inline DT absoluteValue() const { return static_cast<DT>(::sqrt(norm())); }
526 
531  inline TQuaternion<DT> normalize(bool *isError=nullptr) const
532  {
533  // Initialize return value with default quaternion.
534  TQuaternion<DT> retVal(0,0,0,1);
535  const DT n=norm2();
536  if (MLValueIs0WOM(n)){
537  // Error! Check whether we have a pointer to a return error code value.
538  if (isError == nullptr){
539  // No, post an error.
540  printTemplateError("TQuaternion::normalize() const, quaternion can not be normalized",
542  "Returning default quaternion");
543  }
544  else{
545  // Yes, set return code.
546  *isError = true;
547  }
548  }
549  else{
550  // Non zero => no error.
551  if (isError){ *isError = false; }
552  retVal.set(qx/n, qy/n, qz/n, qw/n);
553  }
554  return retVal;
555  }
556 
563  inline TQuaternion<DT> arg(bool *isError=nullptr) const
564  {
565  // Initialize return value with default quaternion.
566  TQuaternion<DT> retVal(0,0,0,1);
567  // Norm2 must be non-zero to avoid divisions by zero.
568  const DT n=norm2();
569  if (MLValueIs0WOM(n)){
570  // Error! Check whether we have a pointer to a return error code value.
571  if (isError == nullptr){
572  // No, post an error.
573  printTemplateError("TQuaternion::arg() const, quaternion can not be normalized",
575  "Returning default quaternion");
576  }
577  else{
578  // Yes, set return code.
579  *isError = true;
580  }
581  }
582  else{
583  // Non zero => no error.
584  if (isError != nullptr){ *isError = false; }
585  retVal = acos(qw/n);
586  }
587  return retVal;
588  }
589 
594  inline TQuaternion<DT> sgn(bool *isError=nullptr) const
595  {
596  // Initialize return value with default quaternion.
597  TQuaternion<DT> retVal(0,0,0,1);
598  const DT absVal = absoluteValue();
599  if (isError != nullptr){
600  // Set error return value.
601  if (absVal==0){
602  *isError = true;
603  }
604  else{
605  // No error.
606  *isError = false;
607  retVal = *this / absVal;
608  }
609  }
610  else{
611  // Post error is absVal == 0.
612  ML_CHECK_FLOAT(absVal);
613  retVal = *this / absVal;
614  }
615  return retVal;
616  }
617 
623  inline TQuaternion<DT> inverse(bool* isInvertible=nullptr) const
624  {
625  // Initialize return value with default quaternion.
626  TQuaternion<DT> retVal(0,0,0,1);
627  const DT n=norm();
628  if (MLValueIs0WOM(n)) {
629  if (isInvertible==nullptr){
630  printTemplateError("TQuaternion::() const, quaternion is not invertable",
632  "Returning default quaternion");
633  }
634  else{
635  *isInvertible = false;
636  }
637  retVal = TQuaternion<DT>();
638  }
639  else{
640  if (isInvertible != nullptr){ *isInvertible = true; }
641  retVal = conjugate().mult(1/n);
642  }
643  return retVal;
644  }
645 
651  // return TQuaternion(::sqrt(norm2())*::sin(0.5*acos(qw/norm2()))*(1/qv().length())*Tvec3<DT>(qx,qy,qz),
652  inline TQuaternion<DT> sqrt(bool *isError=nullptr) const
653  {
654  // Initialize return value with default quaternion.
655  TQuaternion<DT> retVal(0,0,0,1);
656  // Precalculate constants and check for 0 division.
657  const DT n2 = norm2();
658  const DT lqv = qv().length();
659  if (MLValueIs0WOM(n2) || MLValueIs0WOM(lqv)){
660  // Error! Check whether we have a pointer to a return error code value.
661  if (isError == nullptr){
662  // No, post an error.
663  printTemplateError("TQuaternion::sqrt() const, sqrt of quaternion cannot be calculated",
665  "Returning default quaternion");
666  }
667  else{
668  // Yes, set return code.
669  *isError = true;
670  }
671  }
672  else{
673  // Calculate sqrt, lqv and n2 are non 0 here.
674  const DT sqrtSin = ::sqrt(n2)*::sin(0.5*acos(qw/n2));
675  const DT sqrtSinF = sqrtSin*(1/lqv);
676  retVal.set(sqrtSinF*qx, sqrtSinF*qy, sqrtSinF*qz, ::sqrt(n2) * ::cos(0.5*acos(qw/n2)));
677 
678  // Non zero => no error.
679  if (isError != nullptr){ *isError = false; }
680  }
681  return retVal;
682  }
683 
684 
689 
691  inline TQuaternion<DT> exp() const
692  {
693  // Initialize return value with default quaternion.
694  TQuaternion<DT> retVal(0,0,0,1);
695  const DT len = qv().length();
696  if (MLValueIs0WOM(len)){
697  retVal = TQuaternion<DT>(0,0,0,::cos(len)).mult(::exp(qw));
698  }
699  else{
700  retVal = TQuaternion<DT>((qv()/len) * static_cast<DT>(::sin(len)), ::cos(len)).mult(::exp(qw));
701  }
702  return retVal;
703  }
704 
705 
707  inline TQuaternion<DT> ln() const
708  {
709  // Initialize return value with default quaternion.
710  TQuaternion<DT> retVal(0,0,0,1);
711  const DT n2 = norm2();
712  const DT qvLen = qv().length();
713  if (MLValueIs0WOM(qvLen)){
714  retVal.set(0, 0, 0, log10(n2));
715  }
716  else{
717  // n2 is always non 0 if qvLen is non-zero, thus no check is necessary.
718  retVal.set(qv()/qvLen * static_cast<DT>(acos(qw/n2)), log10(n2));
719  }
720  return retVal;
721  }
722 
723 
725  inline TQuaternion<DT> pow(const TQuaternion<DT> &quat) const {return ln().mult(quat).exp(); }
726 
727 
732 
735  {
736  TQuaternion<DT> retVal;
737  const Tvec3<DT> &v = qv();
738  const DT len = v.length();
739  // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
740  // Then the quaternion method behaves like the normal function on real values.
741  retVal.set((!MLValueIs0WOM(len) ?
742  static_cast<DT>(::cos(qw)) * v / len * static_cast<DT>(::sinh(len)) :
743  Tvec3<DT>(0.0)),
744  ::sin(qw)*::cosh(len)
745  );
746  return retVal;
747  }
748 
751  {
752  TQuaternion<DT> retVal;
753  const Tvec3<DT> &v = qv();
754  const DT len = v.length();
755  // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
756  // Then the quaternion method behaves like the normal function on real values.
757  retVal.set((!MLValueIs0WOM(len) ?
758  static_cast<DT>(-1)*static_cast<DT>(::sin(qw))*qv()/len*static_cast<DT>(::sinh(len)) :
759  Tvec3<DT>(0.0)),
760  ::cos(qw)*::cosh(len)
761  );
762  return retVal;
763  }
764 
766  inline TQuaternion<DT> tan(bool *isError=nullptr) const { return sin().div(cos(), isError); }
767 
769  inline TQuaternion<DT> cotan(bool *isError=nullptr) const { return cos().div(sin(), isError); }
770 
771 
772 
777 
780  {
781  TQuaternion<DT> retVal;
782  const Tvec3<DT> &v = qv();
783  const DT len = v.length();
784  // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
785  // Then the quaternion method behaves like the normal function on real values.
786  retVal.set((!MLValueIs0WOM(len) ?
787  static_cast<DT>(::cosh(qw))*v/len*static_cast<DT>(::sin(len)) :
788  Tvec3<DT>(0.0)),
789  ::sinh(qw)*::cos(len)
790  );
791  return retVal;
792  }
793 
796  {
797  TQuaternion<DT> retVal;
798  const Tvec3<DT> &v = qv();
799  const DT len = v.length();
800  // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
801  // Then the quaternion method behaves like the normal function on real values.
802  retVal.set((!MLValueIs0WOM(len) ?
803  static_cast<DT>(::sinh(qw))*v/len*static_cast<DT>(::sin(len)) :
804  Tvec3<DT>(0.0)),
805  ::cosh(qw)*::cos(len)
806  );
807  return retVal;
808  }
809 
811  inline TQuaternion<DT> tanh(bool *isError=nullptr) const
812  {
813  return sinh().div(cosh(), isError);
814  }
815 
817  inline TQuaternion<DT> cotanh(bool *isError=nullptr) const
818  {
819  return cosh().div(sinh(), isError);
820  }
821 
822 
823 
828 
830  inline TQuaternion<DT> arcsinh() const { return add(mult(*this).add(TQuaternion<DT>( 1)).sqrt()).ln(); }
831 
833  inline TQuaternion<DT> arccosh() const { return add(mult(*this).add(TQuaternion<DT>(-1)).sqrt()).ln(); }
834 
836  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); }
837 
838 
848  #define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR) \
849  TQuaternion<DT> retVal; \
850  { \
851  const Tvec3<DT> &v = qv(); \
852  const DT len = v.length(); \
853  if (MLValueIs0WOM(len)){ \
854  /* Error! Check whether we have a pointer to a return error code value. */ \
855  if (isError == NULL){ \
856  /* No, post an error. */ \
857  printTemplateError("TQuaternion::" FUNC_NAME "() const, " FUNC_NAME \
858  " of quaternion cannot be calculated", \
859  ML_BAD_PARAMETER, \
860  "Returning default quaternion"); \
861  } \
862  else{ \
863  /* Yes, set return code, retVal is left on default. */ \
864  *isError = true; \
865  } \
866  } \
867  else{ \
868  /* Define return values. */ \
869  if (isError != NULL){ *isError = false; } \
870  retVal = CALC_EXPR; \
871  } \
872  } \
873  return retVal; \
874 
875 
876 
878  #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arcsinh());
883 
885  TQuaternion<DT> arcsin(bool *isError=nullptr) const
886  {
888  }
889  #undef _ML_QUAT_CALC_EXP
890 
891 
892 
894  #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(arccosh());
896  TQuaternion<DT> arccos(bool *isError=nullptr) const
897  {
899  }
900  #undef _ML_QUAT_CALC_EXP
901 
902 
903 
905  #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arctanh());
907  TQuaternion<DT> arctan(bool *isError=nullptr) const
908  {
910  }
911  #undef _ML_QUAT_CALC_EXP
912 
913 
914  // Undefines _ML_QUATERNION_CALC_CHECKED, it is not needed any more.
915  #undef _ML_QUATERNION_CALC_CHECKED
916 };
917 
918 
919 //-----------------------------------------------------------------------------------
922 //-----------------------------------------------------------------------------------
925 
928 
931 
935 
936 
937 ML_LA_END_NAMESPACE
938 
939 
940 
941 
942 //-------------------------------------------------------------------------
949 //-------------------------------------------------------------------------
950 #ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
951 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
952 ML_LA_START_NAMESPACE
953 #endif
954 
955 //-----------------------------
956 // Addition
957 //-----------------------------
959 template <typename DT>
960 inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
961  return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
962 }
963 
965 template <typename DT>
966 inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
967  return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
968 }
969 
971 template <typename DT>
972 inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
973  const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
974  return qa.operator+(qb);
975 }
976 
977 
978 
979 //-----------------------------
980 // Subtraction
981 //-----------------------------
983 template <typename DT>
984 inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
985  return ML_LA_NAMESPACE::TQuaternion<DT>(-q.qx, -q.qy, -q.qz, d-q.qw);
986 }
987 
989 template <typename DT>
990 inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
991  return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw-d);
992 }
993 
995 template <typename DT>
996 inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
997  const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
998  return qa.operator-(qb);
999 }
1000 
1001 
1003 template <typename DT>
1004 inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
1005  return q.mult(d);
1006 }
1007 
1009 template <typename DT>
1010 inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
1011  return q.mult(d);
1012 }
1013 
1015 template <typename DT>
1016 inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
1017  const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
1018  return qa.operator*(qb);
1019 }
1021 
1022 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1023 ML_LA_END_NAMESPACE
1024 #endif
1025 
1026 #endif // _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
1027 
1028 
1029 
1030 //-------------------------------------------------------------------------
1037 //-------------------------------------------------------------------------
1038 #ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1039 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1040 ML_LA_START_NAMESPACE
1041 #endif
1042 
1045 #ifdef _ML_IMPLEMENT_QUATERNION_SQRT
1046 template <typename DT>
1047 inline ML_LA_NAMESPACE::TQuaternion<DT> sqrt (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sqrt(); }
1048 #endif
1049 
1051 template <typename DT>
1052 inline ML_LA_NAMESPACE::TQuaternion<DT> exp (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.exp(); }
1053 
1055 template <typename DT>
1056 inline ML_LA_NAMESPACE::TQuaternion<DT> ln (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.ln(); }
1057 
1059 template <typename DT>
1060 inline ML_LA_NAMESPACE::TQuaternion<DT> sin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sin(); }
1061 
1063 template <typename DT>
1064 inline ML_LA_NAMESPACE::TQuaternion<DT> cos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cos(); }
1065 
1067 template <typename DT>
1068 inline ML_LA_NAMESPACE::TQuaternion<DT> tan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tan(); }
1069 
1071 template <typename DT>
1072 inline ML_LA_NAMESPACE::TQuaternion<DT> cotan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotan(); }
1073 
1075 template <typename DT>
1076 inline ML_LA_NAMESPACE::TQuaternion<DT> sinh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sinh(); }
1077 
1079 template <typename DT>
1080 inline ML_LA_NAMESPACE::TQuaternion<DT> cosh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cosh(); }
1081 
1083 template <typename DT>
1084 inline ML_LA_NAMESPACE::TQuaternion<DT> tanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tanh(); }
1085 
1087 template <typename DT>
1088 inline ML_LA_NAMESPACE::TQuaternion<DT> cotanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotanh(); }
1089 
1091 template <typename DT>
1092 inline ML_LA_NAMESPACE::TQuaternion<DT> arcsinh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsinh(); }
1093 
1095 template <typename DT>
1096 inline ML_LA_NAMESPACE::TQuaternion<DT> arccosh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccosh(); }
1097 
1099 template <typename DT>
1100 inline ML_LA_NAMESPACE::TQuaternion<DT> arctanh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctanh(); }
1101 
1103 template <typename DT>
1104 inline ML_LA_NAMESPACE::TQuaternion<DT> arcsin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsin(); }
1105 
1107 template <typename DT>
1108 inline ML_LA_NAMESPACE::TQuaternion<DT> arccos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccos(); }
1109 
1111 template <typename DT>
1112 inline ML_LA_NAMESPACE::TQuaternion<DT> arctan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctan(); }
1113 
1114 
1115 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1116 ML_LA_END_NAMESPACE
1117 #endif
1118 
1119 #endif // _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1121 
1122 
1123 //-----------------------------------------------------------------------------------
1124 // Stream output for std::ostream and dyadic multiplication of TQuaternion and scalar.
1125 //-----------------------------------------------------------------------------------
1126 namespace std {
1127 
1129  template <typename DT>
1130  inline ostream& operator<<(ostream& s, const ML_NAMESPACE::TQuaternion<DT> &v){
1131  return s << "(" << v.qx << "," << v.qy << "," << v.qz << "," << v.qw << ")";
1132  }
1133 
1134 }
1135 
1136 
1137 #endif // __mlQuaternion_H
FloatingPointVector< T, 3, DataContainer > cross(const FloatingPointVector< T, 3, DataContainer > &b) const
Returns the cross product for elements, i.e., return vector vertical 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:42
TQuaternion(DT d)
Builds a quaternion from a scalar by setting all elements to 0 and qw to the scalar; use explicit to ...
Definition: mlQuaternion.h:97
DT dot(const TQuaternion< DT > &p) const
Dot product, equivalent to 4 component vector dot product.
Definition: mlQuaternion.h:437
TQuaternion< DT > add(const TQuaternion< DT > &b) const
Adds another quaternion to this one and returns the sum.
Definition: mlQuaternion.h:504
DT & operator[](const size_t i)
Indexing operator.
Definition: mlQuaternion.h:327
TQuaternion(DT x, DT y, DT z, DT w)
Creates a new TQuaternion with the DT values given.
Definition: mlQuaternion.h:125
DT qx
First element of imaginary part.
Definition: mlQuaternion.h:68
TQuaternion< DT > exp() const
Exponential and logarithmic functions: natural exponential, natural logarithm, power.
Definition: mlQuaternion.h:691
TQuaternion< DT > normalize(bool *isError=nullptr) const
Returns the normalization of the quaternion.
Definition: mlQuaternion.h:531
DT absoluteValue() const
Returns the absolute value of a quaternion which is the scalar quantity that determines the length of...
Definition: mlQuaternion.h:525
TQuaternion< DT > cotanh(bool *isError=nullptr) const
Computes the hyperbolic cotangent, for error handling see _ML_QUATERNION_CALC_CHECKED....
Definition: mlQuaternion.h:817
TQuaternion< DT > inverse(bool *isInvertible=nullptr) const
Computes and returns the inverse.
Definition: mlQuaternion.h:623
TQuaternion< DT > arctanh() const
Computes the inverse hyperbolic tangent.
Definition: mlQuaternion.h:836
TQuaternion< DT > div(const TQuaternion< DT > &d, bool *isError=nullptr) const
Divides a quaternion by another quaternion.
Definition: mlQuaternion.h:471
TQuaternion< DT > compDiv(const TQuaternion< DT > &b, bool *isError=nullptr) const
Divides each component by its corresponding component from b; the caller must guarantee that b does n...
Definition: mlQuaternion.h:391
TQuaternion< DT > sqrt(bool *isError=nullptr) const
Computes the square root of a quaternion.
Definition: mlQuaternion.h:652
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:203
TQuaternion< DT > sinh() const
Hyperbolic functions: Hyperbolic sine, hyperbolic cosine, hyperbolic tangent Source: http://www....
Definition: mlQuaternion.h:779
TQuaternion< DT > tanh(bool *isError=nullptr) const
Computes the hyperbolic tangent, for error handling see _ML_QUATERNION_CALC_CHECKED....
Definition: mlQuaternion.h:811
TQuaternion< DT > cosh() const
Computes the hyperbolic cosine.
Definition: mlQuaternion.h:795
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv()
Returns a modifiable reference to the quaternion's imaginary part as vector object,...
Definition: mlQuaternion.h:195
TQuaternion< DT > conjugate() const
Computes the conjugate.
Definition: mlQuaternion.h:510
TQuaternion< DT > even(const TQuaternion< DT > &p) const
Even product, also known as Grassman inner product.
Definition: mlQuaternion.h:448
TQuaternion< DT > negate() const
Computes the negation.
Definition: mlQuaternion.h:513
TQuaternion< DT > euclideanMult(const TQuaternion< DT > &q) const
Euclidean product of this quaternion with another one (which is non-commutative).
Definition: mlQuaternion.h:457
TQuaternion< DT > arg(bool *isError=nullptr) const
Computes the quaternion argument.
Definition: mlQuaternion.h:563
TQuaternion< DT > arcsin(bool *isError=nullptr) const
Inverse trigonometric functions: Inverse sine, inverse cosine, inverse tangent.
Definition: mlQuaternion.h:885
DT norm() const
Computes the d norm.
Definition: mlQuaternion.h:516
TQuaternion< DT > mult(DT s) const
Multiplies this quaternion with a scalar factor.
Definition: mlQuaternion.h:501
TQuaternion()
Standard constructor, setting all elements to 0.
Definition: mlQuaternion.h:92
TQuaternion< DT > cos() const
Computes the cosine.
Definition: mlQuaternion.h:750
DT qw
Real part.
Definition: mlQuaternion.h:71
TQuaternion< DT > odd(const TQuaternion< DT > &p) const
Odd product, also known as cross-product or Grassman outer product.
Definition: mlQuaternion.h:441
DT value_type
Scalar type used for qx, qy, qz, and qw.
Definition: mlQuaternion.h:47
TQuaternion< DT > cotan(bool *isError=nullptr) const
Computes the cotangent, for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:769
TQuaternion< DT > tan(bool *isError=nullptr) const
Computes the tangent, for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:766
TQuaternion< DT > sin() const
Trigonometric functions: sine, cosine, tangent, cotangent.
Definition: mlQuaternion.h:734
TQuaternion< DT > outer(const TQuaternion< DT > &q) const
Euclidean outer product of this quaternion with another one.
Definition: mlQuaternion.h:460
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:213
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:454
DT norm2() const
Computes the magnitude of the quaternion.
Definition: mlQuaternion.h:521
TQuaternion(const TQuaternion< DT2 > &q2)
Copy constructor from another TQuaternion of same or other type.
Definition: mlQuaternion.h:107
TQuaternion< DT > arcsinh() const
Inverse hyperbolic function: arcsinh, arccosh, arctanh.
Definition: mlQuaternion.h:830
TQuaternion< DT > ln() const
Computes the natural logarithm.
Definition: mlQuaternion.h:707
TQuaternion< DT > arctan(bool *isError=nullptr) const
Inverse tangent, for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:907
const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv() const
Returns a constant reference to the quaternion's imaginary part as vector object.
Definition: mlQuaternion.h:186
DT qz
Third element of imaginary part.
Definition: mlQuaternion.h:70
Tmat4< DT > getAsMat4(bool *isConvertible=nullptr) const
Converts this quaternion to a 4x4 matrix.
Definition: mlQuaternion.h:226
TQuaternion(const FloatingPointVector< DT, 4 > &v)
Creates a new TQuaternion from the four-dimensional parameter vector.
Definition: mlQuaternion.h:141
TQuaternion< DT > pow(const TQuaternion< DT > &quat) const
Computes the power of a quaternion.
Definition: mlQuaternion.h:725
DT operator[](const size_t i) const
Constant indexing operator.
Definition: mlQuaternion.h:322
TQuaternion< DT > & operator=(const TQuaternion< DT > &q)
Assignment operator.
Definition: mlQuaternion.h:330
TQuaternion< DT > arccos(bool *isError=nullptr) const
Inverse cosine, for error handling see _ML_QUATERNION_CALC_CHECKED.
Definition: mlQuaternion.h:896
TQuaternion(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, DT w)
Constructor with a vector and DT parameter.
Definition: mlQuaternion.h:153
TQuaternion< DT > sgn(bool *isError=nullptr) const
Returns the sign of the quaternion.
Definition: mlQuaternion.h:594
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 to the quaternion and returns the sum, it is equivalent to a scalar add of s to the qw ...
Definition: mlQuaternion.h:507
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > getImaginaryPart() const
Returns a copy of the quaternion's imaginary part.
Definition: mlQuaternion.h:168
TQuaternion< DT > arccosh() const
Computes the inverse hyperbolic cosine.
Definition: mlQuaternion.h:833
DT getRealPart() const
Returns a copy of the quaternion's real part, also called scalar() of a quaternion.
Definition: mlQuaternion.h:174
DT qy
Second element of imaginary part.
Definition: mlQuaternion.h:69
A four by four matrix class consisting of 4 row vectors.
Definition: mlMatrix4.h:36
void set(const DT val)
Sets all values to double val.
Definition: mlMatrix4.h:277
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 false.
bool MLValuesAreEqualWOM(MLint8 a, MLint8 b)
Returns true if values a and b are equal, otherwise 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:925
#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:905
#define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR)
Defines a code fragment which checks and handles some stuff for safe expression calculations.
Definition: mlQuaternion.h:848
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
Define the default Quaternion type which is used by the ML; it uses double as component type.
Definition: mlQuaternion.h:933
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 specialization from TQuaternion.
Definition: mlQuaternion.h:924
bool operator==(const Tmat2< DT > &a, const Tmat2< DT > &b)
a == b ? Return 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 ? Return true if yes.
Definition: mlMatrix2.h:433
TQuaternion< MLldouble > Quaternionld
A large Quaternion type for further extensions of the ML as specialization from TQuaternion.
Definition: mlQuaternion.h:930
TQuaternion< MLdouble > Quaterniond
The default Quaternion type used in the ML as specialization from TQuaternion.
Definition: mlQuaternion.h:927
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.