13#ifndef ML_QUATERNION_H
14#define ML_QUATERNION_H
91 qx(0), qy(0), qz(0), qw(0) { }
96 qx(0), qy(0), qz(0), qw(d)
104 template <
typename DT2>
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);
151 qx(v[0]), qy(v[1]), qz(v[2]), qw(w)
210 inline void set(
const DT x,
const DT y,
const DT z,
const DT w)
231 printTemplateError(
"TQuaternion::getAsMat4() const, quaternion is not convertible to 4x4 matrix",
233 "Returning Quaterion");
236 *isConvertible =
false;
255 const DT qxqx = qx*qx;
256 const DT qyqy = qy*qy;
257 const DT qzqz = qz*qz;
259 const DT qxqy = qx*qy;
260 const DT qxqz = qx*qz;
261 const DT qxqw = qx*qw;
263 const DT qyqz = qy*qz;
264 const DT qyqw = qy*qw;
266 const DT qzqw = qz*qw;
268 const DT m11 = 1 - s * (qyqy + qzqz);
269 const DT m12 = s * (qxqy - qzqw);
270 const DT m13 = s * (qxqz + qyqw);
272 const DT m21 = s * (qxqy + qzqw);
273 const DT m22 = 1 - s * (qxqx + qzqz);
274 const DT m23 = s * (qyqz - qxqw);
276 const DT m31 = s * (qxqz - qyqw);
277 const DT m32 = s * (qyqz + qxqw);
278 const DT m33 = 1 - s * (qxqx + qyqy);
302 if (isConvertible){ *isConvertible =
true; }
319 inline DT
operator[](
const size_t i)
const {
return array[i]; }
373 qx/=d; qy/=d; qz/=d; qw/=d;
402 *isError = (b.
qx == 0) ||
409 b.
qy != 0 ? qy/b.
qy : qy,
410 b.
qz != 0 ? qz/b.
qz : qz,
411 b.
qw != 0 ? qw/b.
qw : qw) :
448 qw*p.
qw - qx*p.
qx - qy*p.
qy - qz*p.
qz); }
473 if (isError ==
nullptr){
477 "Returning unchanged quaternion");
478 retVal.
set(qx,qy,qz,qw);
483 retVal.
set(qx,qy,qz,qw);
487 if (isError !=
nullptr){ *isError =
false; }
513 inline DT
norm()
const {
return qx*qx + qy*qy + qz*qz + qw*qw; }
518 inline DT
norm2()
const {
return static_cast<DT
>(
::sqrt(qx*qx + qy*qy + qz*qz + qw*qw)); }
535 if (isError ==
nullptr){
539 "Returning default quaternion");
548 if (isError){ *isError =
false; }
549 retVal.
set(qx/n, qy/n, qz/n, qw/n);
568 if (isError ==
nullptr){
572 "Returning default quaternion");
581 if (isError !=
nullptr){ *isError =
false; }
595 const DT absVal = absoluteValue();
596 if (isError !=
nullptr){
604 retVal = *
this / absVal;
610 retVal = *
this / absVal;
626 if (isInvertible==
nullptr){
629 "Returning default quaternion");
632 *isInvertible =
false;
637 if (isInvertible !=
nullptr){ *isInvertible =
true; }
638 retVal = conjugate().
mult(1/n);
653 const DT n2 = norm2();
654 const DT lqv = qv().length();
657 if (isError ==
nullptr){
659 printTemplateError(
"TQuaternion::sqrt() const, sqrt of quaternion cannot be calculated",
661 "Returning default quaternion");
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)));
675 if (isError !=
nullptr){ *isError =
false; }
690 const DT len = qv().length();
706 const DT n2 = norm2();
707 const DT qvLen = qv().length();
709 retVal.
set(0, 0, 0, log10(n2));
713 retVal.
set(qv()/qvLen *
static_cast<DT
>(acos(qw/n2)), log10(n2));
732 const DT len = v.
length();
736 static_cast<DT
>(::cos(qw)) * v / len *
static_cast<DT
>(::sinh(len)) :
738 ::sin(qw)*::cosh(len)
748 const DT len = v.
length();
752 static_cast<DT
>(-1)*
static_cast<DT
>(::sin(qw))*qv()/len*
static_cast<DT
>(::sinh(len)) :
754 ::cos(qw)*::cosh(len)
776 const DT len = v.
length();
780 static_cast<DT
>(::cosh(qw))*v/len*
static_cast<DT
>(::sin(len)) :
782 ::sinh(qw)*::cos(len)
792 const DT len = v.
length();
796 static_cast<DT
>(::sinh(qw))*v/len*
static_cast<DT
>(::sin(len)) :
798 ::cosh(qw)*::cos(len)
806 return sinh().div(cosh(), isError);
812 return cosh().div(sinh(), isError);
840 #define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR) \
841 TQuaternion<DT> retVal; \
843 const Tvec3<DT> &v = qv(); \
844 const DT len = v.length(); \
845 if (MLValueIs0WOM(len)){ \
847 if (isError == NULL){ \
849 printTemplateError("TQuaternion::" FUNC_NAME "() const, " FUNC_NAME \
850 " of quaternion cannot be calculated", \
852 "Returning default quaternion"); \
861 if (isError != NULL){ *isError = false; } \
862 retVal = CALC_EXPR; \
870 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arcsinh());
880 #undef _ML_QUAT_CALC_EXP
885 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(arccosh());
891 #undef _ML_QUAT_CALC_EXP
896 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arctanh());
902 #undef _ML_QUAT_CALC_EXP
906 #undef _ML_QUATERNION_CALC_CHECKED
941#ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
942#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
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);
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);
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);
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);
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);
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);
994template <
typename DT>
995inline ML_LA_NAMESPACE::TQuaternion<DT>
operator*(DT d,
const ML_LA_NAMESPACE::TQuaternion<DT> &q){
1000template <
typename DT>
1001inline ML_LA_NAMESPACE::TQuaternion<DT>
operator*(
const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
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);
1013#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1029#ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1030#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1031ML_LA_START_NAMESPACE
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(); }
1042template <
typename DT>
1043inline ML_LA_NAMESPACE::TQuaternion<DT>
exp (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.exp(); }
1046template <
typename DT>
1047inline ML_LA_NAMESPACE::TQuaternion<DT> ln (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.ln(); }
1050template <
typename DT>
1051inline ML_LA_NAMESPACE::TQuaternion<DT> sin (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.sin(); }
1054template <
typename DT>
1055inline ML_LA_NAMESPACE::TQuaternion<DT> cos (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.cos(); }
1058template <
typename DT>
1059inline ML_LA_NAMESPACE::TQuaternion<DT> tan (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.tan(); }
1062template <
typename DT>
1063inline ML_LA_NAMESPACE::TQuaternion<DT> cotan (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.cotan(); }
1066template <
typename DT>
1067inline ML_LA_NAMESPACE::TQuaternion<DT> sinh (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.sinh(); }
1070template <
typename DT>
1071inline ML_LA_NAMESPACE::TQuaternion<DT> cosh (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.cosh(); }
1074template <
typename DT>
1075inline ML_LA_NAMESPACE::TQuaternion<DT> tanh (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.tanh(); }
1078template <
typename DT>
1079inline ML_LA_NAMESPACE::TQuaternion<DT> cotanh (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.cotanh(); }
1082template <
typename DT>
1083inline ML_LA_NAMESPACE::TQuaternion<DT> arcsinh(
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arcsinh(); }
1086template <
typename DT>
1087inline ML_LA_NAMESPACE::TQuaternion<DT> arccosh(
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arccosh(); }
1090template <
typename DT>
1091inline ML_LA_NAMESPACE::TQuaternion<DT> arctanh(
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arctanh(); }
1094template <
typename DT>
1095inline ML_LA_NAMESPACE::TQuaternion<DT> arcsin (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arcsin(); }
1098template <
typename DT>
1099inline ML_LA_NAMESPACE::TQuaternion<DT> arccos (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arccos(); }
1102template <
typename DT>
1103inline ML_LA_NAMESPACE::TQuaternion<DT> arctan (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arctan(); }
1106#ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
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 <<
")";
Template class for vector arithmetic with floating point datatypes.
T length() const
Returns the length of the vector, i.e., norm2().
FloatingPointVector< T, 3, DataContainer > cross(const FloatingPointVector< T, 3, DataContainer > &b) const
Returns the cross product for elements, i.e., the returned vector is orthogonal to *this and b.
T dot(const FloatingPointVector< T, size, DataContainer > &buffer) const
Returns the dot product, i.e., sum of all components multiplied with corresponding components of buff...
Declaration of complex type traits.
TQuaternion< DT > arctan(bool *isError=nullptr) const
Inverse tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion(DT d)
Builds a quaternion from a scalar by setting all elements to 0 and qw to the scalar; use explicitly t...
TQuaternion< DT > arccos(bool *isError=nullptr) const
Inverse cosine; for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion< DT > euclideanMult(const TQuaternion< DT > &q) const
Euclidean product of this quaternion with another one (which is non-commutative).
DT dot(const TQuaternion< DT > &p) const
Dot product, equivalent to four component vector dot product.
TQuaternion< DT > arg(bool *isError=nullptr) const
Computes the quaternion argument.
TQuaternion< DT > ln() const
Computes the natural logarithm.
TQuaternion(DT x, DT y, DT z, DT w)
Creates a new TQuaternion with the DT values given.
TQuaternion< DT > arccosh() const
Computes the inverse hyperbolic cosine.
DT qx
First element of imaginary part.
TQuaternion< DT > sinh() const
Hyperbolic functions: Hyperbolic sine, hyperbolic cosine, hyperbolic tangent https://en....
DT absoluteValue() const
Returns the absolute value of a quaternion, which is the scalar quantity that determines the length o...
TQuaternion< DT > tan(bool *isError=nullptr) const
Computes the tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion< DT > add(const TQuaternion< DT > &b) const
Adds another quaternion b to this one and returns the sum.
TQuaternion< DT > tanh(bool *isError=nullptr) const
Computes the hyperbolic tangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > getImaginaryPart() const
Returns a copy of the quaternion's imaginary part.
TQuaternion< DT > sqrt(bool *isError=nullptr) const
Computes the square root of a quaternion.
void set(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, const DT w)
Sets all quaternion elements from a vector and DT parameter.
TQuaternion< DT > div(const TQuaternion< DT > &d, bool *isError=nullptr) const
Divides a quaternion by another quaternion.
TQuaternion< DT > sgn(bool *isError=nullptr) const
Returns the sign of the quaternion.
const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv() const
Returns a constant reference to the quaternion's imaginary part as vector object.
TQuaternion< DT > cotan(bool *isError=nullptr) const
Computes the cotangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv()
Returns a modifiable reference to the quaternion's imaginary part as vector object,...
TQuaternion< DT > sin() const
Trigonometric functions: sine, cosine, tangent, cotangent.
TQuaternion< DT > cosh() const
Computes the hyperbolic cosine.
TQuaternion< DT > arcsin(bool *isError=nullptr) const
Inverse trigonometric functions: Inverse sine, inverse cosine, inverse tangent.
TQuaternion< DT > exp() const
Exponential and logarithmic functions: natural exponential, natural logarithm, power.
TQuaternion< DT > negate() const
Computes the negation.
DT norm() const
Computes the d-norm.
TQuaternion< DT > arctanh() const
Computes the inverse hyperbolic tangent.
TQuaternion< DT > arcsinh() const
Inverse hyperbolic function: arcsinh, arccosh, arctanh.
TQuaternion< DT > mult(const TQuaternion< DT > &q) const
Multiplies this quaternion with another one (which is non-commutative). It is also called Grassman pr...
TQuaternion< DT > compDiv(const TQuaternion< DT > &b, bool *isError=nullptr) const
Divides each component by its corresponding component from b.
TQuaternion()
Standard constructor that is setting all elements to 0.
TQuaternion< DT > inverse(bool *isInvertible=nullptr) const
Computes and returns the inverse.
DT value_type
Scalar type used for qx, qy, qz, and qw.
DT & operator[](const size_t i)
Indexing operator.
Tmat4< DT > getAsMat4(bool *isConvertible=nullptr) const
Converts this quaternion to a 4x4 matrix.
TQuaternion< DT > & operator=(const TQuaternion< DT > &q)
Assignment operator.
TQuaternion< DT > add(DT s) const
Adds a scalar s to the quaternion and returns the sum. It is equivalent to a 'scalar add' of s to the...
void set(const DT x, const DT y, const DT z, const DT w)
Sets all quaternion elements qx, qy, qz, and qw from parameters x, y, z, and w, respectively.
DT norm2() const
Computes the magnitude of the quaternion.
TQuaternion< DT > odd(const TQuaternion< DT > &p) const
Odd product, also known as cross-product or Grassman outer product.
TQuaternion< DT > normalize(bool *isError=nullptr) const
Returns the normalization of the quaternion.
TQuaternion(const TQuaternion< DT2 > &q2)
Copy constructor from another TQuaternion of same or different type.
TQuaternion< DT > conjugate() const
Computes the conjugate.
DT qz
Third element of imaginary part.
TQuaternion< DT > mult(DT s) const
Multiplies this quaternion with a scalar factor s.
TQuaternion(const FloatingPointVector< DT, 4 > &v)
Creates a new TQuaternion from the four-dimensional parameter vector.
TQuaternion< DT > cos() const
Computes the cosine.
DT operator[](const size_t i) const
Constant indexing operator.
TQuaternion< DT > cotanh(bool *isError=nullptr) const
Computes the hyperbolic cotangent; for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion< DT > pow(const TQuaternion< DT > &quat) const
Computes the power of a quaternion.
TQuaternion(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, DT w)
Constructor with a vector and DT parameter.
TQuaternion(const TQuaternion &q2)=default
DT getRealPart() const
Returns a copy of the quaternion's real part, also called scalar() of a quaternion.
DT qy
Second element of imaginary part.
TQuaternion< DT > even(const TQuaternion< DT > &p) const
Even product, also known as Grassman inner product.
TQuaternion< DT > outer(const TQuaternion< DT > &q) const
Euclidean outer product of this quaternion with another one.
A 4x4 matrix class consisting of four row vectors.
void set(const DT val)
Sets all values to val.
Forward declarations to resolve header file dependencies.
Specialized base class for the FloatingPointVectorDataContainerBase.
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,...
#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.
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.
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.
MLEXPORT std::ostream & operator<<(std::ostream &s, const ml::Field &v)
Overloads the operator '<<' for stream output of Field objects.