1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef MMI_MATRIX3_H
17 #define MMI_MATRIX3_H
18
19 #define USE_MATH_DEFINES
20
21 #include "mmi_vector2.h"
22 #include "mmi_vector3.h"
23
24 // column-major order
25 namespace OHOS {
26 namespace MMI {
27 inline constexpr int32_t MATRIX3_SIZE { 9 };
28 template<typename T>
29 class Matrix3 {
30 public:
31 static const Matrix3 ZERO;
32 static const Matrix3 IDENTITY;
33 Matrix3();
34 Matrix3(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22);
35 Matrix3(std::vector<T> M);
36
37 Matrix3(const Matrix3& matrix) noexcept = default;
38
39 explicit Matrix3(const T* v);
40
41 ~Matrix3();
42 T Trace() const;
43 static int Index(int row, int col);
44 void SetIdentity();
45 void SetZero();
46 bool IsIdentity() const;
47 Matrix3 Inverse() const;
48 Matrix3 Multiply(const Matrix3& other) const;
49
50 Matrix3 operator+(const Matrix3& other) const;
51 Matrix3 operator-(const Matrix3& other) const;
52 Matrix3 operator-() const;
53 Matrix3 operator*(const Matrix3& other) const;
54 Vector3<T> operator*(const Vector3<T>& other) const;
55 Matrix3 operator*(T scale) const;
56 T* operator[](int col);
57 Matrix3& operator=(const Matrix3& other);
58 Matrix3& operator+=(const Matrix3& other);
59 Matrix3& operator-=(const Matrix3& other);
60 Matrix3& operator*=(const Matrix3& other);
61 Matrix3& operator*=(T scale);
62 bool operator==(const Matrix3& other) const;
63 bool operator!=(const Matrix3& other) const;
64 bool IsNearEqual(const Matrix3& other, T threshold = std::numeric_limits<T>::epsilon()) const;
65 T* GetData();
66 const T* GetConstData() const;
67 T Determinant() const;
68 Matrix3 Transpose() const;
69 Matrix3 Translate(const Vector2<T>& vec) const;
70 Matrix3 Rotate(T angle) const;
71 Matrix3 Rotate(T angle, T pivotx, T pivoty) const;
72 Matrix3 Scale(const Vector2<T>& vec) const;
73 Matrix3 Scale(const Vector2<T>& vec, T pivotx, T pivoty) const;
74 Matrix3 ShearX(T y) const;
75 Matrix3 ShearY(T x) const;
76
77 protected:
78 T data_[MATRIX3_SIZE] = { 0 };
79 };
80
81 typedef Matrix3<float> Matrix3f;
82 typedef Matrix3<double> Matrix3d;
83
84 template<typename T>
85 const Matrix3<T> Matrix3<T>::ZERO(0, 0, 0, 0, 0, 0, 0, 0, 0);
86
87 template<typename T>
88 const Matrix3<T> Matrix3<T>::IDENTITY(1, 0, 0, 0, 1, 0, 0, 0, 1);
89
90 template<typename T>
Matrix3()91 Matrix3<T>::Matrix3()
92 {}
93
94 template<typename T>
Matrix3(T m00,T m01,T m02,T m10,T m11,T m12,T m20,T m21,T m22)95 Matrix3<T>::Matrix3(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22)
96 {
97 data_[0] = m00;
98 data_[1] = m01;
99 data_[2] = m02;
100
101 data_[3] = m10;
102 data_[4] = m11;
103 data_[5] = m12;
104
105 data_[6] = m20;
106 data_[7] = m21;
107 data_[8] = m22;
108 }
109
110 template<typename T>
Matrix3(std::vector<T> matrix)111 Matrix3<T>::Matrix3(std::vector<T> matrix)
112 {
113 if (matrix.size() != MATRIX3_SIZE) {
114 Matrix3();
115 } else {
116 for (size_t i = 0; i < MATRIX3_SIZE; i++) {
117 data_[i] = matrix[i];
118 }
119 }
120 }
121
122 template<typename T>
Matrix3(const T * v)123 Matrix3<T>::Matrix3(const T* v)
124 {
125 std::copy_n(v, std::size(data_), data_);
126 }
127
128 template<typename T>
~Matrix3()129 Matrix3<T>::~Matrix3()
130 {}
131
132 template<typename T>
Trace()133 T Matrix3<T>::Trace() const
134 {
135 T rTrace = 0.0;
136 rTrace += data_[0];
137 rTrace += data_[4];
138 rTrace += data_[8];
139 return rTrace;
140 }
141
142 template<typename T>
Index(int row,int col)143 int Matrix3<T>::Index(int row, int col)
144 {
145 return (col * 3) + row;
146 }
147
148 template<typename T>
SetIdentity()149 void Matrix3<T>::SetIdentity()
150 {
151 *this = IDENTITY;
152 }
153
154 template<typename T>
SetZero()155 void Matrix3<T>::SetZero()
156 {
157 *this = ZERO;
158 }
159
160 template<typename T>
IsIdentity()161 bool Matrix3<T>::IsIdentity() const
162 {
163 return (MMI_EQ<T>(data_[0], 1.0)) && (MMI_EQ<T>(data_[1], 0.0)) && (MMI_EQ<T>(data_[2], 0.0)) &&
164 (MMI_EQ<T>(data_[3], 0.0)) && (MMI_EQ<T>(data_[4], 1.0)) && (MMI_EQ<T>(data_[5], 0.0)) &&
165 (MMI_EQ<T>(data_[6], 0.0)) && (MMI_EQ<T>(data_[7], 0.0)) && (MMI_EQ<T>(data_[8], 1.0));
166 }
167
168 template<typename T>
Inverse()169 Matrix3<T> Matrix3<T>::Inverse() const
170 {
171 T det = Determinant();
172 if (MMI_EQ<T>(det, 0.0)) {
173 return Matrix3<T>(*this);
174 }
175
176 const T invDet = 1.0f / det;
177 const T* data = data_;
178
179 T iX = invDet * (data[4] * data[8] - data[5] * data[7]);
180 T iY = invDet * (data[2] * data[7] - data[1] * data[8]);
181 T iZ = invDet * (data[1] * data[5] - data[2] * data[4]);
182 T jX = invDet * (data[5] * data[6] - data[3] * data[8]);
183 T jY = invDet * (data[0] * data[8] - data[2] * data[6]);
184 T jZ = invDet * (data[2] * data[3] - data[0] * data[5]);
185 T kX = invDet * (data[3] * data[7] - data[4] * data[6]);
186 T kY = invDet * (data[1] * data[6] - data[0] * data[7]);
187 T kZ = invDet * (data[0] * data[4] - data[1] * data[3]);
188
189 return Matrix3<T>(iX, iY, iZ, jX, jY, jZ, kX, kY, kZ);
190 }
191
192 template<typename T>
Multiply(const Matrix3<T> & other)193 Matrix3<T> Matrix3<T>::Multiply(const Matrix3<T>& other) const
194 {
195 Matrix3<T> rMulti;
196 T* rData = rMulti.data_;
197 const T* oData = other.data_;
198
199 rData[0] = data_[0] * oData[0] + data_[3] * oData[1] + data_[6] * oData[2];
200 rData[3] = data_[0] * oData[3] + data_[3] * oData[4] + data_[6] * oData[5];
201 rData[6] = data_[0] * oData[6] + data_[3] * oData[7] + data_[6] * oData[8];
202
203 rData[1] = data_[1] * oData[0] + data_[4] * oData[1] + data_[7] * oData[2];
204 rData[4] = data_[1] * oData[3] + data_[4] * oData[4] + data_[7] * oData[5];
205 rData[7] = data_[1] * oData[6] + data_[4] * oData[7] + data_[7] * oData[8];
206
207 rData[2] = data_[2] * oData[0] + data_[5] * oData[1] + data_[8] * oData[2];
208 rData[5] = data_[2] * oData[3] + data_[5] * oData[4] + data_[8] * oData[5];
209 rData[8] = data_[2] * oData[6] + data_[5] * oData[7] + data_[8] * oData[8];
210 return rMulti;
211 }
212
213 template<typename T>
214 Matrix3<T> Matrix3<T>::operator+(const Matrix3<T>& other) const
215 {
216 Matrix3<T> rMat3Add;
217 T* rMat3Data = rMat3Add.data_;
218 const T* oData = other.data_;
219
220 rMat3Data[0] = data_[0] + oData[0];
221 rMat3Data[1] = data_[1] + oData[1];
222 rMat3Data[2] = data_[2] + oData[2];
223 rMat3Data[3] = data_[3] + oData[3];
224 rMat3Data[4] = data_[4] + oData[4];
225 rMat3Data[5] = data_[5] + oData[5];
226 rMat3Data[6] = data_[6] + oData[6];
227 rMat3Data[7] = data_[7] + oData[7];
228 rMat3Data[8] = data_[8] + oData[8];
229
230 return rMat3Add;
231 }
232
233 template<typename T>
234 Matrix3<T> Matrix3<T>::operator-(const Matrix3<T>& other) const
235 {
236 return *this + (-other);
237 }
238
239 template<typename T>
240 Matrix3<T> Matrix3<T>::operator-() const
241 {
242 Matrix3<T> rMat3Sub;
243 T* rMat3Data = rMat3Sub.data_;
244
245 rMat3Data[0] = -data_[0];
246 rMat3Data[1] = -data_[1];
247 rMat3Data[2] = -data_[2];
248 rMat3Data[3] = -data_[3];
249 rMat3Data[4] = -data_[4];
250 rMat3Data[5] = -data_[5];
251 rMat3Data[6] = -data_[6];
252 rMat3Data[7] = -data_[7];
253 rMat3Data[8] = -data_[8];
254
255 return rMat3Sub;
256 }
257
258 template<typename T>
259 Matrix3<T> Matrix3<T>::operator*(const Matrix3<T>& other) const
260 {
261 return Multiply(other);
262 }
263
264 template<typename T>
265 Vector3<T> Matrix3<T>::operator*(const Vector3<T>& other) const
266 {
267 Vector3<T> rMulti;
268 T* rData = rMulti.data_;
269 const T* oData = other.data_;
270 rData[0] = data_[0] * oData[0] + data_[3] * oData[1] + data_[6] * oData[2];
271
272 rData[1] = data_[1] * oData[0] + data_[4] * oData[1] + data_[7] * oData[2];
273
274 rData[2] = data_[2] * oData[0] + data_[5] * oData[1] + data_[8] * oData[2];
275 return rMulti;
276 }
277
278 template<typename T>
279 Matrix3<T> Matrix3<T>::operator*(T scale) const
280 {
281 Matrix3<T> rMulti;
282 T* rData = rMulti.data_;
283 rData[0] = data_[0] * scale;
284 rData[1] = data_[1] * scale;
285 rData[2] = data_[2] * scale;
286 rData[3] = data_[3] * scale;
287 rData[4] = data_[4] * scale;
288 rData[5] = data_[5] * scale;
289 rData[6] = data_[6] * scale;
290 rData[7] = data_[7] * scale;
291 rData[8] = data_[8] * scale;
292
293 return rMulti;
294 }
295
296 template<typename T>
297 T* Matrix3<T>::operator[](int col)
298 {
299 return &data_[col * 3];
300 }
301
302 template<typename T>
303 Matrix3<T>& Matrix3<T>::operator=(const Matrix3<T>& other)
304 {
305 const T* oMat3Data = other.data_;
306 data_[0] = oMat3Data[0];
307 data_[1] = oMat3Data[1];
308 data_[2] = oMat3Data[2];
309 data_[3] = oMat3Data[3];
310 data_[4] = oMat3Data[4];
311 data_[5] = oMat3Data[5];
312 data_[6] = oMat3Data[6];
313 data_[7] = oMat3Data[7];
314 data_[8] = oMat3Data[8];
315
316 return *this;
317 }
318
319 template<typename T>
320 Matrix3<T>& Matrix3<T>::operator+=(const Matrix3<T>& other)
321 {
322 const T* oData = other.data_;
323
324 data_[0] += oData[0];
325 data_[1] += oData[1];
326 data_[2] += oData[2];
327 data_[3] += oData[3];
328 data_[4] += oData[4];
329 data_[5] += oData[5];
330 data_[6] += oData[6];
331 data_[7] += oData[7];
332 data_[8] += oData[8];
333
334 return *this;
335 }
336
337 template<typename T>
338 Matrix3<T>& Matrix3<T>::operator-=(const Matrix3<T>& other)
339 {
340 const T* oData = other.data_;
341
342 data_[0] -= oData[0];
343 data_[1] -= oData[1];
344 data_[2] -= oData[2];
345 data_[3] -= oData[3];
346 data_[4] -= oData[4];
347 data_[5] -= oData[5];
348 data_[6] -= oData[6];
349 data_[7] -= oData[7];
350 data_[8] -= oData[8];
351
352 return *this;
353 }
354
355 template<typename T>
356 Matrix3<T>& Matrix3<T>::operator*=(const Matrix3<T>& other)
357 {
358 return (*this = *this * other);
359 }
360
361 template<typename T>
362 Matrix3<T>& Matrix3<T>::operator*=(T scale)
363 {
364 data_[0] *= scale;
365 data_[1] *= scale;
366 data_[2] *= scale;
367 data_[3] *= scale;
368 data_[4] *= scale;
369 data_[5] *= scale;
370 data_[6] *= scale;
371 data_[7] *= scale;
372 data_[8] *= scale;
373 return *this;
374 }
375
376 template<typename T>
377 bool Matrix3<T>::operator==(const Matrix3& other) const
378 {
379 const T* oData = other.data_;
380
381 return (MMI_EQ<T>(data_[0], oData[0])) && (MMI_EQ<T>(data_[1], oData[1])) &&
382 (MMI_EQ<T>(data_[2], oData[2])) && (MMI_EQ<T>(data_[3], oData[3])) &&
383 (MMI_EQ<T>(data_[4], oData[4])) && (MMI_EQ<T>(data_[5], oData[5])) &&
384 (MMI_EQ<T>(data_[6], oData[6])) && (MMI_EQ<T>(data_[7], oData[7])) && (MMI_EQ<T>(data_[8], oData[8]));
385 }
386
387 template<typename T>
388 bool Matrix3<T>::operator!=(const Matrix3& other) const
389 {
390 return !operator==(other);
391 }
392
393 template<typename T>
IsNearEqual(const Matrix3 & other,T threshold)394 bool Matrix3<T>::IsNearEqual(const Matrix3& other, T threshold) const
395 {
396 const T* otherData = other.data_;
397 auto result = std::equal(data_, data_ + 8, otherData,
398 [&threshold](const T& left, const T& right) { return MMI_EQ<T>(left, right, threshold); });
399 return result;
400 }
401
402 template<typename T>
GetData()403 inline T* Matrix3<T>::GetData()
404 {
405 return data_;
406 }
407
408 template<typename T>
GetConstData()409 const T* Matrix3<T>::GetConstData() const
410 {
411 return data_;
412 }
413
414 template<typename T>
Determinant()415 T Matrix3<T>::Determinant() const
416 {
417 T x = data_[0] * ((data_[4] * data_[8]) - (data_[5] * data_[7]));
418 T y = data_[1] * ((data_[3] * data_[8]) - (data_[5] * data_[6]));
419 T z = data_[2] * ((data_[3] * data_[7]) - (data_[4] * data_[6]));
420 return x - y + z;
421 }
422
423 template<typename T>
Transpose()424 Matrix3<T> Matrix3<T>::Transpose() const
425 {
426 Matrix3<T> rTrans;
427 T* rData = rTrans.data_;
428 rData[0] = data_[0];
429 rData[1] = data_[3];
430 rData[2] = data_[6];
431 rData[3] = data_[1];
432 rData[4] = data_[4];
433 rData[5] = data_[7];
434 rData[6] = data_[2];
435 rData[7] = data_[5];
436 rData[8] = data_[8];
437 return rTrans;
438 }
439
440 template<typename T>
Translate(const Vector2<T> & vec)441 Matrix3<T> Matrix3<T>::Translate(const Vector2<T>& vec) const
442 {
443 Matrix3<T> rTrans(*this);
444 T* rData = rTrans.data_;
445
446 rData[6] = data_[0] * vec[0] + data_[3] * vec[1] + data_[6];
447 rData[7] = data_[1] * vec[0] + data_[4] * vec[1] + data_[7];
448 rData[8] = data_[2] * vec[0] + data_[5] * vec[1] + data_[8];
449 return rTrans;
450 }
451
452 template<typename T>
Rotate(T angle)453 Matrix3<T> Matrix3<T>::Rotate(T angle) const
454 {
455 T a = angle;
456 T c = cos(a);
457 T s = sin(a);
458
459 Matrix3<T> rRotate(*this);
460 T* rData = rRotate.data_;
461 rData[0] = data_[0] * c + data_[3] * s;
462 rData[1] = data_[1] * c + data_[4] * s;
463 rData[2] = data_[2] * c + data_[5] * s;
464
465 rData[3] = data_[0] * -s + data_[3] * c;
466 rData[4] = data_[1] * -s + data_[4] * c;
467 rData[5] = data_[2] * -s + data_[5] * c;
468 return rRotate;
469 }
470
471 template<typename T>
Rotate(T angle,T pivotx,T pivoty)472 Matrix3<T> Matrix3<T>::Rotate(T angle, T pivotx, T pivoty) const
473 {
474 T a = angle;
475 T c = cos(a);
476 T s = sin(a);
477 T dx = s * pivoty + (1 - c) * pivotx;
478 T dy = -s * pivotx + (1 - c) * pivoty;
479
480 Matrix3<T> rRotate(*this);
481 T* rData = rRotate.data_;
482 rData[0] = data_[0] * c + data_[3] * s;
483 rData[1] = data_[1] * c + data_[4] * s;
484 rData[2] = data_[2] * c + data_[5] * s;
485
486 rData[3] = data_[0] * -s + data_[3] * c;
487 rData[4] = data_[1] * -s + data_[4] * c;
488 rData[5] = data_[2] * -s + data_[5] * c;
489
490 rData[6] = data_[0] * dx + data_[3] * dy + data_[6];
491 rData[7] = data_[1] * dx + data_[4] * dy + data_[7];
492 rData[8] = data_[2] * dx + data_[5] * dy + data_[8];
493 return rRotate;
494 }
495
496 template<typename T>
Scale(const Vector2<T> & vec)497 Matrix3<T> Matrix3<T>::Scale(const Vector2<T>& vec) const
498 {
499 Matrix3<T> rScale(*this);
500 T* rData = rScale.data_;
501 rData[0] = data_[0] * vec[0];
502 rData[1] = data_[1] * vec[0];
503 rData[2] = data_[2] * vec[0];
504
505 rData[3] = data_[3] * vec[1];
506 rData[4] = data_[4] * vec[1];
507 rData[5] = data_[5] * vec[1];
508 return rScale;
509 }
510
511 template<typename T>
Scale(const Vector2<T> & vec,T pivotx,T pivoty)512 Matrix3<T> Matrix3<T>::Scale(const Vector2<T>& vec, T pivotx, T pivoty) const
513 {
514 T dx = pivotx - vec[0] * pivotx;
515 T dy = pivoty - vec[1] * pivoty;
516
517 Matrix3<T> rScale(*this);
518 T* rData = rScale.data_;
519 rData[0] = data_[0] * vec[0];
520 rData[1] = data_[1] * vec[0];
521 rData[2] = data_[2] * vec[0];
522
523 rData[3] = data_[3] * vec[1];
524 rData[4] = data_[4] * vec[1];
525 rData[5] = data_[5] * vec[1];
526
527 rData[6] = data_[0] * dx + data_[3] * dy + data_[6];
528 rData[7] = data_[1] * dx + data_[4] * dy + data_[7];
529 rData[8] = data_[2] * dx + data_[5] * dy + data_[8];
530 return rScale;
531 }
532
533 template<typename T>
ShearX(T y)534 Matrix3<T> Matrix3<T>::ShearX(T y) const
535 {
536 Matrix3<T> rShear(Matrix3<T>::IDENTITY);
537 rShear.data_[1] = y;
538 return (*this) * rShear;
539 }
540
541 template<typename T>
ShearY(T x)542 Matrix3<T> Matrix3<T>::ShearY(T x) const
543 {
544 Matrix3<T> rShear(Matrix3<T>::IDENTITY);
545 rShear.data_[3] = x;
546 return (*this) * rShear;
547 }
548 } // namespace Rosen
549 } // namespace OHOS
550 #endif // RENDER_SERVICE_CLIENT_CORE_COMMON_RS_MATRIX3_H
551