1 // Copyright (c) 1991-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #ifndef _gp_Mat_HeaderFile
16 #define _gp_Mat_HeaderFile
19 #include <Standard_OutOfRange.hxx>
20 #include <Standard_OStream.hxx>
21 #include <Standard_ConstructionError.hxx>
27 #define Mat00 matrix[0][0]
28 #define Mat01 matrix[0][1]
29 #define Mat02 matrix[0][2]
30 #define Mat10 matrix[1][0]
31 #define Mat11 matrix[1][1]
32 #define Mat12 matrix[1][2]
33 #define Mat20 matrix[2][0]
34 #define Mat21 matrix[2][1]
35 #define Mat22 matrix[2][2]
37 #define Nat00 aNewMat.matrix[0][0]
38 #define Nat01 aNewMat.matrix[0][1]
39 #define Nat02 aNewMat.matrix[0][2]
40 #define Nat10 aNewMat.matrix[1][0]
41 #define Nat11 aNewMat.matrix[1][1]
42 #define Nat12 aNewMat.matrix[1][2]
43 #define Nat20 aNewMat.matrix[2][0]
44 #define Nat21 aNewMat.matrix[2][1]
45 #define Nat22 aNewMat.matrix[2][2]
47 #define Oat00 theOther.matrix[0][0]
48 #define Oat01 theOther.matrix[0][1]
49 #define Oat02 theOther.matrix[0][2]
50 #define Oat10 theOther.matrix[1][0]
51 #define Oat11 theOther.matrix[1][1]
52 #define Oat12 theOther.matrix[1][2]
53 #define Oat20 theOther.matrix[2][0]
54 #define Oat21 theOther.matrix[2][1]
55 #define Oat22 theOther.matrix[2][2]
57 //! Describes a three column, three row matrix. This sort of
58 //! object is used in various vectorial or matrix computations.
65 //! creates a matrix with null coefficients.
68 Mat00 = Mat01 = Mat02 =
69 Mat10 = Mat11 = Mat12 =
70 Mat20 = Mat21 = Mat22 = 0.0;
73 gp_Mat (const Standard_Real theA11, const Standard_Real theA12, const Standard_Real theA13,
74 const Standard_Real theA21, const Standard_Real theA22, const Standard_Real theA23,
75 const Standard_Real theA31, const Standard_Real theA32, const Standard_Real theA33);
78 //! theCol1, theCol2, theCol3 are the 3 columns of the matrix.
79 Standard_EXPORT gp_Mat (const gp_XYZ& theCol1, const gp_XYZ& theCol2, const gp_XYZ& theCol3);
81 //! Assigns the three coordinates of theValue to the column of index
82 //! theCol of this matrix.
83 //! Raises OutOfRange if theCol < 1 or theCol > 3.
84 Standard_EXPORT void SetCol (const Standard_Integer theCol, const gp_XYZ& theValue);
86 //! Assigns the number triples theCol1, theCol2, theCol3 to the three
87 //! columns of this matrix.
88 Standard_EXPORT void SetCols (const gp_XYZ& theCol1, const gp_XYZ& theCol2, const gp_XYZ& theCol3);
90 //! Modifies the matrix M so that applying it to any number
91 //! triple (X, Y, Z) produces the same result as the cross
92 //! product of theRef and the number triple (X, Y, Z):
93 //! i.e.: M * {X,Y,Z}t = theRef.Cross({X, Y ,Z})
94 //! this matrix is anti symmetric. To apply this matrix to the
95 //! triplet {XYZ} is the same as to do the cross product between the
96 //! triplet theRef and the triplet {XYZ}.
97 //! Note: this matrix is anti-symmetric.
98 Standard_EXPORT void SetCross (const gp_XYZ& theRef);
100 //! Modifies the main diagonal of the matrix.
102 //! <me>.Value (1, 1) = theX1
103 //! <me>.Value (2, 2) = theX2
104 //! <me>.Value (3, 3) = theX3
106 //! The other coefficients of the matrix are not modified.
107 void SetDiagonal (const Standard_Real theX1, const Standard_Real theX2, const Standard_Real theX3)
114 //! Modifies this matrix so that applying it to any number
115 //! triple (X, Y, Z) produces the same result as the scalar
116 //! product of theRef and the number triple (X, Y, Z):
117 //! this * (X,Y,Z) = theRef.(X,Y,Z)
118 //! Note: this matrix is symmetric.
119 Standard_EXPORT void SetDot (const gp_XYZ& theRef);
121 //! Modifies this matrix so that it represents the Identity matrix.
124 Mat00 = Mat11 = Mat22 = 1.0;
125 Mat01 = Mat02 = Mat10 = Mat12 = Mat20 = Mat21 = 0.0;
128 //! Modifies this matrix so that it represents a rotation. theAng is the angular value in
129 //! radians and the XYZ axis gives the direction of the
131 //! Raises ConstructionError if XYZ.Modulus() <= Resolution()
132 Standard_EXPORT void SetRotation (const gp_XYZ& theAxis, const Standard_Real theAng);
134 //! Assigns the three coordinates of Value to the row of index
135 //! theRow of this matrix. Raises OutOfRange if theRow < 1 or theRow > 3.
136 Standard_EXPORT void SetRow (const Standard_Integer theRow, const gp_XYZ& theValue);
138 //! Assigns the number triples theRow1, theRow2, theRow3 to the three
139 //! rows of this matrix.
140 Standard_EXPORT void SetRows (const gp_XYZ& theRow1, const gp_XYZ& theRow2, const gp_XYZ& theRow3);
142 //! Modifies the matrix so that it represents
143 //! a scaling transformation, where theS is the scale factor. :
146 //! <me> = | 0.0 theS 0.0 |
149 void SetScale (const Standard_Real theS)
151 Mat00 = Mat11 = Mat22 = theS;
152 Mat01 = Mat02 = Mat10 = Mat12 = Mat20 = Mat21 = 0.0;
155 //! Assigns <theValue> to the coefficient of row theRow, column theCol of this matrix.
156 //! Raises OutOfRange if theRow < 1 or theRow > 3 or theCol < 1 or theCol > 3
157 void SetValue (const Standard_Integer theRow, const Standard_Integer theCol, const Standard_Real theValue)
159 Standard_OutOfRange_Raise_if (theRow < 1 || theRow > 3 || theCol < 1 || theCol > 3, " ");
160 matrix[theRow - 1][theCol - 1] = theValue;
163 //! Returns the column of theCol index.
164 //! Raises OutOfRange if theCol < 1 or theCol > 3
165 Standard_EXPORT gp_XYZ Column (const Standard_Integer theCol) const;
167 //! Computes the determinant of the matrix.
168 Standard_Real Determinant() const
170 return Mat00 * (Mat11 * Mat22 - Mat21 * Mat12) -
171 Mat01 * (Mat10 * Mat22 - Mat20 * Mat12) +
172 Mat02 * (Mat10 * Mat21 - Mat20 * Mat11);
175 //! Returns the main diagonal of the matrix.
176 Standard_EXPORT gp_XYZ Diagonal() const;
178 //! returns the row of theRow index.
179 //! Raises OutOfRange if theRow < 1 or theRow > 3
180 Standard_EXPORT gp_XYZ Row (const Standard_Integer theRow) const;
182 //! Returns the coefficient of range (theRow, theCol)
183 //! Raises OutOfRange if theRow < 1 or theRow > 3 or theCol < 1 or theCol > 3
184 const Standard_Real& Value (const Standard_Integer theRow, const Standard_Integer theCol) const
186 Standard_OutOfRange_Raise_if (theRow < 1 || theRow > 3 || theCol < 1 || theCol > 3, " ");
187 return matrix[theRow - 1][theCol - 1];
190 const Standard_Real& operator() (const Standard_Integer theRow, const Standard_Integer theCol) const { return Value (theRow, theCol); }
192 //! Returns the coefficient of range (theRow, theCol)
193 //! Raises OutOfRange if theRow < 1 or theRow > 3 or theCol < 1 or theCol > 3
194 Standard_Real& ChangeValue (const Standard_Integer theRow, const Standard_Integer theCol)
196 Standard_OutOfRange_Raise_if (theRow < 1 || theRow > 3 || theCol < 1 || theCol > 3, " ");
197 return matrix[theRow - 1][theCol - 1];
200 Standard_Real& operator() (const Standard_Integer theRow, const Standard_Integer theCol) { return ChangeValue (theRow, theCol); }
202 //! The Gauss LU decomposition is used to invert the matrix
203 //! (see Math package) so the matrix is considered as singular if
204 //! the largest pivot found is lower or equal to Resolution from gp.
205 Standard_Boolean IsSingular() const
207 // Pour etre sur que Gauss va fonctionner, il faut faire Gauss ...
208 Standard_Real aVal = Determinant();
213 return aVal <= gp::Resolution();
216 void Add (const gp_Mat& theOther);
218 void operator += (const gp_Mat& theOther) { Add (theOther); }
220 //! Computes the sum of this matrix and
221 //! the matrix theOther for each coefficient of the matrix :
222 //! <me>.Coef(i,j) + <theOther>.Coef(i,j)
223 Standard_NODISCARD gp_Mat Added (const gp_Mat& theOther) const;
225 Standard_NODISCARD gp_Mat operator + (const gp_Mat& theOther) const { return Added (theOther); }
227 void Divide (const Standard_Real theScalar);
229 void operator /= (const Standard_Real theScalar) { Divide (theScalar); }
231 //! Divides all the coefficients of the matrix by Scalar
232 Standard_NODISCARD gp_Mat Divided (const Standard_Real theScalar) const;
234 Standard_NODISCARD gp_Mat operator / (const Standard_Real theScalar) const { return Divided (theScalar); }
236 Standard_EXPORT void Invert();
238 //! Inverses the matrix and raises if the matrix is singular.
239 //! - Invert assigns the result to this matrix, while
240 //! - Inverted creates a new one.
242 //! The Gauss LU decomposition is used to invert the matrix.
243 //! Consequently, the matrix is considered as singular if the
244 //! largest pivot found is less than or equal to gp::Resolution().
246 //! Standard_ConstructionError if this matrix is singular,
247 //! and therefore cannot be inverted.
248 Standard_NODISCARD Standard_EXPORT gp_Mat Inverted() const;
250 //! Computes the product of two matrices <me> * <Other>
251 Standard_NODISCARD gp_Mat Multiplied (const gp_Mat& theOther) const
253 gp_Mat aNewMat = *this;
254 aNewMat.Multiply (theOther);
258 Standard_NODISCARD gp_Mat operator * (const gp_Mat& theOther) const { return Multiplied (theOther); }
260 //! Computes the product of two matrices <me> = <Other> * <me>.
261 void Multiply (const gp_Mat& theOther);
263 void operator *= (const gp_Mat& theOther) { Multiply (theOther); }
265 void PreMultiply (const gp_Mat& theOther);
267 Standard_NODISCARD gp_Mat Multiplied (const Standard_Real theScalar) const;
269 Standard_NODISCARD gp_Mat operator * (const Standard_Real theScalar) const { return Multiplied (theScalar); }
271 //! Multiplies all the coefficients of the matrix by Scalar
272 void Multiply (const Standard_Real theScalar);
274 void operator *= (const Standard_Real theScalar) { Multiply (theScalar); }
276 Standard_EXPORT void Power (const Standard_Integer N);
278 //! Computes <me> = <me> * <me> * .......* <me>, theN time.
279 //! if theN = 0 <me> = Identity
280 //! if theN < 0 <me> = <me>.Invert() *...........* <me>.Invert().
281 //! If theN < 0 an exception will be raised if the matrix is not
283 Standard_NODISCARD gp_Mat Powered (const Standard_Integer theN) const
285 gp_Mat aMatN = *this;
290 void Subtract (const gp_Mat& theOther);
292 void operator -= (const gp_Mat& theOther) { Subtract (theOther); }
294 //! cOmputes for each coefficient of the matrix :
295 //! <me>.Coef(i,j) - <theOther>.Coef(i,j)
296 Standard_NODISCARD gp_Mat Subtracted (const gp_Mat& theOther) const;
298 Standard_NODISCARD gp_Mat operator - (const gp_Mat& theOther) const { return Subtracted (theOther); }
302 //! Transposes the matrix. A(j, i) -> A (i, j)
303 Standard_NODISCARD gp_Mat Transposed() const
305 gp_Mat aNewMat = *this;
310 //! Dumps the content of me into the stream
311 Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
314 friend class gp_Trsf;
315 friend class gp_GTrsf;
319 Standard_Real matrix[3][3];
323 //=======================================================================
326 //=======================================================================
327 inline gp_Mat::gp_Mat (const Standard_Real theA11, const Standard_Real theA12, const Standard_Real theA13,
328 const Standard_Real theA21, const Standard_Real theA22, const Standard_Real theA23,
329 const Standard_Real theA31, const Standard_Real theA32, const Standard_Real theA33)
342 //=======================================================================
345 //=======================================================================
346 inline void gp_Mat::Add (const gp_Mat& theOther)
348 Mat00 = Mat00 + Oat00;
349 Mat01 = Mat01 + Oat01;
350 Mat02 = Mat02 + Oat02;
351 Mat10 = Mat10 + Oat10;
352 Mat11 = Mat11 + Oat11;
353 Mat12 = Mat12 + Oat12;
354 Mat20 = Mat20 + Oat20;
355 Mat21 = Mat21 + Oat21;
356 Mat22 = Mat22 + Oat22;
359 //=======================================================================
362 //=======================================================================
363 inline gp_Mat gp_Mat::Added (const gp_Mat& theOther) const
366 Nat00 = Mat00 + Oat00;
367 Nat01 = Mat01 + Oat01;
368 Nat02 = Mat02 + Oat02;
369 Nat10 = Mat10 + Oat10;
370 Nat11 = Mat11 + Oat11;
371 Nat12 = Mat12 + Oat12;
372 Nat20 = Mat20 + Oat20;
373 Nat21 = Mat21 + Oat21;
374 Nat22 = Mat22 + Oat22;
378 //=======================================================================
381 //=======================================================================
382 inline void gp_Mat::Divide (const Standard_Real theScalar)
384 Standard_Real aVal = theScalar;
389 Standard_ConstructionError_Raise_if (aVal <= gp::Resolution(),"gp_Mat : Divide by 0");
390 Standard_Real anUnSurScalar = 1.0 / theScalar;
391 Mat00 *= anUnSurScalar;
392 Mat01 *= anUnSurScalar;
393 Mat02 *= anUnSurScalar;
394 Mat10 *= anUnSurScalar;
395 Mat11 *= anUnSurScalar;
396 Mat12 *= anUnSurScalar;
397 Mat20 *= anUnSurScalar;
398 Mat21 *= anUnSurScalar;
399 Mat22 *= anUnSurScalar;
402 //=======================================================================
405 //=======================================================================
406 inline gp_Mat gp_Mat::Divided (const Standard_Real theScalar) const
408 Standard_Real aVal = theScalar;
413 Standard_ConstructionError_Raise_if (aVal <= gp::Resolution(),"gp_Mat : Divide by 0");
415 Standard_Real anUnSurScalar = 1.0 / theScalar;
416 Nat00 = Mat00 * anUnSurScalar;
417 Nat01 = Mat01 * anUnSurScalar;
418 Nat02 = Mat02 * anUnSurScalar;
419 Nat10 = Mat10 * anUnSurScalar;
420 Nat11 = Mat11 * anUnSurScalar;
421 Nat12 = Mat12 * anUnSurScalar;
422 Nat20 = Mat20 * anUnSurScalar;
423 Nat21 = Mat21 * anUnSurScalar;
424 Nat22 = Mat22 * anUnSurScalar;
428 //=======================================================================
429 //function : Multiply
431 //=======================================================================
432 inline void gp_Mat::Multiply (const gp_Mat& theOther)
434 Standard_Real aT00, aT01, aT02, aT10, aT11, aT12, aT20, aT21, aT22;
435 aT00 = Mat00 * Oat00 + Mat01 * Oat10 + Mat02 * Oat20;
436 aT01 = Mat00 * Oat01 + Mat01 * Oat11 + Mat02 * Oat21;
437 aT02 = Mat00 * Oat02 + Mat01 * Oat12 + Mat02 * Oat22;
438 aT10 = Mat10 * Oat00 + Mat11 * Oat10 + Mat12 * Oat20;
439 aT11 = Mat10 * Oat01 + Mat11 * Oat11 + Mat12 * Oat21;
440 aT12 = Mat10 * Oat02 + Mat11 * Oat12 + Mat12 * Oat22;
441 aT20 = Mat20 * Oat00 + Mat21 * Oat10 + Mat22 * Oat20;
442 aT21 = Mat20 * Oat01 + Mat21 * Oat11 + Mat22 * Oat21;
443 aT22 = Mat20 * Oat02 + Mat21 * Oat12 + Mat22 * Oat22;
455 //=======================================================================
456 //function : PreMultiply
458 //=======================================================================
459 inline void gp_Mat::PreMultiply (const gp_Mat& theOther)
461 Standard_Real aT00, aT01, aT02, aT10, aT11, aT12, aT20, aT21, aT22;
462 aT00 = Oat00 * Mat00 + Oat01 * Mat10 + Oat02 * Mat20;
463 aT01 = Oat00 * Mat01 + Oat01 * Mat11 + Oat02 * Mat21;
464 aT02 = Oat00 * Mat02 + Oat01 * Mat12 + Oat02 * Mat22;
465 aT10 = Oat10 * Mat00 + Oat11 * Mat10 + Oat12 * Mat20;
466 aT11 = Oat10 * Mat01 + Oat11 * Mat11 + Oat12 * Mat21;
467 aT12 = Oat10 * Mat02 + Oat11 * Mat12 + Oat12 * Mat22;
468 aT20 = Oat20 * Mat00 + Oat21 * Mat10 + Oat22 * Mat20;
469 aT21 = Oat20 * Mat01 + Oat21 * Mat11 + Oat22 * Mat21;
470 aT22 = Oat20 * Mat02 + Oat21 * Mat12 + Oat22 * Mat22;
482 //=======================================================================
483 //function : Multiplied
485 //=======================================================================
486 inline gp_Mat gp_Mat::Multiplied (const Standard_Real theScalar) const
489 Nat00 = theScalar * Mat00;
490 Nat01 = theScalar * Mat01;
491 Nat02 = theScalar * Mat02;
492 Nat10 = theScalar * Mat10;
493 Nat11 = theScalar * Mat11;
494 Nat12 = theScalar * Mat12;
495 Nat20 = theScalar * Mat20;
496 Nat21 = theScalar * Mat21;
497 Nat22 = theScalar * Mat22;
501 //=======================================================================
502 //function : Multiply
504 //=======================================================================
505 inline void gp_Mat::Multiply (const Standard_Real theScalar)
518 //=======================================================================
519 //function : Subtract
521 //=======================================================================
522 inline void gp_Mat::Subtract (const gp_Mat& theOther)
535 //=======================================================================
536 //function : Subtracted
538 //=======================================================================
539 inline gp_Mat gp_Mat::Subtracted (const gp_Mat& theOther) const
542 Nat00 = Mat00 - Oat00;
543 Nat01 = Mat01 - Oat01;
544 Nat02 = Mat02 - Oat02;
545 Nat10 = Mat10 - Oat10;
546 Nat11 = Mat11 - Oat11;
547 Nat12 = Mat12 - Oat12;
548 Nat20 = Mat20 - Oat20;
549 Nat21 = Mat21 - Oat21;
550 Nat22 = Mat22 - Oat22;
554 //=======================================================================
555 //function : Transpose
557 //=======================================================================
558 // On macOS 10.13.6 with XCode 9.4.1 the compiler has a bug leading to
559 // generation of invalid code when method gp_Mat::Transpose() is called
560 // for a matrix which is when applied to vector; it looks like vector
561 // is transformed before the matrix is actually transposed; see #29978.
562 // To avoid this, we disable compiler optimization here.
563 #if defined(__APPLE__) && (__apple_build_version__ > 9020000)
564 __attribute__((optnone))
566 inline void gp_Mat::Transpose()
580 //=======================================================================
581 //function : operator*
583 //=======================================================================
584 inline gp_Mat operator* (const Standard_Real theScalar,
585 const gp_Mat& theMat3D)
587 return theMat3D.Multiplied (theScalar);
590 #endif // _gp_Mat_HeaderFile