/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef OD_GEQUATERNION_H #define OD_GEQUATERNION_H /*!DOM*/ #include "Ge/GeExport.h" #include "Ge/GeMatrix3d.h" #include "TD_PackPush.h" /** \details This class represents a rotation quaternion in 3D space. Quaternions provide a convenient mathematical notation for representing orientations and rotations of objects in three dimensions. Quaternions resolve the problem of "gimbal locks". The quaternion consists of 2 components: 1. Component of rotation (WW) 2. Components of rotation axis (XX, YY, ZZ) To define quaternion components, use following formulas:
    WW = cos(angle/2)
    XX = x*sin(angle/2)
    YY = y*sin(angle/2)
    ZZ = z*sin(angle/2)
    
where angle is an angle of desired counter clockwise rotation specified in radians, x, y, z - components of a 3D unit vector that represents axis of rotation. For example, a quaternion that rotates 1.5 radian CCW by the x axis (unit vector(1,0,0)), looks the following way:
        WW            XX             YY             ZZ
    cos(1.5/2)   1*sin(1.5/2)   0*sin(1.5/2)   0*sin(1.5/2)
    
Quaternions can be converted to rotation matrix (OdGeMatrix3d) or vice versa. Note, that there can be an ambiguity in rotation matrix representation. We use Hamilton multiplication convention for OdGeQuaternion. Corresponding C++ library: TD_Ge */ class GE_TOOLKIT_EXPORT OdGeQuaternion { public: /** \details Default constructor for the OdGeQuaternion class. \remarks The default constructor constructs an identity quaternion (1., 0., 0., 0.). */ OdGeQuaternion() : w(1.), x(0.), y(0.), z(0.) {} /** \details Constructor for the OdGeQuaternion class. \param ww [in] The W-component of this quaternion object. \param xx [in] The X-component of this quaternion object. \param yy [in] The Y-component of this quaternion object. \param zz [in] The Z-component of this quaternion object. \remarks Constructs a quaternion with specified components. */ OdGeQuaternion(double ww, double xx, double yy, double zz) : w(ww), x(xx), y(yy), z(zz) {} /** \details Set components for the quaternion and returns a reference to it. \param ww [in] The W-component of this quaternion object. \param xx [in] The X-component of this quaternion object. \param yy [in] The Y-component of this quaternion object. \param zz [in] The Z-component of this quaternion object. */ OdGeQuaternion& set(double ww, double xx, double yy, double zz) { w = ww; x = xx; y = yy; z = zz; return *this; } /** \details Converts passed rotation matrix into the quaternion. \param matrix [in] A 3D matrix that defines components of this quaternion. \remarks Input matrix A must be a rotation matrix, i.e. A^T = A^-1 and det(A) = 1. \returns reference to this OdGeQuaternion object. */ OdGeQuaternion& set(const OdGeMatrix3d& matrix); /** \details Calculates 3D rotation matrix that represents this quaternion. \remarks This quaternion should be normalized, i.e. norm() should be equal to one. \returns OdGeMatrix3d object representing this quaternion. */ OdGeMatrix3d getMatrix() const { OdGeMatrix3d matrix; matrix(0, 0) = w * w + x * x - y * y - z * z; matrix(0, 1) = 2. * (x * y - w * z); matrix(0, 2) = 2. * (w * y + x * z); matrix(1, 0) = 2. * (w * z + x * y); matrix(1, 1) = w * w - x * x + y * y - z * z; matrix(1, 2) = 2. * (y * z - w * x); matrix(2, 0) = 2. * (x * z - w * y); matrix(2, 1) = 2. * (w * x + y * z); matrix(2, 2) = w * w - x * x - y * y + z * z; return matrix; } /** \details Rotates specified 3D point using this quaternion. \param sourcePoint [out] A 3D point that is rotated. \returns rotated 3D point. */ OdGePoint3d rotate(OdGePoint3d& sourcePoint) const { OdGeMatrix3d matrix = getMatrix(); return sourcePoint.transformBy(matrix); } /** \details Rotates specified 3D vector using this quaternion. \param vector [out] A 3D vector that is rotated. \returns rotated 3D vector. */ OdGeVector3d rotate(OdGeVector3d& vector) const { OdGeMatrix3d matrix = getMatrix(); return vector.transformBy(matrix); } /////////////////////////////////////////////////////////////////////////////////////// // DGN special (they use Shuster multiplication convention) /////////////////////////////////////////////////////////////////////////////////////// /** \details Rotates specified 3D point using this quaternion but in the opposite direction. \param sourcePoint [out] A 3D point that is rotated. \returns rotated 3D point. */ OdGePoint3d rotateOpposite(OdGePoint3d& sourcePoint) const { OdGeMatrix3d matrix = getMatrix().transpose(); return sourcePoint.transformBy(matrix); } /** \details Rotates specified 3D vector using this quaternion but in the opposite direction. \param vector [out] A 3D vector that is rotated. \returns rotated 3D vector. */ OdGeVector3d rotateOpposite(OdGeVector3d& vector) const { OdGeMatrix3d matrix = getMatrix().transpose(); return vector.transformBy(matrix); } /////////////////////////////////////////////////////////////////////////////////////// /** \details Returns true if and only if quat is identical to this quaternion, within the specified tolerance. \param quat [in] Quaternion to be compared to this quaternion. \param tol [in] Geometric tolerance. */ bool isEqualTo( const OdGeQuaternion& quat, const OdGeTol& tol = OdGeContext::gTol) const { return fabs(x - quat.x) <= tol.equalVector() && fabs(y - quat.y) <= tol.equalVector() && fabs(z - quat.z) <= tol.equalVector() && fabs(w - quat.w) <= tol.equalVector(); } /** \details Equality operator. Returns true if this quaternion is equal to the input quaternion. \param quat [in] Input quaternion that is checked for equality. */ bool operator ==(const OdGeQuaternion& quat) const { return isEqualTo(quat); } /** \details Inequality operator. Returns true if this quaternion is not equal to the input quaternion. \param quat [in] Input quaternion that is checked for inequality. */ bool operator !=(const OdGeQuaternion& quat) const { return !isEqualTo(quat); } /** \details Multiplication operator for the OdGeQuaternion class. \param scale [in] Input scale factor. \returns A new scaled quaternion. */ OdGeQuaternion operator *( double scale) const { return OdGeQuaternion(w * scale, x * scale, y * scale, z * scale); } /** \details Multiplication operator for the OdGeQuaternion class. \param scale [in] Input scale factor. \returns Reference to this OdGeQuaternion object. \remarks Scales this quaternion by scale factor. */ OdGeQuaternion& operator *=( double scale) { w *= scale; x *= scale; y *= scale; z *= scale; return *this; } /** \details Division operator for the OdGeQuaternion class. \param scale [in] Input scale factor. \returns Quaternion equal to this quaternion divided by the scale factor. */ OdGeQuaternion operator /( double scale) const { return OdGeQuaternion(w / scale, x / scale, y / scale, z / scale); } /** \details Division operator for the OdGeQuaternion class. \param scale [in] Input scale factor. \returns Reference to a quaternion that is divided by the scale factor. */ OdGeQuaternion& operator /=( double scale) { w /= scale; x /= scale; y /= scale; z /= scale; return *this; } /** \details Addition operator for the OdGeQuaternion class. \param quat [in] Input quaternion, component values of which are added to component values of this quaternion. \returns A quaternion with summed components. */ OdGeQuaternion operator +( const OdGeQuaternion& quat) const { return OdGeQuaternion(w + quat.w, x + quat.x, y + quat.y, z + quat.z); } /** \details Addition operator for the OdGeQuaternion class. \param quat [in] A reference to a quaternion, component values of which are added to component values of this quaternion. \returns Reference to a quaternion with summed components. */ OdGeQuaternion& operator +=( const OdGeQuaternion& quat) { w += quat.w; x += quat.x, y += quat.y; z += quat.z; return *this; } /** \details Subtraction operator for the OdGeQuaternion class. \param quat [in] Input quaternion, component values of which are subtracted from component values of this quaternion. \returns A quaternion with subtracted components. */ OdGeQuaternion operator -( const OdGeQuaternion& quat) const { return OdGeQuaternion(w - quat.w, x - quat.x, y - quat.y, z - quat.z); } /** \details Subtraction operator for the OdGeQuaternion class. \param quat [in] A reference to a quaternion, component values of which are subtracted from component values of this quaternion. \returns Reference to a quaternion with subtracted components. */ OdGeQuaternion& operator -=( const OdGeQuaternion& quat) { w -= quat.w; x -= quat.x, y -= quat.y; z -= quat.z; return *this; } /** \details Inverse operator. \remarks Returns a quaternion with inverse component values according to this quaternion. */ OdGeQuaternion operator -() const { return OdGeQuaternion(-w, -x, -y, -z); } /** \details Returns the square of the norm of this quaternion. */ double normSqrd() const { return w*w + x*x + y*y + z*z; } /** \details Returns the norm of this quaternion. */ double norm() const; /** \details Sets this quaternion to the unit quaternion and returns a reference to this quaternion \param tol [in] Geometric tolerance. \remarks If this.norm() <= tol, this quaternion is unchanged. */ OdGeQuaternion& normalize(const OdGeTol& tol = OdGeContext::gTol); /** \details Returns the dot product of this quaternion and the specified quaternion. \param quat [in] Any quaternion to be multiplied with this quaternion. */ double dotProduct(const OdGeQuaternion& quat) const { return w * quat.w + x * quat.x + y * quat.y + z * quat.z; } /** \details Performs spherical linear interpolation, introduced by Ken Shoemake in the context of quaternion interpolation. It refers to constant-speed motion along a unit-radius great circle arc, given the ends and an interpolation parameter between 0 and 1 \param q [in] second quaternion to be interpolated between (first is this quaternion) \param t [in] a scalar between 0.0 (at p) and 1.0 (at q) \param bUseShortestPath [in] boolean that indicates whether to compute quaternions that constitute the shortest possible arc on a four-dimensional unit sphere. */ OdGeQuaternion slerp(OdGeQuaternion& q, double t, bool bUseShortestPath); /** \details Scalar part. */ double w; /** \details First vector part. */ double x; /** \details Second vector part. */ double y; /** \details Third vector part. */ double z; /** \details Identity quaternion (1, 0, 0, 0), i.e. a quaternion that doesn't cause any rotation. */ GE_STATIC_EXPORT static const OdGeQuaternion kIdentity; }; #include "TD_PackPop.h" #endif // OD_GEQUATERNION_H