// 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_Mat2d_HeaderFile #define _gp_Mat2d_HeaderFile #include #include #include class gp_XY; //! Describes a two column, two row matrix. //! This sort of object is used in various vectorial or matrix computations. class gp_Mat2d { public: DEFINE_STANDARD_ALLOC //! Creates a matrix with null coefficients. gp_Mat2d() { myMat[0][0] = myMat[0][1] = myMat[1][0] = myMat[1][1] = 0.0; } //! theCol1, theCol2 are the 2 columns of the matrix. Standard_EXPORT gp_Mat2d (const gp_XY& theCol1, const gp_XY& theCol2); //! Assigns the two coordinates of theValue to the column of range //! theCol of this matrix //! Raises OutOfRange if theCol < 1 or theCol > 2. Standard_EXPORT void SetCol (const Standard_Integer theCol, const gp_XY& theValue); //! Assigns the number pairs theCol1, theCol2 to the two columns of this matrix Standard_EXPORT void SetCols (const gp_XY& theCol1, const gp_XY& theCol2); //! Modifies the main diagonal of the matrix. //! @code //! .Value (1, 1) = theX1 //! .Value (2, 2) = theX2 //! @endcode //! The other coefficients of the matrix are not modified. void SetDiagonal (const Standard_Real theX1, const Standard_Real theX2) { myMat[0][0] = theX1; myMat[1][1] = theX2; } //! Modifies this matrix, so that it represents the Identity matrix. void SetIdentity() { myMat[0][0] = myMat[1][1] = 1.0; myMat[0][1] = myMat[1][0] = 0.0; } //! Modifies this matrix, so that it represents a rotation. theAng is the angular //! value in radian of the rotation. void SetRotation (const Standard_Real theAng); //! Assigns the two coordinates of theValue to the row of index theRow of this matrix. //! Raises OutOfRange if theRow < 1 or theRow > 2. Standard_EXPORT void SetRow (const Standard_Integer theRow, const gp_XY& theValue); //! Assigns the number pairs theRow1, theRow2 to the two rows of this matrix. Standard_EXPORT void SetRows (const gp_XY& theRow1, const gp_XY& theRow2); //! Modifies the matrix such that it //! represents a scaling transformation, where theS is the scale factor : //! @code //! | theS 0.0 | //! = | 0.0 theS | //! @endcode void SetScale (const Standard_Real theS) { myMat[0][0] = myMat[1][1] = theS; myMat[0][1] = myMat[1][0] = 0.0; } //! Assigns to the coefficient of row theRow, column theCol of this matrix. //! Raises OutOfRange if theRow < 1 or theRow > 2 or theCol < 1 or theCol > 2 void SetValue (const Standard_Integer theRow, const Standard_Integer theCol, const Standard_Real theValue) { Standard_OutOfRange_Raise_if (theRow < 1 || theRow > 2 || theCol < 1 || theCol > 2, " "); myMat[theRow - 1][theCol - 1] = theValue; } //! Returns the column of theCol index. //! Raises OutOfRange if theCol < 1 or theCol > 2 Standard_EXPORT gp_XY Column (const Standard_Integer theCol) const; //! Computes the determinant of the matrix. Standard_Real Determinant() const { return myMat[0][0] * myMat[1][1] - myMat[1][0] * myMat[0][1]; } //! Returns the main diagonal of the matrix. Standard_EXPORT gp_XY Diagonal() const; //! Returns the row of index theRow. //! Raised if theRow < 1 or theRow > 2 Standard_EXPORT gp_XY Row (const Standard_Integer theRow) const; //! Returns the coefficient of range (ttheheRow, theCol) //! Raises OutOfRange //! if theRow < 1 or theRow > 2 or theCol < 1 or theCol > 2 const Standard_Real& Value (const Standard_Integer theRow, const Standard_Integer theCol) const { Standard_OutOfRange_Raise_if (theRow < 1 || theRow > 2 || theCol < 1 || theCol > 2, " "); return myMat[theRow - 1][theCol - 1]; } const Standard_Real& operator() (const Standard_Integer theRow, const Standard_Integer theCol) const { return Value (theRow, theCol); } //! Returns the coefficient of range (theRow, theCol) //! Raises OutOfRange //! if theRow < 1 or theRow > 2 or theCol < 1 or theCol > 2 Standard_Real& ChangeValue (const Standard_Integer theRow, const Standard_Integer theCol) { Standard_OutOfRange_Raise_if (theRow < 1 || theRow > 2 || theCol < 1 || theCol > 2, " "); return myMat[theRow - 1][theCol - 1]; } Standard_Real& operator() (const Standard_Integer theRow, const Standard_Integer theCol) { return ChangeValue (theRow, theCol); } //! Returns true if this matrix is singular (and therefore, cannot be inverted). //! The Gauss LU decomposition is used to invert the matrix //! so the matrix is considered as singular if the largest //! pivot found is lower or equal to Resolution from gp. Standard_Boolean IsSingular() const { Standard_Real aDet = Determinant(); if (aDet < 0) { aDet = -aDet; } return aDet <= gp::Resolution(); } void Add (const gp_Mat2d& Other); void operator += (const gp_Mat2d& theOther) { Add (theOther); } //! Computes the sum of this matrix and the matrix //! theOther.for each coefficient of the matrix : //! @code //! .Coef(i,j) + .Coef(i,j) //! @endcode //! Note: //! - operator += assigns the result to this matrix, while //! - operator + creates a new one. Standard_NODISCARD gp_Mat2d Added (const gp_Mat2d& theOther) const; Standard_NODISCARD gp_Mat2d operator + (const gp_Mat2d& theOther) const { return Added (theOther); } void Divide (const Standard_Real theScalar); void operator /= (const Standard_Real theScalar) { Divide (theScalar); } //! Divides all the coefficients of the matrix by a scalar. Standard_NODISCARD gp_Mat2d Divided (const Standard_Real theScalar) const; Standard_NODISCARD gp_Mat2d operator / (const Standard_Real theScalar) const { return Divided (theScalar); } Standard_EXPORT void Invert(); //! Inverses the matrix and raises exception if the matrix //! is singular. Standard_NODISCARD gp_Mat2d Inverted() const { gp_Mat2d aNewMat = *this; aNewMat.Invert(); return aNewMat; } Standard_NODISCARD gp_Mat2d Multiplied (const gp_Mat2d& theOther) const { gp_Mat2d aNewMat2d = *this; aNewMat2d.Multiply (theOther); return aNewMat2d; } Standard_NODISCARD gp_Mat2d operator * (const gp_Mat2d& theOther) const { return Multiplied (theOther); } //! Computes the product of two matrices * void Multiply (const gp_Mat2d& theOther); //! Modifies this matrix by premultiplying it by the matrix Other //! = theOther * . void PreMultiply (const gp_Mat2d& theOther); Standard_NODISCARD gp_Mat2d Multiplied (const Standard_Real theScalar) const; Standard_NODISCARD gp_Mat2d operator * (const Standard_Real theScalar) const { return Multiplied (theScalar); } //! Multiplies all the coefficients of the matrix by a scalar. void Multiply (const Standard_Real theScalar); void operator *= (const Standard_Real theScalar) { Multiply (theScalar); } Standard_EXPORT void Power (const Standard_Integer theN); //! computes = * * .......* , theN time. //! if theN = 0 = Identity //! if theN < 0 = .Invert() *...........* .Invert(). //! If theN < 0 an exception can be raised if the matrix is not //! inversible Standard_NODISCARD gp_Mat2d Powered (const Standard_Integer theN) const { gp_Mat2d aMat2dN = *this; aMat2dN.Power (theN); return aMat2dN; } void Subtract (const gp_Mat2d& theOther); void operator -= (const gp_Mat2d& theOther) { Subtract (theOther); } //! Computes for each coefficient of the matrix : //! @code //! .Coef(i,j) - .Coef(i,j) //! @endcode Standard_NODISCARD gp_Mat2d Subtracted (const gp_Mat2d& theOther) const; Standard_NODISCARD gp_Mat2d operator - (const gp_Mat2d& theOther) const { return Subtracted (theOther); } void Transpose(); //! Transposes the matrix. A(j, i) -> A (i, j) Standard_NODISCARD gp_Mat2d Transposed() const; friend class gp_Trsf2d; friend class gp_GTrsf2d; friend class gp_XY; private: Standard_Real myMat[2][2]; }; //======================================================================= //function : SetRotation // purpose : //======================================================================= inline void gp_Mat2d::SetRotation (const Standard_Real theAng) { Standard_Real aSinA = sin (theAng); Standard_Real aCosA = cos (theAng); myMat[0][0] = myMat[1][1] = aCosA; myMat[0][1] = -aSinA; myMat[1][0] = aSinA; } //======================================================================= //function : Add // purpose : //======================================================================= inline void gp_Mat2d::Add (const gp_Mat2d& theOther) { myMat[0][0] += theOther.myMat[0][0]; myMat[0][1] += theOther.myMat[0][1]; myMat[1][0] += theOther.myMat[1][0]; myMat[1][1] += theOther.myMat[1][1]; } //======================================================================= //function : Added // purpose : //======================================================================= inline gp_Mat2d gp_Mat2d::Added (const gp_Mat2d& theOther) const { gp_Mat2d aNewMat2d; aNewMat2d.myMat[0][0] = myMat[0][0] + theOther.myMat[0][0]; aNewMat2d.myMat[0][1] = myMat[0][1] + theOther.myMat[0][1]; aNewMat2d.myMat[1][0] = myMat[1][0] + theOther.myMat[1][0]; aNewMat2d.myMat[1][1] = myMat[1][1] + theOther.myMat[1][1]; return aNewMat2d; } //======================================================================= //function : Divide // purpose : //======================================================================= inline void gp_Mat2d::Divide (const Standard_Real theScalar) { myMat[0][0] /= theScalar; myMat[0][1] /= theScalar; myMat[1][0] /= theScalar; myMat[1][1] /= theScalar; } //======================================================================= //function : Divided // purpose : //======================================================================= inline gp_Mat2d gp_Mat2d::Divided (const Standard_Real theScalar) const { gp_Mat2d aNewMat2d; aNewMat2d.myMat[0][0] = myMat[0][0] / theScalar; aNewMat2d.myMat[0][1] = myMat[0][1] / theScalar; aNewMat2d.myMat[1][0] = myMat[1][0] / theScalar; aNewMat2d.myMat[1][1] = myMat[1][1] / theScalar; return aNewMat2d; } //======================================================================= //function : Multiply // purpose : //======================================================================= inline void gp_Mat2d::Multiply (const gp_Mat2d& theOther) { const Standard_Real aT00 = myMat[0][0] * theOther.myMat[0][0] + myMat[0][1] * theOther.myMat[1][0]; const Standard_Real aT10 = myMat[1][0] * theOther.myMat[0][0] + myMat[1][1] * theOther.myMat[1][0]; myMat[0][1] = myMat[0][0] * theOther.myMat[0][1] + myMat[0][1] * theOther.myMat[1][1]; myMat[1][1] = myMat[1][0] * theOther.myMat[0][1] + myMat[1][1] * theOther.myMat[1][1]; myMat[0][0] = aT00; myMat[1][0] = aT10; } //======================================================================= //function : PreMultiply // purpose : //======================================================================= inline void gp_Mat2d::PreMultiply (const gp_Mat2d& theOther) { const Standard_Real aT00 = theOther.myMat[0][0] * myMat[0][0] + theOther.myMat[0][1] * myMat[1][0]; myMat[1][0] = theOther.myMat[1][0] * myMat[0][0] + theOther.myMat[1][1] * myMat[1][0]; const Standard_Real aT01 = theOther.myMat[0][0] * myMat[0][1] + theOther.myMat[0][1] * myMat[1][1]; myMat[1][1] = theOther.myMat[1][0] * myMat[0][1] + theOther.myMat[1][1] * myMat[1][1]; myMat[0][0] = aT00; myMat[0][1] = aT01; } //======================================================================= //function : Multiplied // purpose : //======================================================================= inline gp_Mat2d gp_Mat2d::Multiplied (const Standard_Real theScalar) const { gp_Mat2d aNewMat2d; aNewMat2d.myMat[0][0] = myMat[0][0] * theScalar; aNewMat2d.myMat[0][1] = myMat[0][1] * theScalar; aNewMat2d.myMat[1][0] = myMat[1][0] * theScalar; aNewMat2d.myMat[1][1] = myMat[1][1] * theScalar; return aNewMat2d; } //======================================================================= //function : Multiply // purpose : //======================================================================= inline void gp_Mat2d::Multiply (const Standard_Real theScalar) { myMat[0][0] *= theScalar; myMat[0][1] *= theScalar; myMat[1][0] *= theScalar; myMat[1][1] *= theScalar; } //======================================================================= //function : Subtract // purpose : //======================================================================= inline void gp_Mat2d::Subtract (const gp_Mat2d& theOther) { myMat[0][0] -= theOther.myMat[0][0]; myMat[0][1] -= theOther.myMat[0][1]; myMat[1][0] -= theOther.myMat[1][0]; myMat[1][1] -= theOther.myMat[1][1]; } //======================================================================= //function : Subtracted // purpose : //======================================================================= inline gp_Mat2d gp_Mat2d::Subtracted (const gp_Mat2d& theOther) const { gp_Mat2d aNewMat2d; aNewMat2d.myMat[0][0] = myMat[0][0] - theOther.myMat[0][0]; aNewMat2d.myMat[0][1] = myMat[0][1] - theOther.myMat[0][1]; aNewMat2d.myMat[1][0] = myMat[1][0] - theOther.myMat[1][0]; aNewMat2d.myMat[1][1] = myMat[1][1] - theOther.myMat[1][1]; return aNewMat2d; } //======================================================================= //function : Transpose // purpose : //======================================================================= inline void gp_Mat2d::Transpose() { const Standard_Real aTemp = myMat[0][1]; myMat[0][1] = myMat[1][0]; myMat[1][0] = aTemp; } //======================================================================= //function : Transposed // purpose : //======================================================================= inline gp_Mat2d gp_Mat2d::Transposed() const { gp_Mat2d aNewMat2d; aNewMat2d.myMat[1][0] = myMat[0][1]; aNewMat2d.myMat[0][1] = myMat[1][0]; aNewMat2d.myMat[0][0] = myMat[0][0]; aNewMat2d.myMat[1][1] = myMat[1][1]; return aNewMat2d; } //======================================================================= //function : operator* // purpose : //======================================================================= inline gp_Mat2d operator* (const Standard_Real theScalar, const gp_Mat2d& theMat2D) { return theMat2D.Multiplied (theScalar); } #endif // _gp_Mat2d_HeaderFile