// Copyright (c) 1991-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #ifndef _gp_GTrsf2d_HeaderFile #define _gp_GTrsf2d_HeaderFile #include "gp_Ax2d.hxx" #include "gp_Mat2d.hxx" #include "gp_TrsfForm.hxx" #include "gp_XY.hxx" #include "Standard_OutOfRange.hxx" //! Defines a non persistent transformation in 2D space. //! This transformation is a general transformation. //! It can be a gp_Trsf2d, an affinity, or you can //! define your own transformation giving the corresponding matrix of transformation. //! //! With a gp_GTrsf2d you can transform only a doublet of coordinates gp_XY. //! It is not possible to transform other geometric objects //! because these transformations can change the nature of non-elementary geometric objects. //! A gp_GTrsf2d is represented with a 2 rows * 3 columns matrix: //! @code //! V1 V2 T XY XY //! | a11 a12 a14 | | x | | x'| //! | a21 a22 a24 | | y | = | y'| //! | 0 0 1 | | 1 | | 1 | //! @endcode //! where {V1, V2} defines the vectorial part of the //! transformation and T defines the translation part of the transformation. //! Warning //! A gp_GTrsf2d transformation is only applicable on coordinates. //! Be careful if you apply such a transformation to all the points of a geometric object, //! as this can change the nature of the object and thus render it incoherent! //! Typically, a circle is transformed into an ellipse by an affinity transformation. //! To avoid modifying the nature of an object, use a gp_Trsf2d transformation instead, //! as objects of this class respect the nature of geometric objects. class gp_GTrsf2d { public: DEFINE_STANDARD_ALLOC //! returns identity transformation. constexpr gp_GTrsf2d() noexcept : loc(0.0, 0.0), shape(gp_Identity), scale(1.0) { matrix.SetScale(1.0); } //! Converts the gp_Trsf2d transformation theT into a //! general transformation. gp_GTrsf2d(const gp_Trsf2d& theT); //! Creates a transformation based on the matrix theM and the //! vector theV where theM defines the vectorial part of the //! transformation, and theV the translation part. constexpr gp_GTrsf2d(const gp_Mat2d& theM, const gp_XY& theV) noexcept : matrix(theM), loc(theV), shape(gp_Other), scale(0.0) { } //! Changes this transformation into an affinity of ratio theRatio //! with respect to the axis theA. //! Note: An affinity is a point-by-point transformation that //! transforms any point P into a point P' such that if H is //! the orthogonal projection of P on the axis theA, the vectors //! HP and HP' satisfy: HP' = theRatio * HP. Standard_EXPORT void SetAffinity(const gp_Ax2d& theA, const double theRatio); //! Replaces the coefficient (theRow, theCol) of the matrix representing //! this transformation by theValue, //! Raises OutOfRange if theRow < 1 or theRow > 2 or theCol < 1 or theCol > 3 void SetValue(const int theRow, const int theCol, const double theValue); //! Replaces the translation part of this //! transformation by the coordinates of the number pair theCoord. Standard_EXPORT void SetTranslationPart(const gp_XY& theCoord); //! Assigns the vectorial and translation parts of theT to this transformation. void SetTrsf2d(const gp_Trsf2d& theT); //! Replaces the vectorial part of this transformation by theMatrix. constexpr void SetVectorialPart(const gp_Mat2d& theMatrix) noexcept { matrix = theMatrix; shape = gp_Other; scale = 0.0; } //! Returns true if the determinant of the vectorial part of //! this transformation is negative. constexpr bool IsNegative() const noexcept { return matrix.Determinant() < 0.0; } //! Returns true if this transformation is singular (and //! therefore, cannot be inverted). //! Note: The Gauss LU decomposition is used to invert the //! transformation matrix. Consequently, the transformation //! is considered as singular if the largest pivot found is less //! than or equal to gp::Resolution(). //! Warning //! If this transformation is singular, it cannot be inverted. constexpr bool IsSingular() const noexcept { return matrix.IsSingular(); } //! Returns the nature of the transformation. It can be //! an identity transformation, a rotation, a translation, a mirror //! transformation (relative to a point or axis), a scaling //! transformation, a compound transformation or some //! other type of transformation. constexpr gp_TrsfForm Form() const noexcept { return shape; } //! Returns the translation part of the GTrsf2d. constexpr const gp_XY& TranslationPart() const noexcept { return loc; } //! Computes the vectorial part of the GTrsf2d. The returned //! Matrix is a 2*2 matrix. constexpr const gp_Mat2d& VectorialPart() const noexcept { return matrix; } //! Returns the coefficients of the global matrix of transformation. //! Raised OutOfRange if theRow < 1 or theRow > 2 or theCol < 1 or theCol > 3 constexpr double Value(const int theRow, const int theCol) const; double operator()(const int theRow, const int theCol) const { return Value(theRow, theCol); } Standard_EXPORT void Invert(); //! Computes the reverse transformation. //! Raised an exception if the matrix of the transformation //! is not inversible. [[nodiscard]] gp_GTrsf2d Inverted() const { gp_GTrsf2d aT = *this; aT.Invert(); return aT; } //! Computes the transformation composed with theT and . //! In a C++ implementation you can also write Tcomposed = * theT. //! Example : //! @code //! gp_GTrsf2d T1, T2, Tcomp; ............... //! //composition : //! Tcomp = T2.Multiplied(T1); // or (Tcomp = T2 * T1) //! // transformation of a point //! gp_XY P(10.,3.); //! gp_XY P1(P); //! Tcomp.Transforms(P1); //using Tcomp //! gp_XY P2(P); //! T1.Transforms(P2); //using T1 then T2 //! T2.Transforms(P2); // P1 = P2 !!! //! @endcode [[nodiscard]] gp_GTrsf2d Multiplied(const gp_GTrsf2d& theT) const { gp_GTrsf2d aTres = *this; aTres.Multiply(theT); return aTres; } [[nodiscard]] gp_GTrsf2d operator*(const gp_GTrsf2d& theT) const { return Multiplied(theT); } Standard_EXPORT void Multiply(const gp_GTrsf2d& theT); void operator*=(const gp_GTrsf2d& theT) { Multiply(theT); } //! Computes the product of the transformation theT and this //! transformation, and assigns the result to this transformation: //! this = theT * this Standard_EXPORT void PreMultiply(const gp_GTrsf2d& theT); Standard_EXPORT void Power(const int theN); //! Computes the following composition of transformations //! * * .......* , theN time. //! if theN = 0 = Identity //! if theN < 0 = .Inverse() *...........* .Inverse(). //! //! Raises an exception if theN < 0 and if the matrix of the //! transformation is not inversible. [[nodiscard]] gp_GTrsf2d Powered(const int theN) const { gp_GTrsf2d aT = *this; aT.Power(theN); return aT; } constexpr void Transforms(gp_XY& theCoord) const noexcept; [[nodiscard]] constexpr gp_XY Transformed(const gp_XY& theCoord) const noexcept { gp_XY aNewCoord = theCoord; Transforms(aNewCoord); return aNewCoord; } //! Applies this transformation to the coordinates: //! - of the number pair Coord, or //! - X and Y. //! //! Note: //! - Transforms modifies theX, theY, or the coordinate pair Coord, while //! - Transformed creates a new coordinate pair. constexpr void Transforms(double& theX, double& theY) const noexcept; //! Converts this transformation into a gp_Trsf2d transformation. //! Exceptions //! Standard_ConstructionError if this transformation //! cannot be converted, i.e. if its form is gp_Other. Standard_EXPORT gp_Trsf2d Trsf2d() const; private: gp_Mat2d matrix; gp_XY loc; gp_TrsfForm shape; double scale; }; #include "gp_Trsf2d.hxx" //================================================================================================= inline void gp_GTrsf2d::SetTrsf2d(const gp_Trsf2d& theT) { shape = theT.shape; matrix = theT.matrix; loc = theT.loc; scale = theT.scale; } //================================================================================================= inline gp_GTrsf2d::gp_GTrsf2d(const gp_Trsf2d& theT) { shape = theT.shape; matrix = theT.matrix; loc = theT.loc; scale = theT.scale; } //================================================================================================= inline void gp_GTrsf2d::SetValue(const int theRow, const int theCol, const double theValue) { Standard_OutOfRange_Raise_if(theRow < 1 || theRow > 2 || theCol < 1 || theCol > 3, " "); if (theCol == 3) { loc.SetCoord(theRow, theValue); } else { matrix.SetValue(theRow, theCol, theValue); } shape = gp_Other; } //================================================================================================= inline constexpr double gp_GTrsf2d::Value(const int theRow, const int theCol) const { Standard_OutOfRange_Raise_if(theRow < 1 || theRow > 2 || theCol < 1 || theCol > 3, " "); if (theCol == 3) { return loc.Coord(theRow); } if (shape == gp_Other) { return matrix.myMat[theRow - 1][theCol - 1]; } return scale * matrix.myMat[theRow - 1][theCol - 1]; } //================================================================================================= inline constexpr void gp_GTrsf2d::Transforms(gp_XY& theCoord) const noexcept { theCoord.Multiply(matrix); if (!(shape == gp_Other) && !(scale == 1.0)) { theCoord.Multiply(scale); } theCoord.Add(loc); } //================================================================================================= inline constexpr void gp_GTrsf2d::Transforms(double& theX, double& theY) const noexcept { gp_XY aDoublet(theX, theY); aDoublet.Multiply(matrix); if (!(shape == gp_Other) && !(scale == 1.0)) { aDoublet.Multiply(scale); } aDoublet.Add(loc); aDoublet.Coord(theX, theY); } #endif // _gp_GTrsf2d_HeaderFile