Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (c) 1991-1999 Matra Datavision
0002 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014 
0015 #ifndef _gp_Dir_HeaderFile
0016 #define _gp_Dir_HeaderFile
0017 
0018 #include <gp_XYZ.hxx>
0019 #include <Standard_ConstructionError.hxx>
0020 #include <Standard_DomainError.hxx>
0021 #include <Standard_OutOfRange.hxx>
0022 
0023 class gp_Vec;
0024 class gp_Ax1;
0025 class gp_Ax2;
0026 class gp_Trsf;
0027 
0028 //! Describes a unit vector in 3D space. This unit vector is also called "Direction".
0029 //! See Also
0030 //! gce_MakeDir which provides functions for more complex
0031 //! unit vector constructions
0032 //! Geom_Direction which provides additional functions for
0033 //! constructing unit vectors and works, in particular, with the
0034 //! parametric equations of unit vectors.
0035 class gp_Dir
0036 {
0037 public:
0038   //! Standard directions in 3D space for optimized constexpr construction
0039   enum class D
0040   {
0041     X,  //!< Direction along positive X axis (1, 0, 0)
0042     Y,  //!< Direction along positive Y axis (0, 1, 0)
0043     Z,  //!< Direction along positive Z axis (0, 0, 1)
0044     NX, //!< Direction along negative X axis (-1, 0, 0)
0045     NY, //!< Direction along negative Y axis (0, -1, 0)
0046     NZ  //!< Direction along negative Z axis (0, 0, -1)
0047   };
0048 
0049   DEFINE_STANDARD_ALLOC
0050 
0051   //! Creates a direction corresponding to X axis.
0052   constexpr gp_Dir() noexcept
0053       : coord(1., 0., 0.)
0054   {
0055   }
0056 
0057   //! Creates a direction from a standard direction enumeration.
0058   constexpr explicit gp_Dir(const D theDir) noexcept
0059       : coord(theDir == D::X    ? 1.0
0060               : theDir == D::NX ? -1.0
0061                                 : 0.0,
0062               theDir == D::Y    ? 1.0
0063               : theDir == D::NY ? -1.0
0064                                 : 0.0,
0065               theDir == D::Z    ? 1.0
0066               : theDir == D::NZ ? -1.0
0067                                 : 0.0)
0068   {
0069   }
0070 
0071   //! Normalizes the vector theV and creates a direction. Raises ConstructionError if
0072   //! theV.Magnitude() <= Resolution.
0073   //! @note Constexpr-compatible when input is already normalized.
0074   constexpr gp_Dir(const gp_Vec& theV);
0075 
0076   //! Creates a direction from a triplet of coordinates. Raises ConstructionError if
0077   //! theCoord.Modulus() <= Resolution from gp.
0078   //! @note Constexpr-compatible when input is already normalized.
0079   constexpr gp_Dir(const gp_XYZ& theCoord);
0080 
0081   //! Creates a direction with its 3 cartesian coordinates. Raises ConstructionError if
0082   //! std::sqrt(theXv*theXv + theYv*theYv + theZv*theZv) <= Resolution Modification of the
0083   //! direction's coordinates If std::sqrt (theXv*theXv + theYv*theYv + theZv*theZv) <= Resolution
0084   //! from gp where theXv, theYv ,theZv are the new coordinates it is not possible to construct the
0085   //! direction and the method raises the exception ConstructionError.
0086   //! @note Constexpr-compatible when input is already normalized.
0087   constexpr gp_Dir(const double theXv, const double theYv, const double theZv);
0088 
0089   constexpr gp_Dir(const gp_Dir&) noexcept = default;
0090   constexpr gp_Dir(gp_Dir&&) noexcept      = default;
0091 
0092   constexpr gp_Dir& operator=(const gp_Dir&) noexcept = default;
0093   constexpr gp_Dir& operator=(gp_Dir&&) noexcept      = default;
0094 
0095   //! For this unit vector, assigns the value Xi to:
0096   //! -   the X coordinate if theIndex is 1, or
0097   //! -   the Y coordinate if theIndex is 2, or
0098   //! -   the Z coordinate if theIndex is 3,
0099   //! and then normalizes it.
0100   //! Warning:
0101   //! Remember that all the coordinates of a unit vector are
0102   //! implicitly modified when any single one is changed directly.
0103   //! Exceptions
0104   //! Standard_OutOfRange if theIndex is not 1, 2, or 3.
0105   //! Standard_ConstructionError if either of the following
0106   //! is less than or equal to gp::Resolution():
0107   //! -   std::sqrt(Xv*Xv + Yv*Yv + Zv*Zv), or
0108   //! -   the modulus of the number triple formed by the new
0109   //! value theXi and the two other coordinates of this vector
0110   //! that were not directly modified.
0111   //! @note Constexpr-compatible when result is already normalized.
0112   constexpr void SetCoord(const int theIndex, const double theXi);
0113 
0114   //! For this unit vector, assigns the values theXv, theYv and theZv to its three coordinates.
0115   //! Remember that all the coordinates of a unit vector are
0116   //! implicitly modified when any single one is changed directly.
0117   //! @note Constexpr-compatible when input is already normalized.
0118   constexpr void SetCoord(const double theXv, const double theYv, const double theZv);
0119 
0120   //! Assigns the given value to the X coordinate of this unit vector.
0121   //! @note Constexpr-compatible when result is already normalized.
0122   constexpr void SetX(const double theX);
0123 
0124   //! Assigns the given value to the Y coordinate of this unit vector.
0125   //! @note Constexpr-compatible when result is already normalized.
0126   constexpr void SetY(const double theY);
0127 
0128   //! Assigns the given value to the Z coordinate of this unit vector.
0129   //! @note Constexpr-compatible when result is already normalized.
0130   constexpr void SetZ(const double theZ);
0131 
0132   //! Assigns the three coordinates of theCoord to this unit vector.
0133   //! @note Constexpr-compatible when input is already normalized.
0134   constexpr void SetXYZ(const gp_XYZ& theCoord);
0135 
0136   //! Returns the coordinate of range theIndex :
0137   //! theIndex = 1 => X is returned
0138   //! theIndex = 2 => Y is returned
0139   //! theIndex = 3 => Z is returned
0140   //! Exceptions
0141   //! Standard_OutOfRange if theIndex is not 1, 2, or 3.
0142   constexpr double Coord(const int theIndex) const { return coord.Coord(theIndex); }
0143 
0144   //! Returns for the unit vector its three coordinates theXv, theYv, and theZv.
0145   constexpr void Coord(double& theXv, double& theYv, double& theZv) const noexcept
0146   {
0147     coord.Coord(theXv, theYv, theZv);
0148   }
0149 
0150   //! Returns the X coordinate for a unit vector.
0151   constexpr double X() const noexcept { return coord.X(); }
0152 
0153   //! Returns the Y coordinate for a unit vector.
0154   constexpr double Y() const noexcept { return coord.Y(); }
0155 
0156   //! Returns the Z coordinate for a unit vector.
0157   constexpr double Z() const noexcept { return coord.Z(); }
0158 
0159   //! for this unit vector, returns its three coordinates as a number triple.
0160   constexpr const gp_XYZ& XYZ() const noexcept { return coord; }
0161 
0162   //! Returns True if the angle between the two directions is
0163   //! lower or equal to theAngularTolerance.
0164   bool IsEqual(const gp_Dir& theOther, const double theAngularTolerance) const
0165   {
0166     return Angle(theOther) <= theAngularTolerance;
0167   }
0168 
0169   //! Returns True if the angle between this unit vector and the unit vector theOther is equal to
0170   //! Pi/2 (normal).
0171   bool IsNormal(const gp_Dir& theOther, const double theAngularTolerance) const
0172   {
0173     double anAng = M_PI / 2.0 - Angle(theOther);
0174     if (anAng < 0)
0175     {
0176       anAng = -anAng;
0177     }
0178     return anAng <= theAngularTolerance;
0179   }
0180 
0181   //! Returns True if the angle between this unit vector and the unit vector theOther is equal to
0182   //! Pi (opposite).
0183   bool IsOpposite(const gp_Dir& theOther, const double theAngularTolerance) const
0184   {
0185     return M_PI - Angle(theOther) <= theAngularTolerance;
0186   }
0187 
0188   //! Returns true if the angle between this unit vector and the
0189   //! unit vector theOther is equal to 0 or to Pi.
0190   //! Note: the tolerance criterion is given by theAngularTolerance.
0191   bool IsParallel(const gp_Dir& theOther, const double theAngularTolerance) const
0192   {
0193     double anAng = Angle(theOther);
0194     return anAng <= theAngularTolerance || M_PI - anAng <= theAngularTolerance;
0195   }
0196 
0197   //! Computes the angular value in radians between <me> and
0198   //! <theOther>. This value is always positive in 3D space.
0199   //! Returns the angle in the range [0, PI]
0200   Standard_EXPORT double Angle(const gp_Dir& theOther) const;
0201 
0202   //! Computes the angular value between <me> and <theOther>.
0203   //! <theVRef> is the direction of reference normal to <me> and <theOther>
0204   //! and its orientation gives the positive sense of rotation.
0205   //! If the cross product <me> ^ <theOther> has the same orientation
0206   //! as <theVRef> the angular value is positive else negative.
0207   //! Returns the angular value in the range -PI and PI (in radians). Raises DomainError if <me>
0208   //! and <theOther> are not parallel this exception is raised when <theVRef> is in the same plane
0209   //! as <me> and <theOther> The tolerance criterion is Resolution from package gp.
0210   Standard_EXPORT double AngleWithRef(const gp_Dir& theOther, const gp_Dir& theVRef) const;
0211 
0212   //! Computes the cross product between two directions
0213   //! Raises the exception ConstructionError if the two directions
0214   //! are parallel because the computed vector cannot be normalized
0215   //! to create a direction.
0216   //! @note Constexpr-compatible when result is already normalized.
0217   constexpr void Cross(const gp_Dir& theRight);
0218 
0219   constexpr void operator^=(const gp_Dir& theRight) { Cross(theRight); }
0220 
0221   //! Computes the triple vector product.
0222   //! <me> ^ (V1 ^ V2)
0223   //! Raises the exception ConstructionError if V1 and V2 are parallel
0224   //! or <me> and (V1^V2) are parallel because the computed vector
0225   //! can't be normalized to create a direction.
0226   //! @note Constexpr-compatible when result is already normalized.
0227   [[nodiscard]] constexpr gp_Dir Crossed(const gp_Dir& theRight) const;
0228 
0229   [[nodiscard]] constexpr gp_Dir operator^(const gp_Dir& theRight) const
0230   {
0231     return Crossed(theRight);
0232   }
0233 
0234   //! @note Constexpr-compatible when result is already normalized.
0235   constexpr void CrossCross(const gp_Dir& theV1, const gp_Dir& theV2);
0236 
0237   //! Computes the double vector product this ^ (theV1 ^ theV2).
0238   //! -   CrossCrossed creates a new unit vector.
0239   //! Exceptions
0240   //! Standard_ConstructionError if:
0241   //! -   theV1 and theV2 are parallel, or
0242   //! -   this unit vector and (theV1 ^ theV2) are parallel.
0243   //! This is because, in these conditions, the computed vector
0244   //! is null and cannot be normalized.
0245   //! @note Constexpr-compatible when result is already normalized.
0246   [[nodiscard]] constexpr gp_Dir CrossCrossed(const gp_Dir& theV1, const gp_Dir& theV2) const;
0247 
0248   //! Computes the scalar product
0249   constexpr double Dot(const gp_Dir& theOther) const noexcept { return coord.Dot(theOther.coord); }
0250 
0251   constexpr double operator*(const gp_Dir& theOther) const noexcept { return Dot(theOther); }
0252 
0253   //! Computes the triple scalar product <me> * (theV1 ^ theV2).
0254   //! Warnings :
0255   //! The computed vector theV1' = theV1 ^ theV2 is not normalized
0256   //! to create a unitary vector. So this method never
0257   //! raises an exception even if theV1 and theV2 are parallel.
0258   constexpr double DotCross(const gp_Dir& theV1, const gp_Dir& theV2) const noexcept
0259   {
0260     return coord.Dot(theV1.coord.Crossed(theV2.coord));
0261   }
0262 
0263   constexpr void Reverse() noexcept { coord.Reverse(); }
0264 
0265   //! Reverses the orientation of a direction
0266   //! geometric transformations
0267   //! Performs the symmetrical transformation of a direction
0268   //! with respect to the direction V which is the center of
0269   //! the symmetry.
0270   [[nodiscard]] constexpr gp_Dir Reversed() const noexcept
0271   {
0272     gp_Dir aV = *this;
0273     aV.coord.Reverse();
0274     return aV;
0275   }
0276 
0277   [[nodiscard]] constexpr gp_Dir operator-() const noexcept { return Reversed(); }
0278 
0279   Standard_EXPORT void Mirror(const gp_Dir& theV) noexcept;
0280 
0281   //! Performs the symmetrical transformation of a direction
0282   //! with respect to the direction theV which is the center
0283   //! of the symmetry.
0284   [[nodiscard]] Standard_EXPORT gp_Dir Mirrored(const gp_Dir& theV) const noexcept;
0285 
0286   Standard_EXPORT void Mirror(const gp_Ax1& theA1) noexcept;
0287 
0288   //! Performs the symmetrical transformation of a direction
0289   //! with respect to an axis placement which is the axis
0290   //! of the symmetry.
0291   [[nodiscard]] Standard_EXPORT gp_Dir Mirrored(const gp_Ax1& theA1) const noexcept;
0292 
0293   Standard_EXPORT void Mirror(const gp_Ax2& theA2) noexcept;
0294 
0295   //! Performs the symmetrical transformation of a direction
0296   //! with respect to a plane. The axis placement theA2 locates
0297   //! the plane of the symmetry : (Location, XDirection, YDirection).
0298   [[nodiscard]] Standard_EXPORT gp_Dir Mirrored(const gp_Ax2& theA2) const noexcept;
0299 
0300   void Rotate(const gp_Ax1& theA1, const double theAng);
0301 
0302   //! Rotates a direction. theA1 is the axis of the rotation.
0303   //! theAng is the angular value of the rotation in radians.
0304   [[nodiscard]] gp_Dir Rotated(const gp_Ax1& theA1, const double theAng) const
0305   {
0306     gp_Dir aV = *this;
0307     aV.Rotate(theA1, theAng);
0308     return aV;
0309   }
0310 
0311   Standard_EXPORT void Transform(const gp_Trsf& theT);
0312 
0313   //! Transforms a direction with a "Trsf" from gp.
0314   //! Warnings :
0315   //! If the scale factor of the "Trsf" theT is negative then the
0316   //! direction <me> is reversed.
0317   [[nodiscard]] gp_Dir Transformed(const gp_Trsf& theT) const
0318   {
0319     gp_Dir aV = *this;
0320     aV.Transform(theT);
0321     return aV;
0322   }
0323 
0324   //! Dumps the content of me into the stream
0325   Standard_EXPORT void DumpJson(Standard_OStream& theOStream, int theDepth = -1) const;
0326 
0327   //! Inits the content of me from the stream
0328   Standard_EXPORT bool InitFromJson(const Standard_SStream& theSStream, int& theStreamPos);
0329 
0330 private:
0331   gp_XYZ coord;
0332 };
0333 
0334 #include <gp_Trsf.hxx>
0335 
0336 //=================================================================================================
0337 
0338 inline constexpr gp_Dir::gp_Dir(const gp_Vec& theV)
0339     : gp_Dir(theV.XYZ())
0340 {
0341 }
0342 
0343 //=================================================================================================
0344 
0345 inline constexpr gp_Dir::gp_Dir(const gp_XYZ& theXYZ)
0346     : gp_Dir(theXYZ.X(), theXYZ.Y(), theXYZ.Z())
0347 {
0348 }
0349 
0350 //=================================================================================================
0351 
0352 inline constexpr gp_Dir::gp_Dir(const double theXv, const double theYv, const double theZv)
0353 {
0354   const double aSqMod = theXv * theXv + theYv * theYv + theZv * theZv;
0355 
0356   // Fast path: already normalized - fully constexpr
0357   if (aSqMod >= (1.0 - gp::Resolution()) && aSqMod <= (1.0 + gp::Resolution()))
0358   {
0359     coord.SetCoord(theXv, theYv, theZv);
0360     return;
0361   }
0362 
0363   // Slow path: runtime only (sqrt not constexpr - compile error if reached in constexpr context)
0364   Standard_ConstructionError_Raise_if(aSqMod <= gp::Resolution() * gp::Resolution(),
0365                                       "gp_Dir() - input vector has zero norm");
0366   const double aD = sqrt(aSqMod);
0367   coord.SetCoord(theXv / aD, theYv / aD, theZv / aD);
0368 }
0369 
0370 //=================================================================================================
0371 
0372 inline constexpr void gp_Dir::SetCoord(const int theIndex, const double theXi)
0373 {
0374   Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > 3,
0375                                "gp_Dir::SetCoord() - index is out of range [1, 3]");
0376   if (theIndex == 1)
0377   {
0378     SetX(theXi);
0379   }
0380   else if (theIndex == 2)
0381   {
0382     SetY(theXi);
0383   }
0384   else
0385   {
0386     SetZ(theXi);
0387   }
0388 }
0389 
0390 //=================================================================================================
0391 
0392 inline constexpr void gp_Dir::SetCoord(const double theXv, const double theYv, const double theZv)
0393 {
0394   const double aSqMod = theXv * theXv + theYv * theYv + theZv * theZv;
0395 
0396   // Fast path: already normalized - fully constexpr
0397   if (aSqMod >= (1.0 - gp::Resolution()) && aSqMod <= (1.0 + gp::Resolution()))
0398   {
0399     coord.SetCoord(theXv, theYv, theZv);
0400     return;
0401   }
0402 
0403   // Slow path: runtime only (sqrt not constexpr - compile error if reached in constexpr context)
0404   Standard_ConstructionError_Raise_if(aSqMod <= gp::Resolution() * gp::Resolution(),
0405                                       "gp_Dir::SetCoord() - input vector has zero norm");
0406   const double aD = sqrt(aSqMod);
0407   coord.SetCoord(theXv / aD, theYv / aD, theZv / aD);
0408 }
0409 
0410 //=================================================================================================
0411 
0412 inline constexpr void gp_Dir::SetX(const double theX)
0413 {
0414   SetCoord(theX, coord.Y(), coord.Z());
0415 }
0416 
0417 //=================================================================================================
0418 
0419 inline constexpr void gp_Dir::SetY(const double theY)
0420 {
0421   SetCoord(coord.X(), theY, coord.Z());
0422 }
0423 
0424 //=================================================================================================
0425 
0426 inline constexpr void gp_Dir::SetZ(const double theZ)
0427 {
0428   SetCoord(coord.X(), coord.Y(), theZ);
0429 }
0430 
0431 //=================================================================================================
0432 
0433 inline constexpr void gp_Dir::SetXYZ(const gp_XYZ& theXYZ)
0434 {
0435   SetCoord(theXYZ.X(), theXYZ.Y(), theXYZ.Z());
0436 }
0437 
0438 //=================================================================================================
0439 
0440 inline constexpr void gp_Dir::Cross(const gp_Dir& theRight)
0441 {
0442   coord.Cross(theRight.coord);
0443   const double aSqMod = coord.SquareModulus();
0444 
0445   // Fast path: already normalized - fully constexpr
0446   if (aSqMod >= (1.0 - gp::Resolution()) && aSqMod <= (1.0 + gp::Resolution()))
0447   {
0448     return;
0449   }
0450 
0451   // Slow path: runtime only (sqrt not constexpr - compile error if reached in constexpr context)
0452   Standard_ConstructionError_Raise_if(aSqMod <= gp::Resolution() * gp::Resolution(),
0453                                       "gp_Dir::Cross() - result vector has zero norm");
0454   coord.Divide(sqrt(aSqMod));
0455 }
0456 
0457 //=================================================================================================
0458 
0459 inline constexpr gp_Dir gp_Dir::Crossed(const gp_Dir& theRight) const
0460 {
0461   gp_Dir aV = *this;
0462   aV.Cross(theRight);
0463   return aV;
0464 }
0465 
0466 //=================================================================================================
0467 
0468 inline constexpr void gp_Dir::CrossCross(const gp_Dir& theV1, const gp_Dir& theV2)
0469 {
0470   coord.CrossCross(theV1.coord, theV2.coord);
0471   const double aSqMod = coord.SquareModulus();
0472 
0473   // Fast path: already normalized - fully constexpr
0474   if (aSqMod >= (1.0 - gp::Resolution()) && aSqMod <= (1.0 + gp::Resolution()))
0475   {
0476     return;
0477   }
0478 
0479   // Slow path: runtime only (sqrt not constexpr - compile error if reached in constexpr context)
0480   Standard_ConstructionError_Raise_if(aSqMod <= gp::Resolution() * gp::Resolution(),
0481                                       "gp_Dir::CrossCross() - result vector has zero norm");
0482   coord.Divide(sqrt(aSqMod));
0483 }
0484 
0485 //=================================================================================================
0486 
0487 inline constexpr gp_Dir gp_Dir::CrossCrossed(const gp_Dir& theV1, const gp_Dir& theV2) const
0488 {
0489   gp_Dir aV = *this;
0490   aV.CrossCross(theV1, theV2);
0491   return aV;
0492 }
0493 
0494 //=================================================================================================
0495 
0496 inline void gp_Dir::Rotate(const gp_Ax1& theA1, const double theAng)
0497 {
0498   gp_Trsf aT;
0499   aT.SetRotation(theA1, theAng);
0500   coord.Multiply(aT.HVectorialPart());
0501 }
0502 
0503 #endif // _gp_Dir_HeaderFile