Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:03:45

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