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.
26
27// 3D double vector.
28#include "mlVector3.h"
29#include <mlErrorMacros.h>
30#include <mlErrorOutput.h>
32
34
35//--------------------------------------------------------
39//--------------------------------------------------------
40template <typename DT>
42{
43
44public:
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
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
364 inline TQuaternion<DT> operator / (DT d) const
365 {
366 TQuaternion<DT> retVal(*this);
368 retVal /= d;
369 return retVal;
370 }
371
373 inline TQuaternion<DT> &operator /= (DT d)
374 {
376 qx/=d; qy/=d; qz/=d; qw/=d;
377 return *this;
378 }
379
380
382 inline TQuaternion<DT> operator / (const TQuaternion<DT> &q) const
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.
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.
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 }
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();
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 {
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 {
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 {
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 {
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
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
953#endif
954
955//-----------------------------
956// Addition
957//-----------------------------
959template <typename DT>
960inline 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
965template <typename DT>
966inline 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
971template <typename DT>
972inline 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//-----------------------------
983template <typename DT>
984inline 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
989template <typename DT>
990inline 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
995template <typename DT>
996inline 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
1003template <typename DT>
1004inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
1005 return q.mult(d);
1006}
1007
1009template <typename DT>
1010inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
1011 return q.mult(d);
1012}
1013
1015template <typename DT>
1016inline 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
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
1041#endif
1042
1045#ifdef _ML_IMPLEMENT_QUATERNION_SQRT
1046template <typename DT>
1047inline ML_LA_NAMESPACE::TQuaternion<DT> sqrt (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sqrt(); }
1048#endif
1049
1051template <typename DT>
1052inline ML_LA_NAMESPACE::TQuaternion<DT> exp (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.exp(); }
1053
1055template <typename DT>
1056inline ML_LA_NAMESPACE::TQuaternion<DT> ln (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.ln(); }
1057
1059template <typename DT>
1060inline ML_LA_NAMESPACE::TQuaternion<DT> sin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sin(); }
1061
1063template <typename DT>
1064inline ML_LA_NAMESPACE::TQuaternion<DT> cos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cos(); }
1065
1067template <typename DT>
1068inline ML_LA_NAMESPACE::TQuaternion<DT> tan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tan(); }
1069
1071template <typename DT>
1072inline ML_LA_NAMESPACE::TQuaternion<DT> cotan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotan(); }
1073
1075template <typename DT>
1076inline ML_LA_NAMESPACE::TQuaternion<DT> sinh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sinh(); }
1077
1079template <typename DT>
1080inline ML_LA_NAMESPACE::TQuaternion<DT> cosh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cosh(); }
1081
1083template <typename DT>
1084inline ML_LA_NAMESPACE::TQuaternion<DT> tanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tanh(); }
1085
1087template <typename DT>
1088inline ML_LA_NAMESPACE::TQuaternion<DT> cotanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotanh(); }
1089
1091template <typename DT>
1092inline ML_LA_NAMESPACE::TQuaternion<DT> arcsinh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsinh(); }
1093
1095template <typename DT>
1096inline ML_LA_NAMESPACE::TQuaternion<DT> arccosh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccosh(); }
1097
1099template <typename DT>
1100inline ML_LA_NAMESPACE::TQuaternion<DT> arctanh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctanh(); }
1101
1103template <typename DT>
1104inline ML_LA_NAMESPACE::TQuaternion<DT> arcsin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsin(); }
1105
1107template <typename DT>
1108inline ML_LA_NAMESPACE::TQuaternion<DT> arccos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccos(); }
1109
1111template <typename DT>
1112inline 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
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//-----------------------------------------------------------------------------------
1126namespace 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
Template class for vector arithmetic with floating point data types.
T length() const
Returns the length of the vector, i.e. norm2().
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 explicit to ...
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 4 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 Source: http://www....
DT absoluteValue() const
Returns the absolute value of a quaternion which is the scalar quantity that determines the length of...
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 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; the caller must guarantee that b does n...
TQuaternion()
Standard constructor, 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 to the quaternion and returns the sum, it is equivalent to a scalar add of s to the qw ...
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 other 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.
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
explicitly generating the default constructor, to avoid a warning message with gcc9:
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 four by four matrix class consisting of 4 row vectors.
Definition mlMatrix4.h:36
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:823
#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 which checks and handles some stuff for safe expression calculations.
Target mlrange_cast(Source arg)
Generic version of checked ML casts.
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 ? 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).
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.