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
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
114 TQuaternion(const TQuaternion &q2) = default;
115
123 inline explicit TQuaternion(DT x, DT y, DT z, DT w)
124 {
125 qx = x;
126 qy = y;
127 qz = z;
128 qw = w;
129 }
130
139 inline explicit TQuaternion(const FloatingPointVector<DT,4> &v)
140 {
141 qx = v[1];
142 qy = v[2];
143 qz = v[3];
144 qw = v[0];
145 }
146
151 inline explicit TQuaternion(const FloatingPointVector<DT, 3, Vector3DataContainer<DT> > &v, DT w) :
152 qx(v[0]), qy(v[1]), qz(v[2]), qw(w)
153 {
154 }
155
157
158
159 //-------------------------------------------------------------------------
162 //-------------------------------------------------------------------------
163
167 {
168 return qv();
169 }
170
172 inline DT getRealPart() const
173 {
174 return qw;
175 }
176
185 {
186 return reinterpret_cast<const FloatingPointVector<DT, 3, Vector3DataContainer<DT> >&>(qx);
187 }
188
197
201 inline void set(const FloatingPointVector<DT, 3, Vector3DataContainer<DT> > &v, const DT w)
202 {
203 qx = v[0];
204 qy = v[1];
205 qz = v[2];
206 qw = w;
207 }
208
211 inline void set(const DT x, const DT y, const DT z, const DT w)
212 {
213 qx = x;
214 qy = y;
215 qz = z;
216 qw = w;
217 }
218
224 inline Tmat4<DT> getAsMat4(bool *isConvertible=nullptr) const
225 {
226 // Create return value.
227 Tmat4<DT> m;
228 // Check whether conversion is possible.
229 const DT n=norm();
230 if (0==n) {
231 if (!isConvertible){
232 printTemplateError("TQuaternion::getAsMat4() const, quaternion is not convertible to 4x4 matrix",
234 "Returning Quaterion");
235 }
236 else{
237 *isConvertible = false;
238 }
240 }
241 else{
242 // Conversion is possible.
243 const DT s = 2./n;
244 //s is a compressed factor
245 //it originates from the constant factor 2 and the normalization
246 //factor for the vector "1/sqrt(norm(vector))"
247 //To normalize the vector each component is divided by "1/sqrt(norm(vector))"
248 //So each vector component qx,qy,qz has to get its own factor to normalize
249 //the vector while calculating the matrix. However, as s is multiplied
250 //always to a pair of 2 multiplied vector components, the factor can be
251 //pulled in front of the addition (c.f. m11). As pairs of vector components
252 //are added, the sqrt vanishes and what is left is the factor 2./norm(vector)
253 //where norm is what is defined as "norm()" inside the mlQuaternion.h.
254
255 // q0 = qw, first column.
256 const DT qxqx = qx*qx;
257 const DT qyqy = qy*qy;
258 const DT qzqz = qz*qz;
259
260 const DT qxqy = qx*qy;
261 const DT qxqz = qx*qz;
262 const DT qxqw = qx*qw;
263
264 const DT qyqz = qy*qz;
265 const DT qyqw = qy*qw;
266
267 const DT qzqw = qz*qw;
268
269 const DT m11 = 1 - s * (qyqy + qzqz);
270 const DT m12 = s * (qxqy - qzqw);
271 const DT m13 = s * (qxqz + qyqw);
272
273 const DT m21 = s * (qxqy + qzqw);
274 const DT m22 = 1 - s * (qxqx + qzqz);
275 const DT m23 = s * (qyqz - qxqw);
276
277 const DT m31 = s * (qxqz - qyqw);
278 const DT m32 = s * (qyqz + qxqw);
279 const DT m33 = 1 - s * (qxqx + qyqy);
280
281 // Construct matrix from precomputed values
282 m.set(0);
283 m[0][0] = m11;
284 m[0][1] = m12;
285 m[0][2] = m13;
286 m[0][3] = 0.0;
287
288 m[1][0] = m21;
289 m[1][1] = m22;
290 m[1][2] = m23;
291 m[1][3] = 0.0;
292
293 m[2][0] = m31;
294 m[2][1] = m32;
295 m[2][2] = m33;
296 m[2][3] = 0.0;
297
298 m[3][0] = 0.0;
299 m[3][1] = 0.0;
300 m[3][2] = 0.0;
301 m[3][3] = 1.0;
302
303 if (isConvertible){ *isConvertible = true; }
304
305 } // else
306 return m;
307 }
308
310
311
312 //-------------------------------------------------------------------------
315 //-------------------------------------------------------------------------
316
320 inline DT operator[](const size_t i) const { return array[i]; }
321
325 inline DT &operator[](const size_t i) { return array[i]; }
326
329 {
330 if (this != &q){
331 qx = q.qx;
332 qy = q.qy;
333 qz = q.qz;
334 qw = q.qw;
335 }
336 return *this;
337 }
339
340
341 //------------------------------------------------------
344 //------------------------------------------------------
345
347 inline TQuaternion<DT> operator + (const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx+b.qx, qy+b.qy, qz+b.qz, qw+b.qw); }
349 inline TQuaternion<DT> &operator += (const TQuaternion<DT> &b) { qx+=b.qx; qy+=b.qy; qz+=b.qz; qw+=b.qw; return *this; }
350
352 inline TQuaternion<DT> operator - (const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx-b.qx, qy-b.qy, qz-b.qz, qw-b.qw); }
354 inline TQuaternion<DT> &operator -= (const TQuaternion<DT> &b) { qx-=b.qx; qy-=b.qy; qz-=b.qz; qw-=b.qw; return *this; }
355
357 inline TQuaternion<DT> operator * (const TQuaternion<DT> &b) const { return mult(b); }
359 inline TQuaternion<DT> &operator *= (const TQuaternion<DT> &b) { *this = mult(b); return *this; }
360
362 inline TQuaternion<DT> operator / (DT d) const
363 {
364 TQuaternion<DT> retVal(*this);
366 retVal /= d;
367 return retVal;
368 }
369
371 inline TQuaternion<DT> &operator /= (DT d)
372 {
374 qx/=d; qy/=d; qz/=d; qw/=d;
375 return *this;
376 }
377
378
380 inline TQuaternion<DT> operator / (const TQuaternion<DT> &q) const
381 {
382 return TQuaternion<DT>(div(q));
383 }
384
389 inline TQuaternion<DT> compDiv(const TQuaternion<DT> &b, bool *isError=nullptr) const
390 {
391 // Initialize return value with default quaternion.
392 TQuaternion<DT> retVal(0,0,0,1);
393 if (!isError){
394 // No error flag passed. Handle error if necessary.
399 retVal.set(qx/b.qx, qy/b.qy, qz/b.qz, qw/b.qw);
400 }
401 else{
402 // Error flag is available. Return *isError as true in case of error
403 *isError = (b.qx == 0) ||
404 (b.qy == 0) ||
405 (b.qz == 0) ||
406 (b.qw == 0);
407
408 retVal = *isError ?
409 TQuaternion<DT>(b.qx != 0 ? qx/b.qx : qx,
410 b.qy != 0 ? qy/b.qy : qy,
411 b.qz != 0 ? qz/b.qz : qz,
412 b.qw != 0 ? qw/b.qw : qw) :
413 TQuaternion<DT>(qx/b.qx,
414 qy/b.qy,
415 qz/b.qz,
416 qw/b.qw);
417 }
418 return retVal;
419 }
420
423 inline bool operator == (const TQuaternion<DT> &b) const { return MLValuesAreEqualWOM(qx, b.qx) &&
424 MLValuesAreEqualWOM(qy, b.qy) &&
425 MLValuesAreEqualWOM(qz, b.qz) &&
426 MLValuesAreEqualWOM(qw, b.qw); }
429 inline bool operator != (const TQuaternion<DT> &b) const { return !operator==(b); }
431
432
433
435 inline DT dot(const TQuaternion<DT> &p) const { return qx*p.qx + qy*p.qy + qz*p.qz + qw*p.qw; }
436
439 inline TQuaternion<DT> odd(const TQuaternion<DT> &p) const { return TQuaternion<DT>(qy*p.qz - qz*p.qy,
440 qz*p.qx - qx*p.qz,
441 qx*p.qy - qy*p.qx,
442 0); }
443
446 inline TQuaternion<DT> even(const TQuaternion<DT> &p) const { return TQuaternion<DT>(qw*p.qx + qx*p.qw,
447 qw*p.qy + qy*p.qw,
448 qw*p.qz + qz*p.qw,
449 qw*p.qw - qx*p.qx - qy*p.qy - qz*p.qz); }
450
452 inline TQuaternion<DT> mult(const TQuaternion<DT> &q) const { Tvec3<DT> img(qv()); Tvec3<DT> qimg(q.qv()); return TQuaternion<DT>(img.cross(qimg) + img*q.qw + qw*qimg, qw*q.qw - img.dot(qimg)); }
453
455 inline TQuaternion<DT> euclideanMult(const TQuaternion<DT> &q) const { return conjugate().mult(q); }
456
458 inline TQuaternion<DT> outer(const TQuaternion<DT> &q) const { return (euclideanMult(q) - q.euclideanMult(*this)) / 2; }
459
460
469 inline TQuaternion<DT> div(const TQuaternion<DT> &d, bool *isError=nullptr) const
470 {
471 // Initialize return value with default quaternion.
472 TQuaternion<DT> retVal(0,0,0,1);
473 if (d == TQuaternion<DT>(0,0,0,0)){
474 if (isError == nullptr){
475 // No error flag passed. Handle error if necessary.
476 printTemplateError("TQuaternion::div() const, quaternion is not divisible",
478 "Returning unchanged quaternion");
479 retVal.set(qx,qy,qz,qw);
480 }
481 else{
482 // Error flag pointer is available. Return *isError as true in case of error
483 *isError = true;
484 retVal.set(qx,qy,qz,qw);
485 }
486 }
487 else{
488 if (isError != nullptr){ *isError = false; }
489 retVal.set((d.qw*qx - d.qx*qw - d.qy*qz + d.qz*qy)/(d.qw*d.qw + d.qx*d.qx + d.qy*d.qy + d.qz*d.qz),
490 (d.qw*qy + d.qx*qz - d.qy*qw - d.qz*qx)/(d.qw*d.qw + d.qx*d.qx + d.qy*d.qy + d.qz*d.qz),
491 (d.qw*qz - d.qx*qy + d.qy*qx - d.qz*qw)/(d.qw*d.qw + d.qx*d.qx + d.qy*d.qy + d.qz*d.qz),
492 (d.qw*qw + d.qx*qx + d.qy*qy + d.qz*qz)/(d.qw*d.qw + d.qx*d.qx + d.qy*d.qy + d.qz*d.qz));
493 }
494 return retVal;
495 }
496
497
499 inline TQuaternion<DT> mult(DT s) const { return TQuaternion<DT>(qx*s, qy*s, qz*s, qw*s); }
500
502 inline TQuaternion<DT> add(const TQuaternion<DT> &b) const { return TQuaternion<DT>(qx+b.qx, qy+b.qy, qz+b.qz, qw+b.qw); }
503
505 inline TQuaternion<DT> add(DT s) const { return TQuaternion<DT>(qx, qy, qz, qw+s); }
506
508 inline TQuaternion<DT> conjugate() const { return TQuaternion<DT>(-qx, -qy, -qz, qw); }
509
511 inline TQuaternion<DT> negate() const { return TQuaternion<DT>(-qx, -qy, -qz, -qw); }
512
514 inline DT norm() const { return qx*qx + qy*qy + qz*qz + qw*qw; }
515
516
519 inline DT norm2() const { return static_cast<DT>(::sqrt(qx*qx + qy*qy + qz*qz + qw*qw)); }
520
523 inline DT absoluteValue() const { return static_cast<DT>(::sqrt(norm())); }
524
529 inline TQuaternion<DT> normalize(bool *isError=nullptr) const
530 {
531 // Initialize return value with default quaternion.
532 TQuaternion<DT> retVal(0,0,0,1);
533 const DT n=norm2();
534 if (MLValueIs0WOM(n)){
535 // Error! Check whether we have a pointer to a return error code value.
536 if (isError == nullptr){
537 // No, post an error.
538 printTemplateError("TQuaternion::normalize() const, quaternion can not be normalized",
540 "Returning default quaternion");
541 }
542 else{
543 // Yes, set return code.
544 *isError = true;
545 }
546 }
547 else{
548 // Non zero => no error.
549 if (isError){ *isError = false; }
550 retVal.set(qx/n, qy/n, qz/n, qw/n);
551 }
552 return retVal;
553 }
554
561 inline TQuaternion<DT> arg(bool *isError=nullptr) const
562 {
563 // Initialize return value with default quaternion.
564 TQuaternion<DT> retVal(0,0,0,1);
565 // Norm2 must be non-zero to avoid divisions by zero.
566 const DT n=norm2();
567 if (MLValueIs0WOM(n)){
568 // Error! Check whether we have a pointer to a return error code value.
569 if (isError == nullptr){
570 // No, post an error.
571 printTemplateError("TQuaternion::arg() const, quaternion can not be normalized",
573 "Returning default quaternion");
574 }
575 else{
576 // Yes, set return code.
577 *isError = true;
578 }
579 }
580 else{
581 // Non zero => no error.
582 if (isError != nullptr){ *isError = false; }
583 retVal = acos(qw/n);
584 }
585 return retVal;
586 }
587
592 inline TQuaternion<DT> sgn(bool *isError=nullptr) const
593 {
594 // Initialize return value with default quaternion.
595 TQuaternion<DT> retVal(0,0,0,1);
596 const DT absVal = absoluteValue();
597 if (isError != nullptr){
598 // Set error return value.
599 if (absVal==0){
600 *isError = true;
601 }
602 else{
603 // No error.
604 *isError = false;
605 retVal = *this / absVal;
606 }
607 }
608 else{
609 // Post error is absVal == 0.
611 retVal = *this / absVal;
612 }
613 return retVal;
614 }
615
621 inline TQuaternion<DT> inverse(bool* isInvertible=nullptr) const
622 {
623 // Initialize return value with default quaternion.
624 TQuaternion<DT> retVal(0,0,0,1);
625 const DT n=norm();
626 if (MLValueIs0WOM(n)) {
627 if (isInvertible==nullptr){
628 printTemplateError("TQuaternion::() const, quaternion is not invertable",
630 "Returning default quaternion");
631 }
632 else{
633 *isInvertible = false;
634 }
636 }
637 else{
638 if (isInvertible != nullptr){ *isInvertible = true; }
639 retVal = conjugate().mult(1/n);
640 }
641 return retVal;
642 }
643
648 // return TQuaternion(::sqrt(norm2())*::sin(0.5*acos(qw/norm2()))*(1/qv().length())*Tvec3<DT>(qx,qy,qz),
649 inline TQuaternion<DT> sqrt(bool *isError=nullptr) const
650 {
651 // Initialize return value with default quaternion.
652 TQuaternion<DT> retVal(0,0,0,1);
653 // Precalculate constants and check for 0 division.
654 const DT n2 = norm2();
655 const DT lqv = qv().length();
657 // Error! Check whether we have a pointer to a return error code value.
658 if (isError == nullptr){
659 // No, post an error.
660 printTemplateError("TQuaternion::sqrt() const, sqrt of quaternion cannot be calculated",
662 "Returning default quaternion");
663 }
664 else{
665 // Yes, set return code.
666 *isError = true;
667 }
668 }
669 else{
670 // Calculate sqrt, lqv and n2 are non 0 here.
671 const DT sqrtSin = ::sqrt(n2)*::sin(0.5*acos(qw/n2));
672 const DT sqrtSinF = sqrtSin*(1/lqv);
673 retVal.set(sqrtSinF*qx, sqrtSinF*qy, sqrtSinF*qz, ::sqrt(n2) * ::cos(0.5*acos(qw/n2)));
674
675 // Non zero => no error.
676 if (isError != nullptr){ *isError = false; }
677 }
678 return retVal;
679 }
680
681
685
687 inline TQuaternion<DT> exp() const
688 {
689 // Initialize return value with default quaternion.
690 TQuaternion<DT> retVal(0,0,0,1);
691 const DT len = qv().length();
692 if (MLValueIs0WOM(len)){
693 retVal = TQuaternion<DT>(0,0,0,::cos(len)).mult(::exp(qw));
694 }
695 else{
696 retVal = TQuaternion<DT>((qv()/len) * static_cast<DT>(::sin(len)), ::cos(len)).mult(::exp(qw));
697 }
698 return retVal;
699 }
700
701
703 inline TQuaternion<DT> ln() const
704 {
705 // Initialize return value with default quaternion.
706 TQuaternion<DT> retVal(0,0,0,1);
707 const DT n2 = norm2();
708 const DT qvLen = qv().length();
709 if (MLValueIs0WOM(qvLen)){
710 retVal.set(0, 0, 0, log10(n2));
711 }
712 else{
713 // n2 is always non 0 if qvLen is non-zero, thus no check is necessary.
714 retVal.set(qv()/qvLen * static_cast<DT>(acos(qw/n2)), log10(n2));
715 }
716 return retVal;
717 }
718
719
721 inline TQuaternion<DT> pow(const TQuaternion<DT> &quat) const {return ln().mult(quat).exp(); }
722
723
727
730 {
732 const Tvec3<DT> &v = qv();
733 const DT len = v.length();
734 // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
735 // Then the quaternion method behaves like the normal function on real values.
736 retVal.set((!MLValueIs0WOM(len) ?
737 static_cast<DT>(::cos(qw)) * v / len * static_cast<DT>(::sinh(len)) :
738 Tvec3<DT>(0.0)),
739 ::sin(qw)*::cosh(len)
740 );
741 return retVal;
742 }
743
746 {
748 const Tvec3<DT> &v = qv();
749 const DT len = v.length();
750 // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
751 // Then the quaternion method behaves like the normal function on real values.
752 retVal.set((!MLValueIs0WOM(len) ?
753 static_cast<DT>(-1)*static_cast<DT>(::sin(qw))*qv()/len*static_cast<DT>(::sinh(len)) :
754 Tvec3<DT>(0.0)),
755 ::cos(qw)*::cosh(len)
756 );
757 return retVal;
758 }
759
761 inline TQuaternion<DT> tan(bool *isError=nullptr) const { return sin().div(cos(), isError); }
762
764 inline TQuaternion<DT> cotan(bool *isError=nullptr) const { return cos().div(sin(), isError); }
765
766
767
771
774 {
776 const Tvec3<DT> &v = qv();
777 const DT len = v.length();
778 // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
779 // Then the quaternion method behaves like the normal function on real values.
780 retVal.set((!MLValueIs0WOM(len) ?
781 static_cast<DT>(::cosh(qw))*v/len*static_cast<DT>(::sin(len)) :
782 Tvec3<DT>(0.0)),
783 ::sinh(qw)*::cos(len)
784 );
785 return retVal;
786 }
787
790 {
792 const Tvec3<DT> &v = qv();
793 const DT len = v.length();
794 // In case of len == 0 be sure not to divide by zero but setting vector to 0 vector.
795 // Then the quaternion method behaves like the normal function on real values.
796 retVal.set((!MLValueIs0WOM(len) ?
797 static_cast<DT>(::sinh(qw))*v/len*static_cast<DT>(::sin(len)) :
798 Tvec3<DT>(0.0)),
799 ::cosh(qw)*::cos(len)
800 );
801 return retVal;
802 }
803
805 inline TQuaternion<DT> tanh(bool *isError=nullptr) const
806 {
807 return sinh().div(cosh(), isError);
808 }
809
811 inline TQuaternion<DT> cotanh(bool *isError=nullptr) const
812 {
813 return cosh().div(sinh(), isError);
814 }
815
816
817
821
823 inline TQuaternion<DT> arcsinh() const { return add(mult(*this).add(TQuaternion<DT>( 1)).sqrt()).ln(); }
824
826 inline TQuaternion<DT> arccosh() const { return add(mult(*this).add(TQuaternion<DT>(-1)).sqrt()).ln(); }
827
829 inline TQuaternion<DT> arctanh() const { return TQuaternion<DT>((TQuaternion<DT>(qx,qy,qz,qw+1).ln()-TQuaternion<DT>(-qx, -qy, -qz, 1-qw).ln())/0.5); }
830
831
841 #define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR) \
842 TQuaternion<DT> retVal; \
843 { \
844 const Tvec3<DT> &v = qv(); \
845 const DT len = v.length(); \
846 if (MLValueIs0WOM(len)){ \
847 /* Error! Check whether we have a pointer to a return error code value. */ \
848 if (isError == NULL){ \
849 /* No, post an error. */ \
850 printTemplateError("TQuaternion::" FUNC_NAME "() const, " FUNC_NAME \
851 " of quaternion cannot be calculated", \
852 ML_BAD_PARAMETER, \
853 "Returning default quaternion"); \
854 } \
855 else{ \
856 /* Yes, set return code, retVal is left on default. */ \
857 *isError = true; \
858 } \
859 } \
860 else{ \
861 /* Define return values. */ \
862 if (isError != NULL){ *isError = false; } \
863 retVal = CALC_EXPR; \
864 } \
865 } \
866 return retVal; \
867
868
869
871 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arcsinh());
875
877 TQuaternion<DT> arcsin(bool *isError=nullptr) const
878 {
880 }
881 #undef _ML_QUAT_CALC_EXP
882
883
884
886 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(arccosh());
888 TQuaternion<DT> arccos(bool *isError=nullptr) const
889 {
891 }
892 #undef _ML_QUAT_CALC_EXP
893
894
895
897 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arctanh());
899 TQuaternion<DT> arctan(bool *isError=nullptr) const
900 {
902 }
903 #undef _ML_QUAT_CALC_EXP
904
905
906 // Undefines _ML_QUATERNION_CALC_CHECKED, it is not needed anymore.
907 #undef _ML_QUATERNION_CALC_CHECKED
908};
909
910
911//-----------------------------------------------------------------------------------
914//-----------------------------------------------------------------------------------
917
920
923
927
928
930
931
932
933
934//-------------------------------------------------------------------------
941//-------------------------------------------------------------------------
942#ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
943#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
945#endif
946
947//-----------------------------
948// Addition
949//-----------------------------
951template <typename DT>
952inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
953 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
954}
955
957template <typename DT>
958inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
959 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
960}
961
963template <typename DT>
964inline ML_LA_NAMESPACE::TQuaternion<DT> operator+(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
965 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
966 return qa.operator+(qb);
967}
968
969
970
971//-----------------------------
972// Subtraction
973//-----------------------------
975template <typename DT>
976inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
977 return ML_LA_NAMESPACE::TQuaternion<DT>(-q.qx, -q.qy, -q.qz, d-q.qw);
978}
979
981template <typename DT>
982inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
983 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw-d);
984}
985
987template <typename DT>
988inline ML_LA_NAMESPACE::TQuaternion<DT> operator-(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
989 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
990 return qa.operator-(qb);
991}
992
993
995template <typename DT>
996inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(DT d, const ML_LA_NAMESPACE::TQuaternion<DT> &q){
997 return q.mult(d);
998}
999
1001template <typename DT>
1002inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
1003 return q.mult(d);
1004}
1005
1007template <typename DT>
1008inline ML_LA_NAMESPACE::TQuaternion<DT> operator*(const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
1009 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
1010 return qa.operator*(qb);
1011}
1013
1014#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1016#endif
1017
1018#endif // _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
1019
1020
1021
1022//-------------------------------------------------------------------------
1029//-------------------------------------------------------------------------
1030#ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1031#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1033#endif
1034
1037#ifdef _ML_IMPLEMENT_QUATERNION_SQRT
1038template <typename DT>
1039inline ML_LA_NAMESPACE::TQuaternion<DT> sqrt (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sqrt(); }
1040#endif
1041
1043template <typename DT>
1044inline ML_LA_NAMESPACE::TQuaternion<DT> exp (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.exp(); }
1045
1047template <typename DT>
1048inline ML_LA_NAMESPACE::TQuaternion<DT> ln (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.ln(); }
1049
1051template <typename DT>
1052inline ML_LA_NAMESPACE::TQuaternion<DT> sin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sin(); }
1053
1055template <typename DT>
1056inline ML_LA_NAMESPACE::TQuaternion<DT> cos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cos(); }
1057
1059template <typename DT>
1060inline ML_LA_NAMESPACE::TQuaternion<DT> tan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tan(); }
1061
1063template <typename DT>
1064inline ML_LA_NAMESPACE::TQuaternion<DT> cotan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotan(); }
1065
1067template <typename DT>
1068inline ML_LA_NAMESPACE::TQuaternion<DT> sinh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.sinh(); }
1069
1071template <typename DT>
1072inline ML_LA_NAMESPACE::TQuaternion<DT> cosh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cosh(); }
1073
1075template <typename DT>
1076inline ML_LA_NAMESPACE::TQuaternion<DT> tanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.tanh(); }
1077
1079template <typename DT>
1080inline ML_LA_NAMESPACE::TQuaternion<DT> cotanh (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.cotanh(); }
1081
1083template <typename DT>
1084inline ML_LA_NAMESPACE::TQuaternion<DT> arcsinh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsinh(); }
1085
1087template <typename DT>
1088inline ML_LA_NAMESPACE::TQuaternion<DT> arccosh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccosh(); }
1089
1091template <typename DT>
1092inline ML_LA_NAMESPACE::TQuaternion<DT> arctanh(const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctanh(); }
1093
1095template <typename DT>
1096inline ML_LA_NAMESPACE::TQuaternion<DT> arcsin (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arcsin(); }
1097
1099template <typename DT>
1100inline ML_LA_NAMESPACE::TQuaternion<DT> arccos (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arccos(); }
1101
1103template <typename DT>
1104inline ML_LA_NAMESPACE::TQuaternion<DT> arctan (const ML_LA_NAMESPACE::TQuaternion<DT> &q) { return q.arctan(); }
1105
1106
1107#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1109#endif
1110
1111#endif // _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1113
1114
1115//-----------------------------------------------------------------------------------
1116// Stream output for std::ostream and dyadic multiplication of TQuaternion and scalar.
1117//-----------------------------------------------------------------------------------
1118namespace std {
1119
1121 template <typename DT>
1122 inline ostream& operator<<(ostream& s, const ML_NAMESPACE::TQuaternion<DT> &v){
1123 return s << "(" << v.qx << "," << v.qy << "," << v.qz << "," << v.qw << ")";
1124 }
1125
1126}
1127
1128
1129#endif // __mlQuaternion_H
Template class for vector arithmetic with floating point datatypes.
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 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
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 4x4 matrix class consisting of four 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, it returns false.
bool MLValuesAreEqualWOM(MLint8 a, MLint8 b)
Returns true if values a and b are equal; otherwise, it returns false.
#define ML_BAD_PARAMETER
A bad/invalid parameter (or even an inappropriate image) has been passed to a module or an algorithm,...
Definition mlTypeDefs.h:823
#define ML_CHECK_FLOAT(x)
#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.
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 ? 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.