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
60QT_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
68class Q_POSITIONING_PRIVATE_EXPORT QDoubleMatrix4x4
69{
70public:
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
166private:
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
189Q_DECLARE_TYPEINFO(QDoubleMatrix4x4, Q_MOVABLE_TYPE);
190
191inline 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
204inline 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
210inline 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
217Q_POSITIONING_PRIVATE_EXPORT QDoubleMatrix4x4 operator/(const QDoubleMatrix4x4& matrix, double divisor);
218
219inline 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
224inline 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
241inline 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
262inline 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
283inline 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
305inline 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
327inline 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
425inline 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
447inline 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
467inline 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
487inline 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
510inline 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
533inline 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
621inline 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
646inline 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
685inline 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
706inline 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
728inline 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
760inline 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
793inline 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
816inline 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
839inline 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
862inline 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
882inline QPoint QDoubleMatrix4x4::map(const QPoint& point) const
883{
884 return *this * point;
885}
886
887inline QPointF QDoubleMatrix4x4::map(const QPointF& point) const
888{
889 return *this * point;
890}
891
892inline QDoubleVector3D QDoubleMatrix4x4::map(const QDoubleVector3D& point) const
893{
894 return *this * point;
895}
896
897inline 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
920inline 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
928inline 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
934Q_POSITIONING_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QDoubleMatrix4x4 &m);
935#endif
936
937#ifndef QT_NO_DATASTREAM
938Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDoubleMatrix4x4 &);
939Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDoubleMatrix4x4 &);
940#endif
941
942
943QT_END_NAMESPACE
944
945
946#endif // QDOUBLEMATRIX4X4_H
947

source code of qtlocation/src/positioning/qdoublematrix4x4_p.h