ML 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
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 }
337
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) :
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) &&
426
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
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
Declaration of complex type traits.
TQuaternion< DT > arctan(bool *isError=nullptr) const
Inverse tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
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
TQuaternion< DT > ln() const
Computes the natural logarithm.
TQuaternion(DT x, DT y, DT z, DT w)
TQuaternion< DT > arccosh() const
Computes the inverse hyperbolic cosine.
TQuaternion< MLfloat > sinh() const
DT absoluteValue() const
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
TQuaternion< DT > sqrt(bool *isError=nullptr) const
void set(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, const DT w)
TQuaternion< MLfloat > div(const TQuaternion< MLfloat > &d, bool *isError=nullptr) const
TQuaternion< DT > sgn(bool *isError=nullptr) const
const FloatingPointVector< MLfloat, 3, Vector3DataContainer< MLfloat > > & qv() const
TQuaternion< DT > cotan(bool *isError=nullptr) const
Computes the cotangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv()
TQuaternion< MLfloat > sin() const
TQuaternion< MLfloat > cosh() const
TQuaternion< DT > arcsin(bool *isError=nullptr) const
Inverse sine, for error handling see _ML_QUATERNION_CALC_CHECKED.
bool operator==(const TQuaternion< MLfloat > &b) const
TQuaternion< DT > exp() const
Computes the natural exponential.
TQuaternion< DT > negate() const
Computes the negation.
TQuaternion< DT > arctanh() const
Computes the inverse hyperbolic tangent.
TQuaternion< DT > arcsinh() const
Computes the inverse hyperbolic sine.
TQuaternion< MLfloat > mult(const TQuaternion< MLfloat > &q) const
TQuaternion< DT > compDiv(const TQuaternion< DT > &b, bool *isError=nullptr) const
TQuaternion()
Standard constructor that is setting all elements to 0.
TQuaternion< DT > inverse(bool *isInvertible=nullptr) const
DT value_type
Scalar type used for qx, qy, qz, and qw.
DT & operator[](const size_t i)
Tmat4< DT > getAsMat4(bool *isConvertible=nullptr) const
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)
DT norm2() const
TQuaternion< DT > odd(const TQuaternion< DT > &p) const
TQuaternion< DT > normalize(bool *isError=nullptr) const
TQuaternion(const TQuaternion< DT2 > &q2)
TQuaternion< MLfloat > conjugate() const
TQuaternion< DT > mult(DT s) const
Multiplies this quaternion with a scalar factor s.
TQuaternion(const FloatingPointVector< DT, 4 > &v)
TQuaternion< MLfloat > cos() const
DT operator[](const size_t i) const
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)
TQuaternion(const TQuaternion &q2)=default
DT getRealPart() const
Returns a copy of the quaternion's real part, also called scalar() of a quaternion.
TQuaternion< DT > even(const TQuaternion< DT > &p) const
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
static Tmat4< DT > getIdentity()
Returns the identity matrix.
Definition mlMatrix4.h:584
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)
bool MLValuesAreEqualWOM(MLint8 a, MLint8 b)
#define ML_BAD_PARAMETER
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)
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)
TQuaternion< MLdouble > Quaternion
Defines the default Quaternion type that is used by the ML; it uses double as component type.
TQuaternion< MLfloat > Quaternionf
A smaller Quaternion type as a specialization from TQuaternion.
T operator*(const FloatingPointVector< T, size, DataContainer > &a, const FloatingPointVector< T, size, DataContainer > &b)
FloatingPointVector< T, size, DataContainer > operator+(FloatingPointVector< T, size, DataContainer > lhs, const FloatingPointVector< T, size, DataContainer > &rhs)
TQuaternion< MLldouble > Quaternionld
A large Quaternion type for further extensions of the ML as a specialization from TQuaternion.
TQuaternion< MLdouble > Quaterniond
The default Quaternion type used in the ML as a specialization from TQuaternion.
FloatingPointVector< T, size, DataContainer > operator-(FloatingPointVector< T, size, DataContainer > lhs, const FloatingPointVector< T, size, DataContainer > &rhs)
STL namespace.
MLEXPORT std::ostream & operator<<(std::ostream &s, const ml::Field &v)
Overloads the operator '<<' for stream output of Field objects.