1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtGui module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QDOUBLEMATRIX4X4_H |
41 | #define QDOUBLEMATRIX4X4_H |
42 | |
43 | // |
44 | // W A R N I N G |
45 | // ------------- |
46 | // |
47 | // This file is not part of the Qt API. It exists purely as an |
48 | // implementation detail. This header file may change from version to |
49 | // version without notice, or even be removed. |
50 | // |
51 | // We mean it. |
52 | // |
53 | |
54 | #include <QtPositioning/private/qpositioningglobal_p.h> |
55 | #include <QtPositioning/private/qdoublevector3d_p.h> |
56 | #include <QtCore/QDebug> |
57 | #include <QtCore/qmetatype.h> |
58 | #include <QtCore/QRectF> |
59 | |
60 | QT_BEGIN_NAMESPACE |
61 | |
62 | /* |
63 | * This class is a copy/paste/replace of QMatrix4x4 |
64 | * No algorithm has been changed. |
65 | * Some methods have been removed. |
66 | */ |
67 | |
68 | class Q_POSITIONING_PRIVATE_EXPORT QDoubleMatrix4x4 |
69 | { |
70 | public: |
71 | inline QDoubleMatrix4x4() { setToIdentity(); } |
72 | explicit QDoubleMatrix4x4(Qt::Initialization) : flagBits(General) {} |
73 | explicit QDoubleMatrix4x4(const double *values); |
74 | inline QDoubleMatrix4x4(double m11, double m12, double m13, double m14, |
75 | double m21, double m22, double m23, double m24, |
76 | double m31, double m32, double m33, double m34, |
77 | double m41, double m42, double m43, double m44); |
78 | |
79 | QDoubleMatrix4x4(const double *values, int cols, int rows); |
80 | |
81 | inline const double& operator()(int row, int column) const; |
82 | inline double& operator()(int row, int column); |
83 | |
84 | inline bool isAffine() const; |
85 | |
86 | inline bool isIdentity() const; |
87 | inline void setToIdentity(); |
88 | |
89 | inline void fill(double value); |
90 | |
91 | double determinant() const; |
92 | QDoubleMatrix4x4 inverted(bool *invertible = nullptr) const; |
93 | QDoubleMatrix4x4 transposed() const; |
94 | |
95 | inline QDoubleMatrix4x4& operator+=(const QDoubleMatrix4x4& other); |
96 | inline QDoubleMatrix4x4& operator-=(const QDoubleMatrix4x4& other); |
97 | inline QDoubleMatrix4x4& operator*=(const QDoubleMatrix4x4& other); |
98 | inline QDoubleMatrix4x4& operator*=(double factor); |
99 | QDoubleMatrix4x4& operator/=(double divisor); |
100 | inline bool operator==(const QDoubleMatrix4x4& other) const; |
101 | inline bool operator!=(const QDoubleMatrix4x4& other) const; |
102 | |
103 | friend QDoubleMatrix4x4 operator+(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2); |
104 | friend QDoubleMatrix4x4 operator-(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2); |
105 | friend QDoubleMatrix4x4 operator*(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2); |
106 | |
107 | friend QDoubleVector3D operator*(const QDoubleMatrix4x4& matrix, const QDoubleVector3D& vector); |
108 | friend QDoubleVector3D operator*(const QDoubleVector3D& vector, const QDoubleMatrix4x4& matrix); |
109 | |
110 | friend QPoint operator*(const QPoint& point, const QDoubleMatrix4x4& matrix); |
111 | friend QPointF operator*(const QPointF& point, const QDoubleMatrix4x4& matrix); |
112 | friend QDoubleMatrix4x4 operator-(const QDoubleMatrix4x4& matrix); |
113 | friend QPoint operator*(const QDoubleMatrix4x4& matrix, const QPoint& point); |
114 | friend QPointF operator*(const QDoubleMatrix4x4& matrix, const QPointF& point); |
115 | friend QDoubleMatrix4x4 operator*(double factor, const QDoubleMatrix4x4& matrix); |
116 | friend QDoubleMatrix4x4 operator*(const QDoubleMatrix4x4& matrix, double factor); |
117 | friend Q_POSITIONING_PRIVATE_EXPORT QDoubleMatrix4x4 operator/(const QDoubleMatrix4x4& matrix, double divisor); |
118 | |
119 | friend inline bool qFuzzyCompare(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2); |
120 | |
121 | |
122 | void scale(const QDoubleVector3D& vector); |
123 | void translate(const QDoubleVector3D& vector); |
124 | void rotate(double angle, const QDoubleVector3D& vector); |
125 | |
126 | void scale(double x, double y); |
127 | void scale(double x, double y, double z); |
128 | void scale(double factor); |
129 | void translate(double x, double y); |
130 | void translate(double x, double y, double z); |
131 | void rotate(double angle, double x, double y, double z = 0.0f); |
132 | |
133 | void ortho(const QRect& rect); |
134 | void ortho(const QRectF& rect); |
135 | void ortho(double left, double right, double bottom, double top, double nearPlane, double farPlane); |
136 | void frustum(double left, double right, double bottom, double top, double nearPlane, double farPlane); |
137 | void perspective(double verticalAngle, double aspectRatio, double nearPlane, double farPlane); |
138 | |
139 | void lookAt(const QDoubleVector3D& eye, const QDoubleVector3D& center, const QDoubleVector3D& up); |
140 | |
141 | void viewport(const QRectF &rect); |
142 | void viewport(double left, double bottom, double width, double height, double nearPlane = 0.0f, double farPlane = 1.0f); |
143 | void flipCoordinates(); |
144 | |
145 | void copyDataTo(double *values) const; |
146 | |
147 | QPoint map(const QPoint& point) const; |
148 | QPointF map(const QPointF& point) const; |
149 | |
150 | QDoubleVector3D map(const QDoubleVector3D& point) const; |
151 | QDoubleVector3D mapVector(const QDoubleVector3D& vector) const; |
152 | |
153 | QRect mapRect(const QRect& rect) const; |
154 | QRectF mapRect(const QRectF& rect) const; |
155 | |
156 | inline double *data(); |
157 | inline const double *data() const { return *m; } |
158 | inline const double *constData() const { return *m; } |
159 | |
160 | void optimize(); |
161 | |
162 | #ifndef QT_NO_DEBUG_STREAM |
163 | friend Q_POSITIONING_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QDoubleMatrix4x4 &m); |
164 | #endif |
165 | |
166 | private: |
167 | double m[4][4]; // Column-major order to match OpenGL. |
168 | int flagBits; // Flag bits from the enum below. |
169 | |
170 | // When matrices are multiplied, the flag bits are or-ed together. |
171 | enum { |
172 | Identity = 0x0000, // Identity matrix |
173 | Translation = 0x0001, // Contains a translation |
174 | Scale = 0x0002, // Contains a scale |
175 | Rotation2D = 0x0004, // Contains a rotation about the Z axis |
176 | Rotation = 0x0008, // Contains an arbitrary rotation |
177 | Perspective = 0x0010, // Last row is different from (0, 0, 0, 1) |
178 | General = 0x001f // General matrix, unknown contents |
179 | }; |
180 | |
181 | // Construct without initializing identity matrix. |
182 | explicit QDoubleMatrix4x4(int) { } |
183 | |
184 | QDoubleMatrix4x4 orthonormalInverse() const; |
185 | |
186 | void projectedRotate(double angle, double x, double y, double z); |
187 | }; |
188 | |
189 | Q_DECLARE_TYPEINFO(QDoubleMatrix4x4, Q_MOVABLE_TYPE); |
190 | |
191 | inline QDoubleMatrix4x4::QDoubleMatrix4x4 |
192 | (double m11, double m12, double m13, double m14, |
193 | double m21, double m22, double m23, double m24, |
194 | double m31, double m32, double m33, double m34, |
195 | double m41, double m42, double m43, double m44) |
196 | { |
197 | m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41; |
198 | m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42; |
199 | m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43; |
200 | m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44; |
201 | flagBits = General; |
202 | } |
203 | |
204 | inline const double& QDoubleMatrix4x4::operator()(int aRow, int aColumn) const |
205 | { |
206 | Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4); |
207 | return m[aColumn][aRow]; |
208 | } |
209 | |
210 | inline double& QDoubleMatrix4x4::operator()(int aRow, int aColumn) |
211 | { |
212 | Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4); |
213 | flagBits = General; |
214 | return m[aColumn][aRow]; |
215 | } |
216 | |
217 | Q_POSITIONING_PRIVATE_EXPORT QDoubleMatrix4x4 operator/(const QDoubleMatrix4x4& matrix, double divisor); |
218 | |
219 | inline bool QDoubleMatrix4x4::isAffine() const |
220 | { |
221 | return m[0][3] == 0.0f && m[1][3] == 0.0f && m[2][3] == 0.0f && m[3][3] == 1.0f; |
222 | } |
223 | |
224 | inline bool QDoubleMatrix4x4::isIdentity() const |
225 | { |
226 | if (flagBits == Identity) |
227 | return true; |
228 | if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f) |
229 | return false; |
230 | if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f) |
231 | return false; |
232 | if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f) |
233 | return false; |
234 | if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f) |
235 | return false; |
236 | if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f) |
237 | return false; |
238 | return (m[3][3] == 1.0f); |
239 | } |
240 | |
241 | inline void QDoubleMatrix4x4::setToIdentity() |
242 | { |
243 | m[0][0] = 1.0f; |
244 | m[0][1] = 0.0f; |
245 | m[0][2] = 0.0f; |
246 | m[0][3] = 0.0f; |
247 | m[1][0] = 0.0f; |
248 | m[1][1] = 1.0f; |
249 | m[1][2] = 0.0f; |
250 | m[1][3] = 0.0f; |
251 | m[2][0] = 0.0f; |
252 | m[2][1] = 0.0f; |
253 | m[2][2] = 1.0f; |
254 | m[2][3] = 0.0f; |
255 | m[3][0] = 0.0f; |
256 | m[3][1] = 0.0f; |
257 | m[3][2] = 0.0f; |
258 | m[3][3] = 1.0f; |
259 | flagBits = Identity; |
260 | } |
261 | |
262 | inline void QDoubleMatrix4x4::fill(double value) |
263 | { |
264 | m[0][0] = value; |
265 | m[0][1] = value; |
266 | m[0][2] = value; |
267 | m[0][3] = value; |
268 | m[1][0] = value; |
269 | m[1][1] = value; |
270 | m[1][2] = value; |
271 | m[1][3] = value; |
272 | m[2][0] = value; |
273 | m[2][1] = value; |
274 | m[2][2] = value; |
275 | m[2][3] = value; |
276 | m[3][0] = value; |
277 | m[3][1] = value; |
278 | m[3][2] = value; |
279 | m[3][3] = value; |
280 | flagBits = General; |
281 | } |
282 | |
283 | inline QDoubleMatrix4x4& QDoubleMatrix4x4::operator+=(const QDoubleMatrix4x4& other) |
284 | { |
285 | m[0][0] += other.m[0][0]; |
286 | m[0][1] += other.m[0][1]; |
287 | m[0][2] += other.m[0][2]; |
288 | m[0][3] += other.m[0][3]; |
289 | m[1][0] += other.m[1][0]; |
290 | m[1][1] += other.m[1][1]; |
291 | m[1][2] += other.m[1][2]; |
292 | m[1][3] += other.m[1][3]; |
293 | m[2][0] += other.m[2][0]; |
294 | m[2][1] += other.m[2][1]; |
295 | m[2][2] += other.m[2][2]; |
296 | m[2][3] += other.m[2][3]; |
297 | m[3][0] += other.m[3][0]; |
298 | m[3][1] += other.m[3][1]; |
299 | m[3][2] += other.m[3][2]; |
300 | m[3][3] += other.m[3][3]; |
301 | flagBits = General; |
302 | return *this; |
303 | } |
304 | |
305 | inline QDoubleMatrix4x4& QDoubleMatrix4x4::operator-=(const QDoubleMatrix4x4& other) |
306 | { |
307 | m[0][0] -= other.m[0][0]; |
308 | m[0][1] -= other.m[0][1]; |
309 | m[0][2] -= other.m[0][2]; |
310 | m[0][3] -= other.m[0][3]; |
311 | m[1][0] -= other.m[1][0]; |
312 | m[1][1] -= other.m[1][1]; |
313 | m[1][2] -= other.m[1][2]; |
314 | m[1][3] -= other.m[1][3]; |
315 | m[2][0] -= other.m[2][0]; |
316 | m[2][1] -= other.m[2][1]; |
317 | m[2][2] -= other.m[2][2]; |
318 | m[2][3] -= other.m[2][3]; |
319 | m[3][0] -= other.m[3][0]; |
320 | m[3][1] -= other.m[3][1]; |
321 | m[3][2] -= other.m[3][2]; |
322 | m[3][3] -= other.m[3][3]; |
323 | flagBits = General; |
324 | return *this; |
325 | } |
326 | |
327 | inline QDoubleMatrix4x4& QDoubleMatrix4x4::operator*=(const QDoubleMatrix4x4& other) |
328 | { |
329 | flagBits |= other.flagBits; |
330 | |
331 | if (flagBits < Rotation2D) { |
332 | m[3][0] += m[0][0] * other.m[3][0]; |
333 | m[3][1] += m[1][1] * other.m[3][1]; |
334 | m[3][2] += m[2][2] * other.m[3][2]; |
335 | |
336 | m[0][0] *= other.m[0][0]; |
337 | m[1][1] *= other.m[1][1]; |
338 | m[2][2] *= other.m[2][2]; |
339 | return *this; |
340 | } |
341 | |
342 | double m0, m1, m2; |
343 | m0 = m[0][0] * other.m[0][0] |
344 | + m[1][0] * other.m[0][1] |
345 | + m[2][0] * other.m[0][2] |
346 | + m[3][0] * other.m[0][3]; |
347 | m1 = m[0][0] * other.m[1][0] |
348 | + m[1][0] * other.m[1][1] |
349 | + m[2][0] * other.m[1][2] |
350 | + m[3][0] * other.m[1][3]; |
351 | m2 = m[0][0] * other.m[2][0] |
352 | + m[1][0] * other.m[2][1] |
353 | + m[2][0] * other.m[2][2] |
354 | + m[3][0] * other.m[2][3]; |
355 | m[3][0] = m[0][0] * other.m[3][0] |
356 | + m[1][0] * other.m[3][1] |
357 | + m[2][0] * other.m[3][2] |
358 | + m[3][0] * other.m[3][3]; |
359 | m[0][0] = m0; |
360 | m[1][0] = m1; |
361 | m[2][0] = m2; |
362 | |
363 | m0 = m[0][1] * other.m[0][0] |
364 | + m[1][1] * other.m[0][1] |
365 | + m[2][1] * other.m[0][2] |
366 | + m[3][1] * other.m[0][3]; |
367 | m1 = m[0][1] * other.m[1][0] |
368 | + m[1][1] * other.m[1][1] |
369 | + m[2][1] * other.m[1][2] |
370 | + m[3][1] * other.m[1][3]; |
371 | m2 = m[0][1] * other.m[2][0] |
372 | + m[1][1] * other.m[2][1] |
373 | + m[2][1] * other.m[2][2] |
374 | + m[3][1] * other.m[2][3]; |
375 | m[3][1] = m[0][1] * other.m[3][0] |
376 | + m[1][1] * other.m[3][1] |
377 | + m[2][1] * other.m[3][2] |
378 | + m[3][1] * other.m[3][3]; |
379 | m[0][1] = m0; |
380 | m[1][1] = m1; |
381 | m[2][1] = m2; |
382 | |
383 | m0 = m[0][2] * other.m[0][0] |
384 | + m[1][2] * other.m[0][1] |
385 | + m[2][2] * other.m[0][2] |
386 | + m[3][2] * other.m[0][3]; |
387 | m1 = m[0][2] * other.m[1][0] |
388 | + m[1][2] * other.m[1][1] |
389 | + m[2][2] * other.m[1][2] |
390 | + m[3][2] * other.m[1][3]; |
391 | m2 = m[0][2] * other.m[2][0] |
392 | + m[1][2] * other.m[2][1] |
393 | + m[2][2] * other.m[2][2] |
394 | + m[3][2] * other.m[2][3]; |
395 | m[3][2] = m[0][2] * other.m[3][0] |
396 | + m[1][2] * other.m[3][1] |
397 | + m[2][2] * other.m[3][2] |
398 | + m[3][2] * other.m[3][3]; |
399 | m[0][2] = m0; |
400 | m[1][2] = m1; |
401 | m[2][2] = m2; |
402 | |
403 | m0 = m[0][3] * other.m[0][0] |
404 | + m[1][3] * other.m[0][1] |
405 | + m[2][3] * other.m[0][2] |
406 | + m[3][3] * other.m[0][3]; |
407 | m1 = m[0][3] * other.m[1][0] |
408 | + m[1][3] * other.m[1][1] |
409 | + m[2][3] * other.m[1][2] |
410 | + m[3][3] * other.m[1][3]; |
411 | m2 = m[0][3] * other.m[2][0] |
412 | + m[1][3] * other.m[2][1] |
413 | + m[2][3] * other.m[2][2] |
414 | + m[3][3] * other.m[2][3]; |
415 | m[3][3] = m[0][3] * other.m[3][0] |
416 | + m[1][3] * other.m[3][1] |
417 | + m[2][3] * other.m[3][2] |
418 | + m[3][3] * other.m[3][3]; |
419 | m[0][3] = m0; |
420 | m[1][3] = m1; |
421 | m[2][3] = m2; |
422 | return *this; |
423 | } |
424 | |
425 | inline QDoubleMatrix4x4& QDoubleMatrix4x4::operator*=(double factor) |
426 | { |
427 | m[0][0] *= factor; |
428 | m[0][1] *= factor; |
429 | m[0][2] *= factor; |
430 | m[0][3] *= factor; |
431 | m[1][0] *= factor; |
432 | m[1][1] *= factor; |
433 | m[1][2] *= factor; |
434 | m[1][3] *= factor; |
435 | m[2][0] *= factor; |
436 | m[2][1] *= factor; |
437 | m[2][2] *= factor; |
438 | m[2][3] *= factor; |
439 | m[3][0] *= factor; |
440 | m[3][1] *= factor; |
441 | m[3][2] *= factor; |
442 | m[3][3] *= factor; |
443 | flagBits = General; |
444 | return *this; |
445 | } |
446 | |
447 | inline bool QDoubleMatrix4x4::operator==(const QDoubleMatrix4x4& other) const |
448 | { |
449 | return m[0][0] == other.m[0][0] && |
450 | m[0][1] == other.m[0][1] && |
451 | m[0][2] == other.m[0][2] && |
452 | m[0][3] == other.m[0][3] && |
453 | m[1][0] == other.m[1][0] && |
454 | m[1][1] == other.m[1][1] && |
455 | m[1][2] == other.m[1][2] && |
456 | m[1][3] == other.m[1][3] && |
457 | m[2][0] == other.m[2][0] && |
458 | m[2][1] == other.m[2][1] && |
459 | m[2][2] == other.m[2][2] && |
460 | m[2][3] == other.m[2][3] && |
461 | m[3][0] == other.m[3][0] && |
462 | m[3][1] == other.m[3][1] && |
463 | m[3][2] == other.m[3][2] && |
464 | m[3][3] == other.m[3][3]; |
465 | } |
466 | |
467 | inline bool QDoubleMatrix4x4::operator!=(const QDoubleMatrix4x4& other) const |
468 | { |
469 | return m[0][0] != other.m[0][0] || |
470 | m[0][1] != other.m[0][1] || |
471 | m[0][2] != other.m[0][2] || |
472 | m[0][3] != other.m[0][3] || |
473 | m[1][0] != other.m[1][0] || |
474 | m[1][1] != other.m[1][1] || |
475 | m[1][2] != other.m[1][2] || |
476 | m[1][3] != other.m[1][3] || |
477 | m[2][0] != other.m[2][0] || |
478 | m[2][1] != other.m[2][1] || |
479 | m[2][2] != other.m[2][2] || |
480 | m[2][3] != other.m[2][3] || |
481 | m[3][0] != other.m[3][0] || |
482 | m[3][1] != other.m[3][1] || |
483 | m[3][2] != other.m[3][2] || |
484 | m[3][3] != other.m[3][3]; |
485 | } |
486 | |
487 | inline QDoubleMatrix4x4 operator+(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2) |
488 | { |
489 | QDoubleMatrix4x4 m(1); |
490 | m.m[0][0] = m1.m[0][0] + m2.m[0][0]; |
491 | m.m[0][1] = m1.m[0][1] + m2.m[0][1]; |
492 | m.m[0][2] = m1.m[0][2] + m2.m[0][2]; |
493 | m.m[0][3] = m1.m[0][3] + m2.m[0][3]; |
494 | m.m[1][0] = m1.m[1][0] + m2.m[1][0]; |
495 | m.m[1][1] = m1.m[1][1] + m2.m[1][1]; |
496 | m.m[1][2] = m1.m[1][2] + m2.m[1][2]; |
497 | m.m[1][3] = m1.m[1][3] + m2.m[1][3]; |
498 | m.m[2][0] = m1.m[2][0] + m2.m[2][0]; |
499 | m.m[2][1] = m1.m[2][1] + m2.m[2][1]; |
500 | m.m[2][2] = m1.m[2][2] + m2.m[2][2]; |
501 | m.m[2][3] = m1.m[2][3] + m2.m[2][3]; |
502 | m.m[3][0] = m1.m[3][0] + m2.m[3][0]; |
503 | m.m[3][1] = m1.m[3][1] + m2.m[3][1]; |
504 | m.m[3][2] = m1.m[3][2] + m2.m[3][2]; |
505 | m.m[3][3] = m1.m[3][3] + m2.m[3][3]; |
506 | m.flagBits = QDoubleMatrix4x4::General; |
507 | return m; |
508 | } |
509 | |
510 | inline QDoubleMatrix4x4 operator-(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2) |
511 | { |
512 | QDoubleMatrix4x4 m(1); |
513 | m.m[0][0] = m1.m[0][0] - m2.m[0][0]; |
514 | m.m[0][1] = m1.m[0][1] - m2.m[0][1]; |
515 | m.m[0][2] = m1.m[0][2] - m2.m[0][2]; |
516 | m.m[0][3] = m1.m[0][3] - m2.m[0][3]; |
517 | m.m[1][0] = m1.m[1][0] - m2.m[1][0]; |
518 | m.m[1][1] = m1.m[1][1] - m2.m[1][1]; |
519 | m.m[1][2] = m1.m[1][2] - m2.m[1][2]; |
520 | m.m[1][3] = m1.m[1][3] - m2.m[1][3]; |
521 | m.m[2][0] = m1.m[2][0] - m2.m[2][0]; |
522 | m.m[2][1] = m1.m[2][1] - m2.m[2][1]; |
523 | m.m[2][2] = m1.m[2][2] - m2.m[2][2]; |
524 | m.m[2][3] = m1.m[2][3] - m2.m[2][3]; |
525 | m.m[3][0] = m1.m[3][0] - m2.m[3][0]; |
526 | m.m[3][1] = m1.m[3][1] - m2.m[3][1]; |
527 | m.m[3][2] = m1.m[3][2] - m2.m[3][2]; |
528 | m.m[3][3] = m1.m[3][3] - m2.m[3][3]; |
529 | m.flagBits = QDoubleMatrix4x4::General; |
530 | return m; |
531 | } |
532 | |
533 | inline QDoubleMatrix4x4 operator*(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2) |
534 | { |
535 | int flagBits = m1.flagBits | m2.flagBits; |
536 | if (flagBits < QDoubleMatrix4x4::Rotation2D) { |
537 | QDoubleMatrix4x4 m = m1; |
538 | m.m[3][0] += m.m[0][0] * m2.m[3][0]; |
539 | m.m[3][1] += m.m[1][1] * m2.m[3][1]; |
540 | m.m[3][2] += m.m[2][2] * m2.m[3][2]; |
541 | |
542 | m.m[0][0] *= m2.m[0][0]; |
543 | m.m[1][1] *= m2.m[1][1]; |
544 | m.m[2][2] *= m2.m[2][2]; |
545 | m.flagBits = flagBits; |
546 | return m; |
547 | } |
548 | |
549 | QDoubleMatrix4x4 m(1); |
550 | m.m[0][0] = m1.m[0][0] * m2.m[0][0] |
551 | + m1.m[1][0] * m2.m[0][1] |
552 | + m1.m[2][0] * m2.m[0][2] |
553 | + m1.m[3][0] * m2.m[0][3]; |
554 | m.m[0][1] = m1.m[0][1] * m2.m[0][0] |
555 | + m1.m[1][1] * m2.m[0][1] |
556 | + m1.m[2][1] * m2.m[0][2] |
557 | + m1.m[3][1] * m2.m[0][3]; |
558 | m.m[0][2] = m1.m[0][2] * m2.m[0][0] |
559 | + m1.m[1][2] * m2.m[0][1] |
560 | + m1.m[2][2] * m2.m[0][2] |
561 | + m1.m[3][2] * m2.m[0][3]; |
562 | m.m[0][3] = m1.m[0][3] * m2.m[0][0] |
563 | + m1.m[1][3] * m2.m[0][1] |
564 | + m1.m[2][3] * m2.m[0][2] |
565 | + m1.m[3][3] * m2.m[0][3]; |
566 | |
567 | m.m[1][0] = m1.m[0][0] * m2.m[1][0] |
568 | + m1.m[1][0] * m2.m[1][1] |
569 | + m1.m[2][0] * m2.m[1][2] |
570 | + m1.m[3][0] * m2.m[1][3]; |
571 | m.m[1][1] = m1.m[0][1] * m2.m[1][0] |
572 | + m1.m[1][1] * m2.m[1][1] |
573 | + m1.m[2][1] * m2.m[1][2] |
574 | + m1.m[3][1] * m2.m[1][3]; |
575 | m.m[1][2] = m1.m[0][2] * m2.m[1][0] |
576 | + m1.m[1][2] * m2.m[1][1] |
577 | + m1.m[2][2] * m2.m[1][2] |
578 | + m1.m[3][2] * m2.m[1][3]; |
579 | m.m[1][3] = m1.m[0][3] * m2.m[1][0] |
580 | + m1.m[1][3] * m2.m[1][1] |
581 | + m1.m[2][3] * m2.m[1][2] |
582 | + m1.m[3][3] * m2.m[1][3]; |
583 | |
584 | m.m[2][0] = m1.m[0][0] * m2.m[2][0] |
585 | + m1.m[1][0] * m2.m[2][1] |
586 | + m1.m[2][0] * m2.m[2][2] |
587 | + m1.m[3][0] * m2.m[2][3]; |
588 | m.m[2][1] = m1.m[0][1] * m2.m[2][0] |
589 | + m1.m[1][1] * m2.m[2][1] |
590 | + m1.m[2][1] * m2.m[2][2] |
591 | + m1.m[3][1] * m2.m[2][3]; |
592 | m.m[2][2] = m1.m[0][2] * m2.m[2][0] |
593 | + m1.m[1][2] * m2.m[2][1] |
594 | + m1.m[2][2] * m2.m[2][2] |
595 | + m1.m[3][2] * m2.m[2][3]; |
596 | m.m[2][3] = m1.m[0][3] * m2.m[2][0] |
597 | + m1.m[1][3] * m2.m[2][1] |
598 | + m1.m[2][3] * m2.m[2][2] |
599 | + m1.m[3][3] * m2.m[2][3]; |
600 | |
601 | m.m[3][0] = m1.m[0][0] * m2.m[3][0] |
602 | + m1.m[1][0] * m2.m[3][1] |
603 | + m1.m[2][0] * m2.m[3][2] |
604 | + m1.m[3][0] * m2.m[3][3]; |
605 | m.m[3][1] = m1.m[0][1] * m2.m[3][0] |
606 | + m1.m[1][1] * m2.m[3][1] |
607 | + m1.m[2][1] * m2.m[3][2] |
608 | + m1.m[3][1] * m2.m[3][3]; |
609 | m.m[3][2] = m1.m[0][2] * m2.m[3][0] |
610 | + m1.m[1][2] * m2.m[3][1] |
611 | + m1.m[2][2] * m2.m[3][2] |
612 | + m1.m[3][2] * m2.m[3][3]; |
613 | m.m[3][3] = m1.m[0][3] * m2.m[3][0] |
614 | + m1.m[1][3] * m2.m[3][1] |
615 | + m1.m[2][3] * m2.m[3][2] |
616 | + m1.m[3][3] * m2.m[3][3]; |
617 | m.flagBits = flagBits; |
618 | return m; |
619 | } |
620 | |
621 | inline QDoubleVector3D operator*(const QDoubleVector3D& vector, const QDoubleMatrix4x4& matrix) |
622 | { |
623 | double x, y, z, w; |
624 | x = vector.x() * matrix.m[0][0] + |
625 | vector.y() * matrix.m[0][1] + |
626 | vector.z() * matrix.m[0][2] + |
627 | matrix.m[0][3]; |
628 | y = vector.x() * matrix.m[1][0] + |
629 | vector.y() * matrix.m[1][1] + |
630 | vector.z() * matrix.m[1][2] + |
631 | matrix.m[1][3]; |
632 | z = vector.x() * matrix.m[2][0] + |
633 | vector.y() * matrix.m[2][1] + |
634 | vector.z() * matrix.m[2][2] + |
635 | matrix.m[2][3]; |
636 | w = vector.x() * matrix.m[3][0] + |
637 | vector.y() * matrix.m[3][1] + |
638 | vector.z() * matrix.m[3][2] + |
639 | matrix.m[3][3]; |
640 | if (w == 1.0f) |
641 | return QDoubleVector3D(x, y, z); |
642 | else |
643 | return QDoubleVector3D(x / w, y / w, z / w); |
644 | } |
645 | |
646 | inline QDoubleVector3D operator*(const QDoubleMatrix4x4& matrix, const QDoubleVector3D& vector) |
647 | { |
648 | double x, y, z, w; |
649 | if (matrix.flagBits == QDoubleMatrix4x4::Identity) { |
650 | return vector; |
651 | } else if (matrix.flagBits < QDoubleMatrix4x4::Rotation2D) { |
652 | // Translation | Scale |
653 | return QDoubleVector3D(vector.x() * matrix.m[0][0] + matrix.m[3][0], |
654 | vector.y() * matrix.m[1][1] + matrix.m[3][1], |
655 | vector.z() * matrix.m[2][2] + matrix.m[3][2]); |
656 | } else if (matrix.flagBits < QDoubleMatrix4x4::Rotation) { |
657 | // Translation | Scale | Rotation2D |
658 | return QDoubleVector3D(vector.x() * matrix.m[0][0] + vector.y() * matrix.m[1][0] + matrix.m[3][0], |
659 | vector.x() * matrix.m[0][1] + vector.y() * matrix.m[1][1] + matrix.m[3][1], |
660 | vector.z() * matrix.m[2][2] + matrix.m[3][2]); |
661 | } else { |
662 | x = vector.x() * matrix.m[0][0] + |
663 | vector.y() * matrix.m[1][0] + |
664 | vector.z() * matrix.m[2][0] + |
665 | matrix.m[3][0]; |
666 | y = vector.x() * matrix.m[0][1] + |
667 | vector.y() * matrix.m[1][1] + |
668 | vector.z() * matrix.m[2][1] + |
669 | matrix.m[3][1]; |
670 | z = vector.x() * matrix.m[0][2] + |
671 | vector.y() * matrix.m[1][2] + |
672 | vector.z() * matrix.m[2][2] + |
673 | matrix.m[3][2]; |
674 | w = vector.x() * matrix.m[0][3] + |
675 | vector.y() * matrix.m[1][3] + |
676 | vector.z() * matrix.m[2][3] + |
677 | matrix.m[3][3]; |
678 | if (w == 1.0f) |
679 | return QDoubleVector3D(x, y, z); |
680 | else |
681 | return QDoubleVector3D(x / w, y / w, z / w); |
682 | } |
683 | } |
684 | |
685 | inline QPoint operator*(const QPoint& point, const QDoubleMatrix4x4& matrix) |
686 | { |
687 | double xin, yin; |
688 | double x, y, w; |
689 | xin = point.x(); |
690 | yin = point.y(); |
691 | x = xin * matrix.m[0][0] + |
692 | yin * matrix.m[0][1] + |
693 | matrix.m[0][3]; |
694 | y = xin * matrix.m[1][0] + |
695 | yin * matrix.m[1][1] + |
696 | matrix.m[1][3]; |
697 | w = xin * matrix.m[3][0] + |
698 | yin * matrix.m[3][1] + |
699 | matrix.m[3][3]; |
700 | if (w == 1.0f) |
701 | return QPoint(qRound(d: x), qRound(d: y)); |
702 | else |
703 | return QPoint(qRound(d: x / w), qRound(d: y / w)); |
704 | } |
705 | |
706 | inline QPointF operator*(const QPointF& point, const QDoubleMatrix4x4& matrix) |
707 | { |
708 | double xin, yin; |
709 | double x, y, w; |
710 | xin = point.x(); |
711 | yin = point.y(); |
712 | x = xin * matrix.m[0][0] + |
713 | yin * matrix.m[0][1] + |
714 | matrix.m[0][3]; |
715 | y = xin * matrix.m[1][0] + |
716 | yin * matrix.m[1][1] + |
717 | matrix.m[1][3]; |
718 | w = xin * matrix.m[3][0] + |
719 | yin * matrix.m[3][1] + |
720 | matrix.m[3][3]; |
721 | if (w == 1.0f) { |
722 | return QPointF(double(x), double(y)); |
723 | } else { |
724 | return QPointF(double(x / w), double(y / w)); |
725 | } |
726 | } |
727 | |
728 | inline QPoint operator*(const QDoubleMatrix4x4& matrix, const QPoint& point) |
729 | { |
730 | double xin, yin; |
731 | double x, y, w; |
732 | xin = point.x(); |
733 | yin = point.y(); |
734 | if (matrix.flagBits == QDoubleMatrix4x4::Identity) { |
735 | return point; |
736 | } else if (matrix.flagBits < QDoubleMatrix4x4::Rotation2D) { |
737 | // Translation | Scale |
738 | return QPoint(qRound(d: xin * matrix.m[0][0] + matrix.m[3][0]), |
739 | qRound(d: yin * matrix.m[1][1] + matrix.m[3][1])); |
740 | } else if (matrix.flagBits < QDoubleMatrix4x4::Perspective) { |
741 | return QPoint(qRound(d: xin * matrix.m[0][0] + yin * matrix.m[1][0] + matrix.m[3][0]), |
742 | qRound(d: xin * matrix.m[0][1] + yin * matrix.m[1][1] + matrix.m[3][1])); |
743 | } else { |
744 | x = xin * matrix.m[0][0] + |
745 | yin * matrix.m[1][0] + |
746 | matrix.m[3][0]; |
747 | y = xin * matrix.m[0][1] + |
748 | yin * matrix.m[1][1] + |
749 | matrix.m[3][1]; |
750 | w = xin * matrix.m[0][3] + |
751 | yin * matrix.m[1][3] + |
752 | matrix.m[3][3]; |
753 | if (w == 1.0f) |
754 | return QPoint(qRound(d: x), qRound(d: y)); |
755 | else |
756 | return QPoint(qRound(d: x / w), qRound(d: y / w)); |
757 | } |
758 | } |
759 | |
760 | inline QPointF operator*(const QDoubleMatrix4x4& matrix, const QPointF& point) |
761 | { |
762 | double xin, yin; |
763 | double x, y, w; |
764 | xin = point.x(); |
765 | yin = point.y(); |
766 | if (matrix.flagBits == QDoubleMatrix4x4::Identity) { |
767 | return point; |
768 | } else if (matrix.flagBits < QDoubleMatrix4x4::Rotation2D) { |
769 | // Translation | Scale |
770 | return QPointF(xin * matrix.m[0][0] + matrix.m[3][0], |
771 | yin * matrix.m[1][1] + matrix.m[3][1]); |
772 | } else if (matrix.flagBits < QDoubleMatrix4x4::Perspective) { |
773 | return QPointF(xin * matrix.m[0][0] + yin * matrix.m[1][0] + matrix.m[3][0], |
774 | xin * matrix.m[0][1] + yin * matrix.m[1][1] + matrix.m[3][1]); |
775 | } else { |
776 | x = xin * matrix.m[0][0] + |
777 | yin * matrix.m[1][0] + |
778 | matrix.m[3][0]; |
779 | y = xin * matrix.m[0][1] + |
780 | yin * matrix.m[1][1] + |
781 | matrix.m[3][1]; |
782 | w = xin * matrix.m[0][3] + |
783 | yin * matrix.m[1][3] + |
784 | matrix.m[3][3]; |
785 | if (w == 1.0f) { |
786 | return QPointF(double(x), double(y)); |
787 | } else { |
788 | return QPointF(double(x / w), double(y / w)); |
789 | } |
790 | } |
791 | } |
792 | |
793 | inline QDoubleMatrix4x4 operator-(const QDoubleMatrix4x4& matrix) |
794 | { |
795 | QDoubleMatrix4x4 m(1); |
796 | m.m[0][0] = -matrix.m[0][0]; |
797 | m.m[0][1] = -matrix.m[0][1]; |
798 | m.m[0][2] = -matrix.m[0][2]; |
799 | m.m[0][3] = -matrix.m[0][3]; |
800 | m.m[1][0] = -matrix.m[1][0]; |
801 | m.m[1][1] = -matrix.m[1][1]; |
802 | m.m[1][2] = -matrix.m[1][2]; |
803 | m.m[1][3] = -matrix.m[1][3]; |
804 | m.m[2][0] = -matrix.m[2][0]; |
805 | m.m[2][1] = -matrix.m[2][1]; |
806 | m.m[2][2] = -matrix.m[2][2]; |
807 | m.m[2][3] = -matrix.m[2][3]; |
808 | m.m[3][0] = -matrix.m[3][0]; |
809 | m.m[3][1] = -matrix.m[3][1]; |
810 | m.m[3][2] = -matrix.m[3][2]; |
811 | m.m[3][3] = -matrix.m[3][3]; |
812 | m.flagBits = QDoubleMatrix4x4::General; |
813 | return m; |
814 | } |
815 | |
816 | inline QDoubleMatrix4x4 operator*(double factor, const QDoubleMatrix4x4& matrix) |
817 | { |
818 | QDoubleMatrix4x4 m(1); |
819 | m.m[0][0] = matrix.m[0][0] * factor; |
820 | m.m[0][1] = matrix.m[0][1] * factor; |
821 | m.m[0][2] = matrix.m[0][2] * factor; |
822 | m.m[0][3] = matrix.m[0][3] * factor; |
823 | m.m[1][0] = matrix.m[1][0] * factor; |
824 | m.m[1][1] = matrix.m[1][1] * factor; |
825 | m.m[1][2] = matrix.m[1][2] * factor; |
826 | m.m[1][3] = matrix.m[1][3] * factor; |
827 | m.m[2][0] = matrix.m[2][0] * factor; |
828 | m.m[2][1] = matrix.m[2][1] * factor; |
829 | m.m[2][2] = matrix.m[2][2] * factor; |
830 | m.m[2][3] = matrix.m[2][3] * factor; |
831 | m.m[3][0] = matrix.m[3][0] * factor; |
832 | m.m[3][1] = matrix.m[3][1] * factor; |
833 | m.m[3][2] = matrix.m[3][2] * factor; |
834 | m.m[3][3] = matrix.m[3][3] * factor; |
835 | m.flagBits = QDoubleMatrix4x4::General; |
836 | return m; |
837 | } |
838 | |
839 | inline QDoubleMatrix4x4 operator*(const QDoubleMatrix4x4& matrix, double factor) |
840 | { |
841 | QDoubleMatrix4x4 m(1); |
842 | m.m[0][0] = matrix.m[0][0] * factor; |
843 | m.m[0][1] = matrix.m[0][1] * factor; |
844 | m.m[0][2] = matrix.m[0][2] * factor; |
845 | m.m[0][3] = matrix.m[0][3] * factor; |
846 | m.m[1][0] = matrix.m[1][0] * factor; |
847 | m.m[1][1] = matrix.m[1][1] * factor; |
848 | m.m[1][2] = matrix.m[1][2] * factor; |
849 | m.m[1][3] = matrix.m[1][3] * factor; |
850 | m.m[2][0] = matrix.m[2][0] * factor; |
851 | m.m[2][1] = matrix.m[2][1] * factor; |
852 | m.m[2][2] = matrix.m[2][2] * factor; |
853 | m.m[2][3] = matrix.m[2][3] * factor; |
854 | m.m[3][0] = matrix.m[3][0] * factor; |
855 | m.m[3][1] = matrix.m[3][1] * factor; |
856 | m.m[3][2] = matrix.m[3][2] * factor; |
857 | m.m[3][3] = matrix.m[3][3] * factor; |
858 | m.flagBits = QDoubleMatrix4x4::General; |
859 | return m; |
860 | } |
861 | |
862 | inline bool qFuzzyCompare(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2) |
863 | { |
864 | return qFuzzyCompare(p1: m1.m[0][0], p2: m2.m[0][0]) && |
865 | qFuzzyCompare(p1: m1.m[0][1], p2: m2.m[0][1]) && |
866 | qFuzzyCompare(p1: m1.m[0][2], p2: m2.m[0][2]) && |
867 | qFuzzyCompare(p1: m1.m[0][3], p2: m2.m[0][3]) && |
868 | qFuzzyCompare(p1: m1.m[1][0], p2: m2.m[1][0]) && |
869 | qFuzzyCompare(p1: m1.m[1][1], p2: m2.m[1][1]) && |
870 | qFuzzyCompare(p1: m1.m[1][2], p2: m2.m[1][2]) && |
871 | qFuzzyCompare(p1: m1.m[1][3], p2: m2.m[1][3]) && |
872 | qFuzzyCompare(p1: m1.m[2][0], p2: m2.m[2][0]) && |
873 | qFuzzyCompare(p1: m1.m[2][1], p2: m2.m[2][1]) && |
874 | qFuzzyCompare(p1: m1.m[2][2], p2: m2.m[2][2]) && |
875 | qFuzzyCompare(p1: m1.m[2][3], p2: m2.m[2][3]) && |
876 | qFuzzyCompare(p1: m1.m[3][0], p2: m2.m[3][0]) && |
877 | qFuzzyCompare(p1: m1.m[3][1], p2: m2.m[3][1]) && |
878 | qFuzzyCompare(p1: m1.m[3][2], p2: m2.m[3][2]) && |
879 | qFuzzyCompare(p1: m1.m[3][3], p2: m2.m[3][3]); |
880 | } |
881 | |
882 | inline QPoint QDoubleMatrix4x4::map(const QPoint& point) const |
883 | { |
884 | return *this * point; |
885 | } |
886 | |
887 | inline QPointF QDoubleMatrix4x4::map(const QPointF& point) const |
888 | { |
889 | return *this * point; |
890 | } |
891 | |
892 | inline QDoubleVector3D QDoubleMatrix4x4::map(const QDoubleVector3D& point) const |
893 | { |
894 | return *this * point; |
895 | } |
896 | |
897 | inline QDoubleVector3D QDoubleMatrix4x4::mapVector(const QDoubleVector3D& vector) const |
898 | { |
899 | if (flagBits < Scale) { |
900 | // Translation |
901 | return vector; |
902 | } else if (flagBits < Rotation2D) { |
903 | // Translation | Scale |
904 | return QDoubleVector3D(vector.x() * m[0][0], |
905 | vector.y() * m[1][1], |
906 | vector.z() * m[2][2]); |
907 | } else { |
908 | return QDoubleVector3D(vector.x() * m[0][0] + |
909 | vector.y() * m[1][0] + |
910 | vector.z() * m[2][0], |
911 | vector.x() * m[0][1] + |
912 | vector.y() * m[1][1] + |
913 | vector.z() * m[2][1], |
914 | vector.x() * m[0][2] + |
915 | vector.y() * m[1][2] + |
916 | vector.z() * m[2][2]); |
917 | } |
918 | } |
919 | |
920 | inline double *QDoubleMatrix4x4::data() |
921 | { |
922 | // We have to assume that the caller will modify the matrix elements, |
923 | // so we flip it over to "General" mode. |
924 | flagBits = General; |
925 | return *m; |
926 | } |
927 | |
928 | inline void QDoubleMatrix4x4::viewport(const QRectF &rect) |
929 | { |
930 | viewport(left: rect.x(), bottom: rect.y(), width: rect.width(), height: rect.height()); |
931 | } |
932 | |
933 | #ifndef QT_NO_DEBUG_STREAM |
934 | Q_POSITIONING_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QDoubleMatrix4x4 &m); |
935 | #endif |
936 | |
937 | #ifndef QT_NO_DATASTREAM |
938 | Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDoubleMatrix4x4 &); |
939 | Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDoubleMatrix4x4 &); |
940 | #endif |
941 | |
942 | |
943 | QT_END_NAMESPACE |
944 | |
945 | |
946 | #endif // QDOUBLEMATRIX4X4_H |
947 | |