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.
24
25// 3D double vector.
26#include "mlVector3.h"
27#include <mlErrorMacros.h>
28#include <mlErrorOutput.h>
30
31ML_LA_START_NAMESPACE
32
33//--------------------------------------------------------
37//--------------------------------------------------------
38template <typename DT>
40{
41
42public:
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
113 TQuaternion(const TQuaternion& q2) = default;
114
122 inline explicit TQuaternion(DT x, DT y, DT z, DT w)
123 {
124 qx = x;
125 qy = y;
126 qz = z;
127 qw = w;
128 }
129
138 inline explicit TQuaternion(const FloatingPointVector<DT,4> &v)
139 {
140 qx = v[1];
141 qy = v[2];
142 qz = v[3];
143 qw = v[0];
144 }
145
150 inline explicit TQuaternion(const FloatingPointVector<DT, 3, Vector3DataContainer<DT> > &v, DT w) :
151 qx(v[0]), qy(v[1]), qz(v[2]), qw(w)
152 {
153 }
154
156
157
158 //-------------------------------------------------------------------------
161 //-------------------------------------------------------------------------
162
166 {
167 return qv();
168 }
169
171 inline DT getRealPart() const
172 {
173 return qw;
174 }
175
184 {
185 return reinterpret_cast<const FloatingPointVector<DT, 3, Vector3DataContainer<DT> >&>(qx);
186 }
187
196
200 inline void set(const FloatingPointVector<DT, 3, Vector3DataContainer<DT> > &v, const DT w)
201 {
202 qx = v[0];
203 qy = v[1];
204 qz = v[2];
205 qw = w;
206 }
207
210 inline void set(const DT x, const DT y, const DT z, const DT w)
211 {
212 qx = x;
213 qy = y;
214 qz = z;
215 qw = w;
216 }
217
223 inline Tmat4<DT> getAsMat4(bool *isConvertible=nullptr) const
224 {
225 // Create return value.
226 Tmat4<DT> m;
227 // Check whether conversion is possible.
228 const DT n=norm();
229 if (0==n) {
230 if (!isConvertible){
231 printTemplateError("TQuaternion::getAsMat4() const, quaternion is not convertible to 4x4 matrix",
233 "Returning Quaterion");
234 }
235 else{
236 *isConvertible = false;
237 }
239 }
240 else{
241 // Conversion is possible.
242 const DT s = 2./n;
243 //s is a compressed factor
244 //it originates from the constant factor 2 and the normalization
245 //factor for the vector "1/sqrt(norm(vector))"
246 //To normalize the vector each component is divided by "1/sqrt(norm(vector))"
247 //So each vector component qx,qy,qz has to get its own factor to normalize
248 //the vector while calculating the matrix. However, as s is multiplied
249 //always to a pair of 2 multiplied vector components, the factor can be
250 //pulled in front of the addition (c.f. m11). As pairs of vector components
251 //are added, the sqrt vanishes and what is left is the factor 2./norm(vector)
252 //where norm is what is defined as "norm()" inside the mlQuaternion.h.
253
254 // q0 = qw, first column.
255 const DT qxqx = qx*qx;
256 const DT qyqy = qy*qy;
257 const DT qzqz = qz*qz;
258
259 const DT qxqy = qx*qy;
260 const DT qxqz = qx*qz;
261 const DT qxqw = qx*qw;
262
263 const DT qyqz = qy*qz;
264 const DT qyqw = qy*qw;
265
266 const DT qzqw = qz*qw;
267
268 const DT m11 = 1 - s * (qyqy + qzqz);
269 const DT m12 = s * (qxqy - qzqw);
270 const DT m13 = s * (qxqz + qyqw);
271
272 const DT m21 = s * (qxqy + qzqw);
273 const DT m22 = 1 - s * (qxqx + qzqz);
274 const DT m23 = s * (qyqz - qxqw);
275
276 const DT m31 = s * (qxqz - qyqw);
277 const DT m32 = s * (qyqz + qxqw);
278 const DT m33 = 1 - s * (qxqx + qyqy);
279
280 // Construct matrix from precomputed values
281 m.set(0);
282 m[0][0] = m11;
283 m[0][1] = m12;
284 m[0][2] = m13;
285 m[0][3] = 0.0;
286
287 m[1][0] = m21;
288 m[1][1] = m22;
289 m[1][2] = m23;
290 m[1][3] = 0.0;
291
292 m[2][0] = m31;
293 m[2][1] = m32;
294 m[2][2] = m33;
295 m[2][3] = 0.0;
296
297 m[3][0] = 0.0;
298 m[3][1] = 0.0;
299 m[3][2] = 0.0;
300 m[3][3] = 1.0;
301
302 if (isConvertible){ *isConvertible = true; }
303
304 } // else
305 return m;
306 }
307
309
310
311 //-------------------------------------------------------------------------
314 //-------------------------------------------------------------------------
315
319 inline DT operator[](const size_t i) const { return array[i]; }
320
324 inline DT &operator[](const size_t i) { return array[i]; }
325
328 {
329 if (this != &q){
330 qx = q.qx;
331 qy = q.qy;
332 qz = q.qz;
333 qw = q.qw;
334 }
335 return *this;
336 }
338
339
340 //------------------------------------------------------
343 //------------------------------------------------------
344
346 inline TQuaternion<DT> operator + (const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx+b.qx, qy+b.qy, qz+b.qz, qw+b.qw); }
348 inline TQuaternion<DT> &operator += (const TQuaternion<DT> &b) { qx+=b.qx; qy+=b.qy; qz+=b.qz; qw+=b.qw; return *this; }
349
351 inline TQuaternion<DT> operator - (const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx-b.qx, qy-b.qy, qz-b.qz, qw-b.qw); }
353 inline TQuaternion<DT> &operator -= (const TQuaternion<DT> &b) { qx-=b.qx; qy-=b.qy; qz-=b.qz; qw-=b.qw; return *this; }
354
356 inline TQuaternion<DT> operator * (const TQuaternion<DT> &b) const { return mult(b); }
358 inline TQuaternion<DT> &operator *= (const TQuaternion<DT> &b) { *this = mult(b); return *this; }
359
361 inline TQuaternion<DT> operator / (DT d) const
362 {
363 TQuaternion<DT> retVal(*this);
365 retVal /= d;
366 return retVal;
367 }
368
370 inline TQuaternion<DT> &operator /= (DT d)
371 {
373 qx/=d; qy/=d; qz/=d; qw/=d;
374 return *this;
375 }
376
377
379 inline TQuaternion<DT> operator / (const TQuaternion<DT> &q) const
380 {
381 return TQuaternion<DT>(div(q));
382 }
383
388 inline TQuaternion<DT> compDiv(const TQuaternion<DT> &b, bool *isError=nullptr) const
389 {
390 // Initialize return value with default quaternion.
391 TQuaternion<DT> retVal(0,0,0,1);
392 if (!isError){
393 // No error flag passed. Handle error if necessary.
398 retVal.set(qx/b.qx, qy/b.qy, qz/b.qz, qw/b.qw);
399 }
400 else{
401 // Error flag is available. Return *isError as true in case of error
402 *isError = (b.qx == 0) ||
403 (b.qy == 0) ||
404 (b.qz == 0) ||
405 (b.qw == 0);
406
407 retVal = *isError ?
408 TQuaternion<DT>(b.qx != 0 ? qx/b.qx : qx,
409 b.qy != 0 ? qy/b.qy : qy,
410 b.qz != 0 ? qz/b.qz : qz,
411 b.qw != 0 ? qw/b.qw : qw) :
412 TQuaternion<DT>(qx/b.qx,
413 qy/b.qy,
414 qz/b.qz,
415 qw/b.qw);
416 }
417 return retVal;
418 }
419
422 inline bool operator == (const TQuaternion<DT> &b) const { return MLValuesAreEqualWOM(qx, b.qx) &&
423 MLValuesAreEqualWOM(qy, b.qy) &&
424 MLValuesAreEqualWOM(qz, b.qz) &&
425 MLValuesAreEqualWOM(qw, b.qw); }
428 inline bool operator != (const TQuaternion<DT> &b) const { return !operator==(b); }
430
431
432
434 inline DT dot(const TQuaternion<DT> &p) const { return qx*p.qx + qy*p.qy + qz*p.qz + qw*p.qw; }
435
438 inline TQuaternion<DT> odd(const TQuaternion<DT> &p) const { return TQuaternion<DT>(qy*p.qz - qz*p.qy,
439 qz*p.qx - qx*p.qz,
440 qx*p.qy - qy*p.qx,
441 0); }
442
445 inline TQuaternion<DT> even(const TQuaternion<DT> &p) const { return TQuaternion<DT>(qw*p.qx + qx*p.qw,
446 qw*p.qy + qy*p.qw,
447 qw*p.qz + qz*p.qw,
448 qw*p.qw - qx*p.qx - qy*p.qy - qz*p.qz); }
449
451 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)); }
452
454 inline TQuaternion<DT> euclideanMult(const TQuaternion<DT> &q) const { return conjugate().mult(q); }
455
457 inline TQuaternion<DT> outer(const TQuaternion<DT> &q) const { return (euclideanMult(q) - q.euclideanMult(*this)) / 2; }
458
459
468 inline TQuaternion<DT> div(const TQuaternion<DT> &d, bool *isError=nullptr) const
469 {
470 // Initialize return value with default quaternion.
471 TQuaternion<DT> retVal(0,0,0,1);
472 if (d == TQuaternion<DT>(0,0,0,0)){
473 if (isError == nullptr){
474 // No error flag passed. Handle error if necessary.
475 printTemplateError("TQuaternion::div() const, quaternion is not divisible",
477 "Returning unchanged quaternion");
478 retVal.set(qx,qy,qz,qw);
479 }
480 else{
481 // Error flag pointer is available. Return *isError as true in case of error
482 *isError = true;
483 retVal.set(qx,qy,qz,qw);
484 }
485 }
486 else{
487 if (isError != nullptr){ *isError = false; }
488 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),
489 (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),
490 (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),
491 (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));
492 }
493 return retVal;
494 }
495
496
498 inline TQuaternion<DT> mult(DT s) const { return TQuaternion<DT>(qx*s, qy*s, qz*s, qw*s); }
499
501 inline TQuaternion<DT> add(const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx+b.qx, qy+b.qy, qz+b.qz, qw+b.qw); }
502
504 inline TQuaternion<DT> add(DT s) const { return TQuaternion<DT>(qx, qy, qz, qw+s); }
505
507 inline TQuaternion<DT> conjugate() const { return TQuaternion<DT>(-qx, -qy, -qz, qw); }
508
510 inline TQuaternion<DT> negate() const { return TQuaternion<DT>(-qx, -qy, -qz, -qw); }
511
513 inline DT norm() const { return qx*qx + qy*qy + qz*qz + qw*qw; }
514
515
518 inline DT norm2() const { return static_cast<DT>(::sqrt(qx*qx + qy*qy + qz*qz + qw*qw)); }
519
522 inline DT absoluteValue() const { return static_cast<DT>(::sqrt(norm())); }
523
528 inline TQuaternion<DT> normalize(bool *isError=nullptr) const
529 {
530 // Initialize return value with default quaternion.
531 TQuaternion<DT> retVal(0,0,0,1);
532 const DT n=norm2();
533 if (MLValueIs0WOM(n)){
534 // Error! Check whether we have a pointer to a return error code value.
535 if (isError == nullptr){
536 // No, post an error.
537 printTemplateError("TQuaternion::normalize() const, quaternion cannot be normalized",
539 "Returning default quaternion");
540 }
541 else{
542 // Yes, set return code.
543 *isError = true;
544 }
545 }
546 else{
547 // Non zero => no error.
548 if (isError){ *isError = false; }
549 retVal.set(qx/n, qy/n, qz/n, qw/n);
550 }
551 return retVal;
552 }
553
560 inline TQuaternion<DT> arg(bool *isError=nullptr) const
561 {
562 // Initialize return value with default quaternion.
563 TQuaternion<DT> retVal(0,0,0,1);
564 // Norm2 must be non-zero to avoid divisions by zero.
565 const DT n=norm2();
566 if (MLValueIs0WOM(n)){
567 // Error! Check whether we have a pointer to a return error code value.
568 if (isError == nullptr){
569 // No, post an error.
570 printTemplateError("TQuaternion::arg() const, quaternion cannot be normalized",
572 "Returning default quaternion");
573 }
574 else{
575 // Yes, set return code.
576 *isError = true;
577 }
578 }
579 else{
580 // Non zero => no error.
581 if (isError != nullptr){ *isError = false; }
582 retVal = acos(qw/n);
583 }
584 return retVal;
585 }
586
591 inline TQuaternion<DT> sgn(bool *isError=nullptr) const
592 {
593 // Initialize return value with default quaternion.
594 TQuaternion<DT> retVal(0,0,0,1);
595 const DT absVal = absoluteValue();
596 if (isError != nullptr){
597 // Set error return value.
598 if (absVal==0){
599 *isError = true;
600 }
601 else{
602 // No error.
603 *isError = false;
604 retVal = *this / absVal;
605 }
606 }
607 else{
608 // Post error is absVal == 0.
609 ML_CHECK_FLOAT(absVal);
610 retVal = *this / absVal;
611 }
612 return retVal;
613 }
614
620 inline TQuaternion<DT> inverse(bool* isInvertible=nullptr) const
621 {
622 // Initialize return value with default quaternion.
623 TQuaternion<DT> retVal(0,0,0,1);
624 const DT n=norm();
625 if (MLValueIs0WOM(n)) {
626 if (isInvertible==nullptr){
627 printTemplateError("TQuaternion::() const, quaternion is not invertable",
629 "Returning default quaternion");
630 }
631 else{
632 *isInvertible = false;
633 }
634 retVal = TQuaternion<DT>();
635 }
636 else{
637 if (isInvertible != nullptr){ *isInvertible = true; }
638 retVal = conjugate().mult(1/n);
639 }
640 return retVal;
641 }
642
647 // return TQuaternion(::sqrt(norm2())*::sin(0.5*acos(qw/norm2()))*(1/qv().length())*Tvec3<DT>(qx,qy,qz),
648 inline TQuaternion<DT> sqrt(bool *isError=nullptr) const
649 {
650 // Initialize return value with default quaternion.
651 TQuaternion<DT> retVal(0,0,0,1);
652 // Precalculate constants and check for 0 division.
653 const DT n2 = norm2();
654 const DT lqv = qv().length();
655 if (MLValueIs0WOM(n2) || MLValueIs0WOM(lqv)){
656 // Error! Check whether we have a pointer to a return error code value.
657 if (isError == nullptr){
658 // No, post an error.
659 printTemplateError("TQuaternion::sqrt() const, sqrt of quaternion cannot be calculated",
661 "Returning default quaternion");
662 }
663 else{
664 // Yes, set return code.
665 *isError = true;
666 }
667 }
668 else{
669 // Calculate sqrt, lqv and n2 are non 0 here.
670 const DT sqrtSin = ::sqrt(n2)*::sin(0.5*acos(qw/n2));
671 const DT sqrtSinF = sqrtSin*(1/lqv);
672 retVal.set(sqrtSinF*qx, sqrtSinF*qy, sqrtSinF*qz, ::sqrt(n2) * ::cos(0.5*acos(qw/n2)));
673
674 // Non zero => no error.
675 if (isError != nullptr){ *isError = false; }
676 }
677 return retVal;
678 }
679
680
684
686 inline TQuaternion<DT> exp() const
687 {
688 // Initialize return value with default quaternion.
689 TQuaternion<DT> retVal(0,0,0,1);
690 const DT len = qv().length();
691 if (MLValueIs0WOM(len)){
692 retVal = TQuaternion<DT>(0,0,0,::cos(len)).mult(::exp(qw));
693 }
694 else{
695 retVal = TQuaternion<DT>((qv()/len) * static_cast<DT>(::sin(len)), ::cos(len)).mult(::exp(qw));
696 }
697 return retVal;
698 }
699
700
702 inline TQuaternion<DT> ln() const
703 {
704 // Initialize return value with default quaternion.
705 TQuaternion<DT> retVal(0,0,0,1);
706 const DT n2 = norm2();
707 const DT qvLen = qv().length();
708 if (MLValueIs0WOM(qvLen)){
709 retVal.set(0, 0, 0, log10(n2));
710 }
711 else{
712 // n2 is always non 0 if qvLen is non-zero, thus no check is necessary.
713 retVal.set(qv()/qvLen * static_cast<DT>(acos(qw/n2)), log10(n2));
714 }
715 return retVal;
716 }
717
718
720 inline TQuaternion<DT> pow(const TQuaternion<DT> &quat) const {return ln().mult(quat).exp(); }
721
722
726
729 {
730 TQuaternion<DT> retVal;
731 const Tvec3<DT> &v = qv();
732 const DT len = v.length();
733 // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
734 // Then the quaternion method behaves like the normal function on real values.
735 retVal.set((!MLValueIs0WOM(len) ?
736 static_cast<DT>(::cos(qw)) * v / len * static_cast<DT>(::sinh(len)) :
737 Tvec3<DT>(0.0)),
738 ::sin(qw)*::cosh(len)
739 );
740 return retVal;
741 }
742
745 {
746 TQuaternion<DT> retVal;
747 const Tvec3<DT> &v = qv();
748 const DT len = v.length();
749 // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
750 // Then the quaternion method behaves like the normal function on real values.
751 retVal.set((!MLValueIs0WOM(len) ?
752 static_cast<DT>(-1)*static_cast<DT>(::sin(qw))*qv()/len*static_cast<DT>(::sinh(len)) :
753 Tvec3<DT>(0.0)),
754 ::cos(qw)*::cosh(len)
755 );
756 return retVal;
757 }
758
760 inline TQuaternion<DT> tan(bool *isError=nullptr) const { return sin().div(cos(), isError); }
761
763 inline TQuaternion<DT> cotan(bool *isError=nullptr) const { return cos().div(sin(), isError); }
764
765
766
770
773 {
774 TQuaternion<DT> retVal;
775 const Tvec3<DT> &v = qv();
776 const DT len = v.length();
777 // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
778 // Then the quaternion method behaves like the normal function on real values.
779 retVal.set((!MLValueIs0WOM(len) ?
780 static_cast<DT>(::cosh(qw))*v/len*static_cast<DT>(::sin(len)) :
781 Tvec3<DT>(0.0)),
782 ::sinh(qw)*::cos(len)
783 );
784 return retVal;
785 }
786
789 {
790 TQuaternion<DT> retVal;
791 const Tvec3<DT> &v = qv();
792 const DT len = v.length();
793 // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
794 // Then the quaternion method behaves like the normal function on real values.
795 retVal.set((!MLValueIs0WOM(len) ?
796 static_cast<DT>(::sinh(qw))*v/len*static_cast<DT>(::sin(len)) :
797 Tvec3<DT>(0.0)),
798 ::cosh(qw)*::cos(len)
799 );
800 return retVal;
801 }
802
804 inline TQuaternion<DT> tanh(bool *isError=nullptr) const
805 {
806 return sinh().div(cosh(), isError);
807 }
808
810 inline TQuaternion<DT> cotanh(bool *isError=nullptr) const
811 {
812 return cosh().div(sinh(), isError);
813 }
814
815
816
820
822 inline TQuaternion<DT> arcsinh() const { return add(mult(*this).add(TQuaternion<DT>( 1)).sqrt()).ln(); }
823
825 inline TQuaternion<DT> arccosh() const { return add(mult(*this).add(TQuaternion<DT>(-1)).sqrt()).ln(); }
826
828 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); }
829
830
840 #define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR) \
841 TQuaternion<DT> retVal; \
842 { \
843 const Tvec3<DT> &v = qv(); \
844 const DT len = v.length(); \
845 if (MLValueIs0WOM(len)){ \
846 /* Error! Check whether we have a pointer to a return error code value. */ \
847 if (isError == NULL){ \
848 /* No, post an error. */ \
849 printTemplateError("TQuaternion::" FUNC_NAME "() const, " FUNC_NAME \
850 " of quaternion cannot be calculated", \
851 ML_BAD_PARAMETER, \
852 "Returning default quaternion"); \
853 } \
854 else{ \
855 /* Yes, set return code, retVal is left on default. */ \
856 *isError = true; \
857 } \
858 } \
859 else{ \
860 /* Define return values. */ \
861 if (isError != NULL){ *isError = false; } \
862 retVal = CALC_EXPR; \
863 } \
864 } \
865 return retVal; \
866
867
868
870 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arcsinh());
874
876 TQuaternion<DT> arcsin(bool *isError=nullptr) const
877 {
879 }
880 #undef _ML_QUAT_CALC_EXP
881
882
883
885 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(arccosh());
887 TQuaternion<DT> arccos(bool *isError=nullptr) const
888 {
890 }
891 #undef _ML_QUAT_CALC_EXP
892
893
894
896 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arctanh());
898 TQuaternion<DT> arctan(bool *isError=nullptr) const
899 {
901 }
902 #undef _ML_QUAT_CALC_EXP
903
904
905 // Undefines _ML_QUATERNION_CALC_CHECKED, it is not needed anymore.
906 #undef _ML_QUATERNION_CALC_CHECKED
907};
908
909
910//-----------------------------------------------------------------------------------
913//-----------------------------------------------------------------------------------
916
919
922
926
927
928ML_LA_END_NAMESPACE
929
930
931
932
933//-------------------------------------------------------------------------
940//-------------------------------------------------------------------------
941#ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
942#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
943ML_LA_START_NAMESPACE
944#endif
945
946//-----------------------------
947// Addition
948//-----------------------------
950template <typename DT>
951inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
952 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
953}
954
956template <typename DT>
957inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
958 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
959}
960
962template <typename DT>
963inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
964 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
965 return qa.operator+(qb);
966}
967
968
969
970//-----------------------------
971// Subtraction
972//-----------------------------
974template <typename DT>
975inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
976 return ML_LA_NAMESPACE::TQuaternion<DT>(-q.qx, -q.qy, -q.qz, d-q.qw);
977}
978
980template <typename DT>
981inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
982 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw-d);
983}
984
986template <typename DT>
987inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
988 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
989 return qa.operator-(qb);
990}
991
992
994template <typename DT>
995inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
996 return q.mult(d);
997}
998
1000template <typename DT>
1001inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
1002 return q.mult(d);
1003}
1004
1006template <typename DT>
1007inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
1008 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
1009 return qa.operator*(qb);
1010}
1012
1013#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1014ML_LA_END_NAMESPACE
1015#endif
1016
1017#endif // _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
1018
1019
1020
1021//-------------------------------------------------------------------------
1028//-------------------------------------------------------------------------
1029#ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1030#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1031ML_LA_START_NAMESPACE
1032#endif
1033
1036#ifdef _ML_IMPLEMENT_QUATERNION_SQRT
1037template <typename DT>
1038inline ML_LA_NAMESPACE::TQuaternion<DT> sqrt (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sqrt(); }
1039#endif
1040
1042template <typename DT>
1043inline ML_LA_NAMESPACE::TQuaternion<DT> exp (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.exp(); }
1044
1046template <typename DT>
1047inline ML_LA_NAMESPACE::TQuaternion<DT> ln (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.ln(); }
1048
1050template <typename DT>
1051inline ML_LA_NAMESPACE::TQuaternion<DT> sin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sin(); }
1052
1054template <typename DT>
1055inline ML_LA_NAMESPACE::TQuaternion<DT> cos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cos(); }
1056
1058template <typename DT>
1059inline ML_LA_NAMESPACE::TQuaternion<DT> tan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tan(); }
1060
1062template <typename DT>
1063inline ML_LA_NAMESPACE::TQuaternion<DT> cotan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotan(); }
1064
1066template <typename DT>
1067inline ML_LA_NAMESPACE::TQuaternion<DT> sinh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sinh(); }
1068
1070template <typename DT>
1071inline ML_LA_NAMESPACE::TQuaternion<DT> cosh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cosh(); }
1072
1074template <typename DT>
1075inline ML_LA_NAMESPACE::TQuaternion<DT> tanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tanh(); }
1076
1078template <typename DT>
1079inline ML_LA_NAMESPACE::TQuaternion<DT> cotanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotanh(); }
1080
1082template <typename DT>
1083inline ML_LA_NAMESPACE::TQuaternion<DT> arcsinh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsinh(); }
1084
1086template <typename DT>
1087inline ML_LA_NAMESPACE::TQuaternion<DT> arccosh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccosh(); }
1088
1090template <typename DT>
1091inline ML_LA_NAMESPACE::TQuaternion<DT> arctanh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctanh(); }
1092
1094template <typename DT>
1095inline ML_LA_NAMESPACE::TQuaternion<DT> arcsin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsin(); }
1096
1098template <typename DT>
1099inline ML_LA_NAMESPACE::TQuaternion<DT> arccos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccos(); }
1100
1102template <typename DT>
1103inline ML_LA_NAMESPACE::TQuaternion<DT> arctan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctan(); }
1104
1105
1106#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1107ML_LA_END_NAMESPACE
1108#endif
1109
1110#endif // _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1112
1113
1114//-----------------------------------------------------------------------------------
1115// Stream output for std::ostream and dyadic multiplication of TQuaternion and scalar.
1116//-----------------------------------------------------------------------------------
1117namespace std {
1118
1120 template <typename DT>
1121 inline ostream& operator<<(ostream& s, const ML_NAMESPACE::TQuaternion<DT> &v){
1122 return s << "(" << v.qx << "," << v.qy << "," << v.qz << "," << v.qw << ")";
1123 }
1124
1125}
1126
1127
1128#endif // __mlQuaternion_H
Template class for vector arithmetic with floating point datatypes.
T length() const
Returns the length of the vector, i.e., norm2().
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 dot(const FloatingPointVector< T, size, DataContainer > &buffer) const
Returns the dot product, i.e., sum of all components multiplied with corresponding components of buff...
Declaration of complex type traits.
TQuaternion< DT > arctan(bool *isError=nullptr) const
Inverse tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion(DT d)
Builds a quaternion from a scalar by setting all elements to 0 and qw to the scalar; use explicitly t...
TQuaternion< DT > arccos(bool *isError=nullptr) const
Inverse cosine; for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion< DT > euclideanMult(const TQuaternion< DT > &q) const
Euclidean product of this quaternion with another one (which is non-commutative).
DT dot(const TQuaternion< DT > &p) const
Dot product, equivalent to four component vector dot product.
TQuaternion< DT > arg(bool *isError=nullptr) const
Computes the quaternion argument.
TQuaternion< DT > ln() const
Computes the natural logarithm.
TQuaternion(DT x, DT y, DT z, DT w)
Creates a new TQuaternion with the DT values given.
TQuaternion< DT > arccosh() const
Computes the inverse hyperbolic cosine.
DT qx
First element of imaginary part.
TQuaternion< DT > sinh() const
Hyperbolic functions: Hyperbolic sine, hyperbolic cosine, hyperbolic tangent https://en....
DT absoluteValue() const
Returns the absolute value of a quaternion, which is the scalar quantity that determines the length o...
TQuaternion< DT > tan(bool *isError=nullptr) const
Computes the tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion< DT > add(const TQuaternion< DT > &b) const
Adds another quaternion b to this one and returns the sum.
TQuaternion< DT > tanh(bool *isError=nullptr) const
Computes the hyperbolic tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > getImaginaryPart() const
Returns a copy of the quaternion's imaginary part.
TQuaternion< DT > sqrt(bool *isError=nullptr) const
Computes the square root of a quaternion.
void set(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, const DT w)
Sets all quaternion elements from a vector and DT parameter.
TQuaternion< DT > div(const TQuaternion< DT > &d, bool *isError=nullptr) const
Divides a quaternion by another quaternion.
TQuaternion< DT > sgn(bool *isError=nullptr) const
Returns the sign of the quaternion.
const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv() const
Returns a constant reference to the quaternion's imaginary part as vector object.
TQuaternion< DT > cotan(bool *isError=nullptr) const
Computes the cotangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv()
Returns a modifiable reference to the quaternion's imaginary part as vector object,...
TQuaternion< DT > sin() const
Trigonometric functions: sine, cosine, tangent, cotangent.
TQuaternion< DT > cosh() const
Computes the hyperbolic cosine.
TQuaternion< DT > arcsin(bool *isError=nullptr) const
Inverse trigonometric functions: Inverse sine, inverse cosine, inverse tangent.
TQuaternion< DT > exp() const
Exponential and logarithmic functions: natural exponential, natural logarithm, power.
TQuaternion< DT > negate() const
Computes the negation.
DT norm() const
Computes the d-norm.
TQuaternion< DT > arctanh() const
Computes the inverse hyperbolic tangent.
TQuaternion< DT > arcsinh() const
Inverse hyperbolic function: arcsinh, arccosh, arctanh.
TQuaternion< DT > mult(const TQuaternion< DT > &q) const
Multiplies this quaternion with another one (which is non-commutative). It is also called Grassman pr...
TQuaternion< DT > compDiv(const TQuaternion< DT > &b, bool *isError=nullptr) const
Divides each component by its corresponding component from b.
TQuaternion()
Standard constructor that is setting all elements to 0.
TQuaternion< DT > inverse(bool *isInvertible=nullptr) const
Computes and returns the inverse.
DT qw
Real part.
DT value_type
Scalar type used for qx, qy, qz, and qw.
DT & operator[](const size_t i)
Indexing operator.
Tmat4< DT > getAsMat4(bool *isConvertible=nullptr) const
Converts this quaternion to a 4x4 matrix.
TQuaternion< DT > & operator=(const TQuaternion< DT > &q)
Assignment operator.
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...
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.
DT norm2() const
Computes the magnitude of the quaternion.
TQuaternion< DT > odd(const TQuaternion< DT > &p) const
Odd product, also known as cross-product or Grassman outer product.
TQuaternion< DT > normalize(bool *isError=nullptr) const
Returns the normalization of the quaternion.
TQuaternion(const TQuaternion< DT2 > &q2)
Copy constructor from another TQuaternion of same or different type.
TQuaternion< DT > conjugate() const
Computes the conjugate.
DT qz
Third element of imaginary part.
TQuaternion< DT > mult(DT s) const
Multiplies this quaternion with a scalar factor s.
TQuaternion(const FloatingPointVector< DT, 4 > &v)
Creates a new TQuaternion from the four-dimensional parameter vector.
TQuaternion< DT > cos() const
Computes the cosine.
DT operator[](const size_t i) const
Constant indexing operator.
TQuaternion< DT > cotanh(bool *isError=nullptr) const
Computes the hyperbolic cotangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion< DT > pow(const TQuaternion< DT > &quat) const
Computes the power of a quaternion.
TQuaternion(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, DT w)
Constructor with a vector and DT parameter.
TQuaternion(const TQuaternion &q2)=default
DT getRealPart() const
Returns a copy of the quaternion's real part, also called scalar() of a quaternion.
DT qy
Second element of imaginary part.
TQuaternion< DT > even(const TQuaternion< DT > &p) const
Even product, also known as Grassman inner product.
TQuaternion< DT > outer(const TQuaternion< DT > &q) const
Euclidean outer product of this quaternion with another one.
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:822
#define ML_CHECK_FLOAT(x)
#define _ML_QUAT_CALC_EXP
Internal helper macro - do not use.
#define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR)
Defines a code fragment that checks and handles operations for safe expression calculations.
double exp(T value)
double sqrt(T value)
ScopeGuard< Functor > operator+(ScopeGuardOnExit, Functor &&fn)
void ML_UTILS_EXPORT printTemplateError(const char *location, MLErrorCode reason, const std::string_view &handling)
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).
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.
STL namespace.
MLEXPORT std::ostream & operator<<(std::ostream &s, const ml::Field &v)
Overloads the operator '<<' for stream output of Field objects.