Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-09 09:15:36

0001 // Created on: 2010-05-11
0002 // Created by: Kirill GAVRILOV
0003 // Copyright (c) 2010-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _gp_Quaternion_HeaderFile
0017 #define _gp_Quaternion_HeaderFile
0018 
0019 #include <gp_EulerSequence.hxx>
0020 #include <gp_Mat.hxx>
0021 #include <gp_Vec.hxx>
0022 
0023 //! Represents operation of rotation in 3d space as quaternion
0024 //! and implements operations with rotations basing on
0025 //! quaternion mathematics.
0026 //!
0027 //! In addition, provides methods for conversion to and from other
0028 //! representations of rotation (3*3 matrix, vector and
0029 //! angle, Euler angles)
0030 class gp_Quaternion
0031 {
0032 public:
0033   DEFINE_STANDARD_ALLOC
0034 
0035   //! Creates an identity quaternion
0036   gp_Quaternion()
0037       : x(0.0),
0038         y(0.0),
0039         z(0.0),
0040         w(1.0)
0041   {
0042   }
0043 
0044   //! Creates quaternion directly from component values
0045   gp_Quaternion(const Standard_Real theX,
0046                 const Standard_Real theY,
0047                 const Standard_Real theZ,
0048                 const Standard_Real theW)
0049       : x(theX),
0050         y(theY),
0051         z(theZ),
0052         w(theW)
0053   {
0054   }
0055 
0056   //! Creates quaternion representing shortest-arc rotation
0057   //! operator producing vector theVecTo from vector theVecFrom.
0058   gp_Quaternion(const gp_Vec& theVecFrom, const gp_Vec& theVecTo)
0059   {
0060     SetRotation(theVecFrom, theVecTo);
0061   }
0062 
0063   //! Creates quaternion representing shortest-arc rotation
0064   //! operator producing vector theVecTo from vector theVecFrom.
0065   //! Additional vector theHelpCrossVec defines preferred direction for
0066   //! rotation and is used when theVecTo and theVecFrom are directed
0067   //! oppositely.
0068   gp_Quaternion(const gp_Vec& theVecFrom, const gp_Vec& theVecTo, const gp_Vec& theHelpCrossVec)
0069   {
0070     SetRotation(theVecFrom, theVecTo, theHelpCrossVec);
0071   }
0072 
0073   //! Creates quaternion representing rotation on angle
0074   //! theAngle around vector theAxis
0075   gp_Quaternion(const gp_Vec& theAxis, const Standard_Real theAngle)
0076   {
0077     SetVectorAndAngle(theAxis, theAngle);
0078   }
0079 
0080   //! Creates quaternion from rotation matrix 3*3
0081   //! (which should be orthonormal skew-symmetric matrix)
0082   gp_Quaternion(const gp_Mat& theMat) { SetMatrix(theMat); }
0083 
0084   //! Simple equal test without precision
0085   Standard_EXPORT Standard_Boolean IsEqual(const gp_Quaternion& theOther) const;
0086 
0087   //! Sets quaternion to shortest-arc rotation producing
0088   //! vector theVecTo from vector theVecFrom.
0089   //! If vectors theVecFrom and theVecTo are opposite then rotation
0090   //! axis is computed as theVecFrom ^ (1,0,0) or theVecFrom ^ (0,0,1).
0091   Standard_EXPORT void SetRotation(const gp_Vec& theVecFrom, const gp_Vec& theVecTo);
0092 
0093   //! Sets quaternion to shortest-arc rotation producing
0094   //! vector theVecTo from vector theVecFrom.
0095   //! If vectors theVecFrom and theVecTo are opposite then rotation
0096   //! axis is computed as theVecFrom ^ theHelpCrossVec.
0097   Standard_EXPORT void SetRotation(const gp_Vec& theVecFrom,
0098                                    const gp_Vec& theVecTo,
0099                                    const gp_Vec& theHelpCrossVec);
0100 
0101   //! Create a unit quaternion from Axis+Angle representation
0102   Standard_EXPORT void SetVectorAndAngle(const gp_Vec& theAxis, const Standard_Real theAngle);
0103 
0104   //! Convert a quaternion to Axis+Angle representation,
0105   //! preserve the axis direction and angle from -PI to +PI
0106   Standard_EXPORT void GetVectorAndAngle(gp_Vec& theAxis, Standard_Real& theAngle) const;
0107 
0108   //! Create a unit quaternion by rotation matrix
0109   //! matrix must contain only rotation (not scale or shear)
0110   //!
0111   //! For numerical stability we find first the greatest component of quaternion
0112   //! and than search others from this one
0113   Standard_EXPORT void SetMatrix(const gp_Mat& theMat);
0114 
0115   //! Returns rotation operation as 3*3 matrix
0116   Standard_EXPORT gp_Mat GetMatrix() const;
0117 
0118   //! Create a unit quaternion representing rotation defined
0119   //! by generalized Euler angles
0120   Standard_EXPORT void SetEulerAngles(const gp_EulerSequence theOrder,
0121                                       const Standard_Real    theAlpha,
0122                                       const Standard_Real    theBeta,
0123                                       const Standard_Real    theGamma);
0124 
0125   //! Returns Euler angles describing current rotation
0126   Standard_EXPORT void GetEulerAngles(const gp_EulerSequence theOrder,
0127                                       Standard_Real&         theAlpha,
0128                                       Standard_Real&         theBeta,
0129                                       Standard_Real&         theGamma) const;
0130 
0131   void Set(const Standard_Real theX,
0132            const Standard_Real theY,
0133            const Standard_Real theZ,
0134            const Standard_Real theW);
0135 
0136   void Set(const gp_Quaternion& theQuaternion);
0137 
0138   Standard_Real X() const { return x; }
0139 
0140   Standard_Real Y() const { return y; }
0141 
0142   Standard_Real Z() const { return z; }
0143 
0144   Standard_Real W() const { return w; }
0145 
0146   //! Make identity quaternion (zero-rotation)
0147   void SetIdent()
0148   {
0149     x = y = z = 0.0;
0150     w         = 1.0;
0151   }
0152 
0153   //! Reverse direction of rotation (conjugate quaternion)
0154   void Reverse()
0155   {
0156     x = -x;
0157     y = -y;
0158     z = -z;
0159   }
0160 
0161   //! Return rotation with reversed direction (conjugated quaternion)
0162   Standard_NODISCARD gp_Quaternion Reversed() const { return gp_Quaternion(-x, -y, -z, w); }
0163 
0164   //! Inverts quaternion (both rotation direction and norm)
0165   void Invert()
0166   {
0167     Standard_Real anIn = 1.0 / SquareNorm();
0168     Set(-x * anIn, -y * anIn, -z * anIn, w * anIn);
0169   }
0170 
0171   //! Return inversed quaternion q^-1
0172   Standard_NODISCARD gp_Quaternion Inverted() const
0173   {
0174     Standard_Real anIn = 1.0 / SquareNorm();
0175     return gp_Quaternion(-x * anIn, -y * anIn, -z * anIn, w * anIn);
0176   }
0177 
0178   //! Returns square norm of quaternion
0179   Standard_Real SquareNorm() const { return x * x + y * y + z * z + w * w; }
0180 
0181   //! Returns norm of quaternion
0182   Standard_Real Norm() const { return Sqrt(SquareNorm()); }
0183 
0184   //! Scale all components by quaternion by theScale; note that
0185   //! rotation is not changed by this operation (except 0-scaling)
0186   void Scale(const Standard_Real theScale);
0187 
0188   void operator*=(const Standard_Real theScale) { Scale(theScale); }
0189 
0190   //! Returns scaled quaternion
0191   Standard_NODISCARD gp_Quaternion Scaled(const Standard_Real theScale) const
0192   {
0193     return gp_Quaternion(x * theScale, y * theScale, z * theScale, w * theScale);
0194   }
0195 
0196   Standard_NODISCARD gp_Quaternion operator*(const Standard_Real theScale) const
0197   {
0198     return Scaled(theScale);
0199   }
0200 
0201   //! Stabilize quaternion length within 1 - 1/4.
0202   //! This operation is a lot faster than normalization
0203   //! and preserve length goes to 0 or infinity
0204   Standard_EXPORT void StabilizeLength();
0205 
0206   //! Scale quaternion that its norm goes to 1.
0207   //! The appearing of 0 magnitude or near is a error,
0208   //! so we can be sure that can divide by magnitude
0209   Standard_EXPORT void Normalize();
0210 
0211   //! Returns quaternion scaled so that its norm goes to 1.
0212   Standard_NODISCARD gp_Quaternion Normalized() const
0213   {
0214     gp_Quaternion aNormilizedQ(*this);
0215     aNormilizedQ.Normalize();
0216     return aNormilizedQ;
0217   }
0218 
0219   //! Returns quaternion with all components negated.
0220   //! Note that this operation does not affect neither
0221   //! rotation operator defined by quaternion nor its norm.
0222   Standard_NODISCARD gp_Quaternion Negated() const { return gp_Quaternion(-x, -y, -z, -w); }
0223 
0224   Standard_NODISCARD gp_Quaternion operator-() const { return Negated(); }
0225 
0226   //! Makes sum of quaternion components; result is "rotations mix"
0227   Standard_NODISCARD gp_Quaternion Added(const gp_Quaternion& theOther) const
0228   {
0229     return gp_Quaternion(x + theOther.x, y + theOther.y, z + theOther.z, w + theOther.w);
0230   }
0231 
0232   Standard_NODISCARD gp_Quaternion operator+(const gp_Quaternion& theOther) const
0233   {
0234     return Added(theOther);
0235   }
0236 
0237   //! Makes difference of quaternion components; result is "rotations mix"
0238   Standard_NODISCARD gp_Quaternion Subtracted(const gp_Quaternion& theOther) const
0239   {
0240     return gp_Quaternion(x - theOther.x, y - theOther.y, z - theOther.z, w - theOther.w);
0241   }
0242 
0243   Standard_NODISCARD gp_Quaternion operator-(const gp_Quaternion& theOther) const
0244   {
0245     return Subtracted(theOther);
0246   }
0247 
0248   //! Multiply function - work the same as Matrices multiplying.
0249   //! @code
0250   //! qq' = (cross(v,v') + wv' + w'v, ww' - dot(v,v'))
0251   //! @endcode
0252   //! Result is rotation combination: q' than q (here q=this, q'=theQ).
0253   //! Notices that:
0254   //! @code
0255   //! qq' != q'q;
0256   //! qq^-1 = q;
0257   //! @endcode
0258   Standard_NODISCARD gp_Quaternion Multiplied(const gp_Quaternion& theOther) const;
0259 
0260   Standard_NODISCARD gp_Quaternion operator*(const gp_Quaternion& theOther) const
0261   {
0262     return Multiplied(theOther);
0263   }
0264 
0265   //! Adds components of other quaternion; result is "rotations mix"
0266   void Add(const gp_Quaternion& theOther);
0267 
0268   void operator+=(const gp_Quaternion& theOther) { Add(theOther); }
0269 
0270   //! Subtracts components of other quaternion; result is "rotations mix"
0271   void Subtract(const gp_Quaternion& theOther);
0272 
0273   void operator-=(const gp_Quaternion& theOther) { Subtract(theOther); }
0274 
0275   //! Adds rotation by multiplication
0276   void Multiply(const gp_Quaternion& theOther)
0277   {
0278     (*this) = Multiplied(theOther); // have no optimization here
0279   }
0280 
0281   void operator*=(const gp_Quaternion& theOther) { Multiply(theOther); }
0282 
0283   //! Computes inner product / scalar product / Dot
0284   Standard_Real Dot(const gp_Quaternion& theOther) const
0285   {
0286     return x * theOther.x + y * theOther.y + z * theOther.z + w * theOther.w;
0287   }
0288 
0289   //! Return rotation angle from -PI to PI
0290   Standard_EXPORT Standard_Real GetRotationAngle() const;
0291 
0292   //! Rotates vector by quaternion as rotation operator
0293   Standard_EXPORT gp_Vec Multiply(const gp_Vec& theVec) const;
0294 
0295   gp_Vec operator*(const gp_Vec& theVec) const { return Multiply(theVec); }
0296 
0297 private:
0298   Standard_Real x;
0299   Standard_Real y;
0300   Standard_Real z;
0301   Standard_Real w;
0302 };
0303 
0304 //=======================================================================
0305 // function : Set
0306 // purpose  :
0307 //=======================================================================
0308 inline void gp_Quaternion::Set(Standard_Real theX,
0309                                Standard_Real theY,
0310                                Standard_Real theZ,
0311                                Standard_Real theW)
0312 {
0313   this->x = theX;
0314   this->y = theY;
0315   this->z = theZ;
0316   this->w = theW;
0317 }
0318 
0319 //=======================================================================
0320 // function : Set
0321 // purpose  :
0322 //=======================================================================
0323 inline void gp_Quaternion::Set(const gp_Quaternion& theQuaternion)
0324 {
0325   x = theQuaternion.x;
0326   y = theQuaternion.y;
0327   z = theQuaternion.z;
0328   w = theQuaternion.w;
0329 }
0330 
0331 //=======================================================================
0332 // function : Scale
0333 // purpose  :
0334 //=======================================================================
0335 inline void gp_Quaternion::Scale(const Standard_Real theScale)
0336 {
0337   x *= theScale;
0338   y *= theScale;
0339   z *= theScale;
0340   w *= theScale;
0341 }
0342 
0343 //=======================================================================
0344 // function : Multiplied
0345 // purpose  :
0346 //=======================================================================
0347 inline gp_Quaternion gp_Quaternion::Multiplied(const gp_Quaternion& theQ) const
0348 {
0349   return gp_Quaternion(w * theQ.x + x * theQ.w + y * theQ.z - z * theQ.y,
0350                        w * theQ.y + y * theQ.w + z * theQ.x - x * theQ.z,
0351                        w * theQ.z + z * theQ.w + x * theQ.y - y * theQ.x,
0352                        w * theQ.w - x * theQ.x - y * theQ.y - z * theQ.z);
0353   // 16 multiplications    12 addidtions    0 variables
0354 }
0355 
0356 //=======================================================================
0357 // function : Add
0358 // purpose  :
0359 //=======================================================================
0360 inline void gp_Quaternion::Add(const gp_Quaternion& theQ)
0361 {
0362   x += theQ.x;
0363   y += theQ.y;
0364   z += theQ.z;
0365   w += theQ.w;
0366 }
0367 
0368 //=======================================================================
0369 // function : Subtract
0370 // purpose  :
0371 //=======================================================================
0372 inline void gp_Quaternion::Subtract(const gp_Quaternion& theQ)
0373 {
0374   x -= theQ.x;
0375   y -= theQ.y;
0376   z -= theQ.z;
0377   w -= theQ.w;
0378 }
0379 
0380 #endif // _gp_Quaternion_HeaderFile