1 // Copyright (c) 2020 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #ifndef _NCollection_Mat3_HeaderFile
15 #define _NCollection_Mat3_HeaderFile
17 #include <NCollection_Vec3.hxx>
18 #include <Standard_ConstructionError.hxx>
21 //! Warning, empty constructor returns an identity matrix.
22 template<typename Element_t>
23 class NCollection_Mat3
27 //! Return identity matrix.
28 static NCollection_Mat3 Identity()
30 return NCollection_Mat3();
33 //! Return zero matrix.
34 static NCollection_Mat3 Zero()
36 NCollection_Mat3 aMat; aMat.InitZero();
42 //! Empty constructor for identity matrix.
48 //! Conversion constructor (explicitly converts some 3x3 matrix with other element type
49 //! to a new 3x3 matrix with the element type Element_t,
50 //! whose elements are static_cast'ed corresponding elements of theOtherMat3 matrix)
51 //! @tparam OtherElement_t the element type of the other 3x3 matrix theOtherVec3
52 //! @param theOtherMat3 the 3x3 matrix that needs to be converted
53 template <typename OtherElement_t>
54 explicit NCollection_Mat3 (const NCollection_Mat3<OtherElement_t>& theOtherMat3)
56 ConvertFrom (theOtherMat3);
59 //! Get element at the specified row and column.
60 //! @param theRow [in] the row.to address.
61 //! @param theCol [in] the column to address.
62 //! @return the value of the addressed element.
63 Element_t GetValue (const size_t theRow, const size_t theCol) const
65 return myMat[theCol * 3 + theRow];
68 //! Access element at the specified row and column.
69 //! @param theRow [in] the row.to access.
70 //! @param theCol [in] the column to access.
71 //! @return reference on the matrix element.
72 Element_t& ChangeValue (const size_t theRow, const size_t theCol)
74 return myMat[theCol * 3 + theRow];
77 //! Set value for the element specified by row and columns.
78 //! @param theRow [in] the row to change.
79 //! @param theCol [in] the column to change.
80 //! @param theValue [in] the value to set.s
81 void SetValue (const size_t theRow,
83 const Element_t theValue)
85 myMat[theCol * 3 + theRow] = theValue;
89 Element_t& operator()(const size_t theRow, const size_t theCol) { return ChangeValue (theRow, theCol); }
92 Element_t operator()(const size_t theRow, const size_t theCol) const { return GetValue (theRow, theCol); }
95 NCollection_Vec3<Element_t> GetRow (const size_t theRow) const
97 return NCollection_Vec3<Element_t> (GetValue (theRow, 0), GetValue (theRow, 1), GetValue (theRow, 2));
100 //! Change first 3 row values by the passed vector.
101 //! @param theRow [in] the row to change.
102 //! @param theVec [in] the vector of values.
103 void SetRow (const size_t theRow, const NCollection_Vec3<Element_t>& theVec)
105 SetValue (theRow, 0, theVec.x());
106 SetValue (theRow, 1, theVec.y());
107 SetValue (theRow, 2, theVec.z());
110 //! Return the column.
111 NCollection_Vec3<Element_t> GetColumn (const size_t theCol) const
113 return NCollection_Vec3<Element_t> (GetValue (0, theCol), GetValue (1, theCol), GetValue (2, theCol));
116 //! Change first 3 column values by the passed vector.
117 //! @param theCol [in] the column to change.
118 //! @param theVec [in] the vector of values.
119 void SetColumn (const size_t theCol,
120 const NCollection_Vec3<Element_t>& theVec)
122 SetValue (0, theCol, theVec.x());
123 SetValue (1, theCol, theVec.y());
124 SetValue (2, theCol, theVec.z());
127 //! Get vector of diagonal elements.
128 //! @return vector of diagonal elements.
129 NCollection_Vec3<Element_t> GetDiagonal() const
131 return NCollection_Vec3<Element_t> (GetValue (0, 0), GetValue (1, 1), GetValue (2, 2));
134 //! Change first 3 elements of the diagonal matrix.
135 //! @param theVec the vector of values.
136 void SetDiagonal (const NCollection_Vec3<Element_t>& theVec)
138 SetValue (0, 0, theVec.x());
139 SetValue (1, 1, theVec.y());
140 SetValue (2, 2, theVec.z());
143 //! Initialize the zero matrix.
146 std::memcpy (this, MyZeroArray, sizeof (NCollection_Mat3));
149 //! Checks the matrix for zero (without tolerance).
152 return std::memcmp (this, MyZeroArray, sizeof (NCollection_Mat3)) == 0;
155 //! Initialize the identity matrix.
158 std::memcpy (this, MyIdentityArray, sizeof (NCollection_Mat3));
161 //! Checks the matrix for identity (without tolerance).
162 bool IsIdentity() const
164 return std::memcmp (this, MyIdentityArray, sizeof (NCollection_Mat3)) == 0;
167 //! Check this matrix for equality with another matrix (without tolerance!).
168 bool IsEqual (const NCollection_Mat3& theOther) const
170 return std::memcmp (this, &theOther, sizeof(NCollection_Mat3)) == 0;
173 //! Comparison operator.
174 bool operator== (const NCollection_Mat3& theMat) const { return IsEqual (theMat); }
176 //! Check this vector with another vector for non-equality (without tolerance!).
177 bool operator!= (const NCollection_Mat3& theOther) const { return !IsEqual (theOther); }
179 //! Raw access to the data (for OpenGL exchange).
180 //! the data is returned in column-major order.
181 const Element_t* GetData() const { return myMat; }
182 Element_t* ChangeData() { return myMat; }
184 //! Multiply by the vector (M * V).
185 //! @param theVec [in] the vector to multiply.
186 NCollection_Vec3<Element_t> operator* (const NCollection_Vec3<Element_t>& theVec) const
188 return NCollection_Vec3<Element_t> (
189 GetValue (0, 0) * theVec.x() + GetValue (0, 1) * theVec.y() + GetValue (0, 2) * theVec.z(),
190 GetValue (1, 0) * theVec.x() + GetValue (1, 1) * theVec.y() + GetValue (1, 2) * theVec.z(),
191 GetValue (2, 0) * theVec.x() + GetValue (2, 1) * theVec.y() + GetValue (2, 2) * theVec.z());
194 //! Compute matrix multiplication product: A * B.
195 //! @param theMatA [in] the matrix "A".
196 //! @param theMatB [in] the matrix "B".
197 static NCollection_Mat3 Multiply (const NCollection_Mat3& theMatA,
198 const NCollection_Mat3& theMatB)
200 NCollection_Mat3 aMatRes;
203 for (size_t aResElem = 0; aResElem < 9; ++aResElem)
205 aMatRes.myMat[aResElem] = (Element_t )0;
206 for (aInputElem = 0; aInputElem < 3; ++aInputElem)
208 aMatRes.myMat[aResElem] += theMatA.GetValue(aResElem % 3, aInputElem)
209 * theMatB.GetValue(aInputElem, aResElem / 3);
216 //! Compute matrix multiplication.
217 //! @param theMat [in] the matrix to multiply.
218 void Multiply (const NCollection_Mat3& theMat)
220 *this = Multiply(*this, theMat);
223 //! Multiply by the another matrix.
224 //! @param theMat [in] the other matrix.
225 NCollection_Mat3& operator*= (const NCollection_Mat3& theMat)
231 //! Compute matrix multiplication product.
232 //! @param theMat [in] the other matrix.
233 //! @return result of multiplication.
234 Standard_NODISCARD NCollection_Mat3 operator* (const NCollection_Mat3& theMat) const
236 return Multiplied (theMat);
239 //! Compute matrix multiplication product.
240 //! @param theMat [in] the other matrix.
241 //! @return result of multiplication.
242 Standard_NODISCARD NCollection_Mat3 Multiplied (const NCollection_Mat3& theMat) const
244 NCollection_Mat3 aTempMat (*this);
249 //! Compute per-component multiplication.
250 //! @param theFactor [in] the scale factor.
251 void Multiply (const Element_t theFactor)
253 for (size_t i = 0; i < 9; ++i)
255 myMat[i] *= theFactor;
259 //! Compute per-element multiplication.
260 //! @param theFactor [in] the scale factor.
261 NCollection_Mat3& operator*= (const Element_t theFactor)
263 Multiply (theFactor);
267 //! Compute per-element multiplication.
268 //! @param theFactor [in] the scale factor.
269 //! @return the result of multiplication.
270 Standard_NODISCARD NCollection_Mat3 operator* (const Element_t theFactor) const
272 return Multiplied (theFactor);
275 //! Compute per-element multiplication.
276 //! @param theFactor [in] the scale factor.
277 //! @return the result of multiplication.
278 Standard_NODISCARD NCollection_Mat3 Multiplied (const Element_t theFactor) const
280 NCollection_Mat3 aTempMat (*this);
281 aTempMat *= theFactor;
285 //! Compute per-component division.
286 //! @param theFactor [in] the scale factor.
287 void Divide (const Element_t theFactor)
289 for (size_t i = 0; i < 9; ++i)
291 myMat[i] /= theFactor;
295 //! Per-component division.
296 //! @param theScalar [in] the scale factor.
297 NCollection_Mat3& operator/= (const Element_t theScalar)
303 //! Divides all the coefficients of the matrix by scalar.
304 Standard_NODISCARD NCollection_Mat3 Divided (const Element_t theScalar) const
306 NCollection_Mat3 aTempMat (*this);
307 aTempMat /= theScalar;
311 //! Divides all the coefficients of the matrix by scalar.
312 Standard_NODISCARD NCollection_Mat3 operator/ (const Element_t theScalar) const
314 return Divided (theScalar);
317 //! Per-component addition of another matrix.
318 void Add (const NCollection_Mat3& theMat)
320 for (size_t i = 0; i < 9; ++i)
322 myMat[i] += theMat.myMat[i];
326 //! Per-component addition of another matrix.
327 NCollection_Mat3& operator+= (const NCollection_Mat3& theMat)
333 //! Per-component subtraction of another matrix.
334 void Subtract (const NCollection_Mat3& theMat)
336 for (size_t i = 0; i < 9; ++i)
338 myMat[i] -= theMat.myMat[i];
342 //! Per-component subtraction of another matrix.
343 NCollection_Mat3& operator-= (const NCollection_Mat3& theMat)
349 //! Per-component addition of another matrix.
350 Standard_NODISCARD NCollection_Mat3 Added (const NCollection_Mat3& theMat) const
352 NCollection_Mat3 aMat (*this);
357 //! Per-component addition of another matrix.
358 Standard_NODISCARD NCollection_Mat3 operator+ (const NCollection_Mat3& theMat) const
360 return Added (theMat);
363 //! Per-component subtraction of another matrix.
364 Standard_NODISCARD NCollection_Mat3 Subtracted (const NCollection_Mat3& theMat) const
366 NCollection_Mat3 aMat (*this);
371 //! Per-component subtraction of another matrix.
372 Standard_NODISCARD NCollection_Mat3 operator- (const NCollection_Mat3& theMat) const
374 return Subtracted (theMat);
377 //! Returns matrix with all components negated.
378 Standard_NODISCARD NCollection_Mat3 Negated() const
380 NCollection_Mat3 aMat;
381 for (size_t i = 0; i < 9; ++i)
383 aMat.myMat[i] = -myMat[i];
388 //! Returns matrix with all components negated.
389 Standard_NODISCARD NCollection_Mat3 operator-() const
394 //! Transpose the matrix.
395 //! @return transposed copy of the matrix.
396 Standard_NODISCARD NCollection_Mat3 Transposed() const
398 NCollection_Mat3 aTempMat;
399 aTempMat.SetRow (0, GetColumn (0));
400 aTempMat.SetRow (1, GetColumn (1));
401 aTempMat.SetRow (2, GetColumn (2));
405 //! Transpose the matrix.
408 *this = Transposed();
411 //! Return determinant of the matrix.
412 Element_t Determinant() const
414 return (GetValue (0, 0) * GetValue (1, 1) * GetValue (2, 2)
415 + GetValue (0, 1) * GetValue (1, 2) * GetValue (2, 0)
416 + GetValue (0, 2) * GetValue (1, 0) * GetValue (2, 1))
417 - (GetValue (0, 2) * GetValue (1, 1) * GetValue (2, 0)
418 + GetValue (0, 0) * GetValue (1, 2) * GetValue (2, 1)
419 + GetValue (0, 1) * GetValue (1, 0) * GetValue (2, 2));
422 //! Return adjoint (adjugate matrix, e.g. conjugate transpose).
423 Standard_NODISCARD NCollection_Mat3 Adjoint() const
425 NCollection_Mat3 aMat;
426 aMat.SetRow (0, NCollection_Vec3<Element_t>::Cross (GetRow(1), GetRow(2)));
427 aMat.SetRow (1, NCollection_Vec3<Element_t>::Cross (GetRow(2), GetRow(0)));
428 aMat.SetRow (2, NCollection_Vec3<Element_t>::Cross (GetRow(0), GetRow(1)));
432 //! Compute inverted matrix.
433 //! @param[out] theInv the inverted matrix
434 //! @param[out] theDet determinant of matrix
435 //! @return true if reversion success
436 bool Inverted (NCollection_Mat3& theInv, Element_t& theDet) const
438 const NCollection_Mat3 aMat = Adjoint();
439 theDet = aMat.GetRow(0).Dot (GetRow(0));
440 if (theDet == Element_t(0))
445 theInv = aMat.Transposed() / theDet;
449 //! Compute inverted matrix.
450 //! @param[out] theInv the inverted matrix
451 //! @return true if reversion success
452 bool Inverted (NCollection_Mat3& theInv) const
455 return Inverted (theInv, aDet);
458 //! Return inverted matrix.
459 NCollection_Mat3 Inverted() const
461 NCollection_Mat3 anInv;
462 if (!Inverted (anInv))
464 throw Standard_ConstructionError ("NCollection_Mat3::Inverted() - matrix has zero determinant");
469 //! Take values from NCollection_Mat3 with a different element type with type conversion.
470 template <typename Other_t>
471 void ConvertFrom (const NCollection_Mat3<Other_t>& theFrom)
473 for (int anIdx = 0; anIdx < 9; ++anIdx)
475 myMat[anIdx] = static_cast<Element_t> (theFrom.myMat[anIdx]);
479 //! Maps plain C array to matrix type.
480 static NCollection_Mat3<Element_t>& Map (Element_t* theData)
482 return *reinterpret_cast<NCollection_Mat3<Element_t>*> (theData);
485 //! Maps plain C array to matrix type.
486 static const NCollection_Mat3<Element_t>& Map (const Element_t* theData)
488 return *reinterpret_cast<const NCollection_Mat3<Element_t>*> (theData);
491 //! Dumps the content of me into the stream
492 void DumpJson (Standard_OStream& theOStream, Standard_Integer) const
494 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "NCollection_Mat3", 9,
495 GetValue (0, 0), GetValue (0, 1), GetValue (0, 2),
496 GetValue (1, 0), GetValue (1, 1), GetValue (1, 2),
497 GetValue (2, 0), GetValue (2, 1), GetValue (2, 2))
506 static const Element_t MyZeroArray[9];
507 static const Element_t MyIdentityArray[9];
509 // All instantiations are friend to each other
510 template<class OtherType> friend class NCollection_Mat3;
513 template<typename Element_t>
514 const Element_t NCollection_Mat3<Element_t>::MyZeroArray[] =
519 template<typename Element_t>
520 const Element_t NCollection_Mat3<Element_t>::MyIdentityArray[] =
525 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
526 #include <type_traits>
528 static_assert(std::is_trivially_copyable<NCollection_Mat3<float>>::value, "NCollection_Mat3 is not is_trivially_copyable() structure!");
529 static_assert(std::is_standard_layout <NCollection_Mat3<float>>::value, "NCollection_Mat3 is not is_standard_layout() structure!");
530 static_assert(sizeof(NCollection_Mat3<float>) == sizeof(float)*9, "NCollection_Mat3 is not packed/aligned!");
533 #endif // _NCollection_Mat3_HeaderFile