QGIS API Documentation 4.1.0-Master (009143bf4b4)
Loading...
Searching...
No Matches
qgsmatrix4x4.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmatrix4x4.cpp
3 --------------------------------------
4 Date : July 2023
5 Copyright : (C) 2023 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsmatrix4x4.h"
17
18// the implementation is partially based on Qt's QMatrix4x4 (simplified)
19
20
21// clang-format off
23 double m11, double m12, double m13, double m14,
24 double m21, double m22, double m23, double m24,
25 double m31, double m32, double m33, double m34,
26 double m41, double m42, double m43, double m44
27)
28// clang-format on
29{
30 m[0][0] = m11;
31 m[0][1] = m21;
32 m[0][2] = m31;
33 m[0][3] = m41;
34 m[1][0] = m12;
35 m[1][1] = m22;
36 m[1][2] = m32;
37 m[1][3] = m42;
38 m[2][0] = m13;
39 m[2][1] = m23;
40 m[2][2] = m33;
41 m[2][3] = m43;
42 m[3][0] = m14;
43 m[3][1] = m24;
44 m[3][2] = m34;
45 m[3][3] = m44;
46}
47
49{
50 m[3][0] += m[0][0] * vector.x() + m[1][0] * vector.y() + m[2][0] * vector.z();
51 m[3][1] += m[0][1] * vector.x() + m[1][1] * vector.y() + m[2][1] * vector.z();
52 m[3][2] += m[0][2] * vector.x() + m[1][2] * vector.y() + m[2][2] * vector.z();
53 m[3][3] += m[0][3] * vector.x() + m[1][3] * vector.y() + m[2][3] * vector.z();
54}
55
56QList< double > QgsMatrix4x4::dataList() const
57{
58 QList< double > res;
59 res.reserve( 16 );
60 for ( int i = 0; i < 16; ++i )
61 {
62 res.append( m[i / 4][i % 4] );
63 }
64 return res;
65}
66
67QgsVector3D operator*( const QgsMatrix4x4 &matrix, const QgsVector3D &vector )
68{
69 double x, y, z, w;
70
71 x = vector.x() * matrix.m[0][0] + vector.y() * matrix.m[1][0] + vector.z() * matrix.m[2][0] + matrix.m[3][0];
72 y = vector.x() * matrix.m[0][1] + vector.y() * matrix.m[1][1] + vector.z() * matrix.m[2][1] + matrix.m[3][1];
73 z = vector.x() * matrix.m[0][2] + vector.y() * matrix.m[1][2] + vector.z() * matrix.m[2][2] + matrix.m[3][2];
74 w = vector.x() * matrix.m[0][3] + vector.y() * matrix.m[1][3] + vector.z() * matrix.m[2][3] + matrix.m[3][3];
75 if ( w == 1.0 )
76 return QgsVector3D( x, y, z );
77 else
78 return QgsVector3D( x / w, y / w, z / w );
79}
80
82{
83 if ( m[0][0] != 1.0 || m[0][1] != 0.0 || m[0][2] != 0.0 )
84 return false;
85 if ( m[0][3] != 0.0 || m[1][0] != 0.0 || m[1][1] != 1.0 )
86 return false;
87 if ( m[1][2] != 0.0 || m[1][3] != 0.0 || m[2][0] != 0.0 )
88 return false;
89 if ( m[2][1] != 0.0 || m[2][2] != 1.0 || m[2][3] != 0.0 )
90 return false;
91 if ( m[3][0] != 0.0 || m[3][1] != 0.0 || m[3][2] != 0.0 )
92 return false;
93 return ( m[3][3] == 1.0 );
94}
95
97{
98 m[0][0] = 1.0;
99 m[0][1] = 0.0;
100 m[0][2] = 0.0;
101 m[0][3] = 0.0;
102 m[1][0] = 0.0;
103 m[1][1] = 1.0;
104 m[1][2] = 0.0;
105 m[1][3] = 0.0;
106 m[2][0] = 0.0;
107 m[2][1] = 0.0;
108 m[2][2] = 1.0;
109 m[2][3] = 0.0;
110 m[3][0] = 0.0;
111 m[3][1] = 0.0;
112 m[3][2] = 0.0;
113 m[3][3] = 1.0;
114}
115
116
118{
119 QgsMatrix4x4 m( 1 );
120 m.m[0][0] = m1.m[0][0] * m2.m[0][0] + m1.m[1][0] * m2.m[0][1] + m1.m[2][0] * m2.m[0][2] + m1.m[3][0] * m2.m[0][3];
121 m.m[0][1] = m1.m[0][1] * m2.m[0][0] + m1.m[1][1] * m2.m[0][1] + m1.m[2][1] * m2.m[0][2] + m1.m[3][1] * m2.m[0][3];
122 m.m[0][2] = m1.m[0][2] * m2.m[0][0] + m1.m[1][2] * m2.m[0][1] + m1.m[2][2] * m2.m[0][2] + m1.m[3][2] * m2.m[0][3];
123 m.m[0][3] = m1.m[0][3] * m2.m[0][0] + m1.m[1][3] * m2.m[0][1] + m1.m[2][3] * m2.m[0][2] + m1.m[3][3] * m2.m[0][3];
124
125 m.m[1][0] = m1.m[0][0] * m2.m[1][0] + m1.m[1][0] * m2.m[1][1] + m1.m[2][0] * m2.m[1][2] + m1.m[3][0] * m2.m[1][3];
126 m.m[1][1] = m1.m[0][1] * m2.m[1][0] + m1.m[1][1] * m2.m[1][1] + m1.m[2][1] * m2.m[1][2] + m1.m[3][1] * m2.m[1][3];
127 m.m[1][2] = m1.m[0][2] * m2.m[1][0] + m1.m[1][2] * m2.m[1][1] + m1.m[2][2] * m2.m[1][2] + m1.m[3][2] * m2.m[1][3];
128 m.m[1][3] = m1.m[0][3] * m2.m[1][0] + m1.m[1][3] * m2.m[1][1] + m1.m[2][3] * m2.m[1][2] + m1.m[3][3] * m2.m[1][3];
129
130 m.m[2][0] = m1.m[0][0] * m2.m[2][0] + m1.m[1][0] * m2.m[2][1] + m1.m[2][0] * m2.m[2][2] + m1.m[3][0] * m2.m[2][3];
131 m.m[2][1] = m1.m[0][1] * m2.m[2][0] + m1.m[1][1] * m2.m[2][1] + m1.m[2][1] * m2.m[2][2] + m1.m[3][1] * m2.m[2][3];
132 m.m[2][2] = m1.m[0][2] * m2.m[2][0] + m1.m[1][2] * m2.m[2][1] + m1.m[2][2] * m2.m[2][2] + m1.m[3][2] * m2.m[2][3];
133 m.m[2][3] = m1.m[0][3] * m2.m[2][0] + m1.m[1][3] * m2.m[2][1] + m1.m[2][3] * m2.m[2][2] + m1.m[3][3] * m2.m[2][3];
134
135 m.m[3][0] = m1.m[0][0] * m2.m[3][0] + m1.m[1][0] * m2.m[3][1] + m1.m[2][0] * m2.m[3][2] + m1.m[3][0] * m2.m[3][3];
136 m.m[3][1] = m1.m[0][1] * m2.m[3][0] + m1.m[1][1] * m2.m[3][1] + m1.m[2][1] * m2.m[3][2] + m1.m[3][1] * m2.m[3][3];
137 m.m[3][2] = m1.m[0][2] * m2.m[3][0] + m1.m[1][2] * m2.m[3][1] + m1.m[2][2] * m2.m[3][2] + m1.m[3][2] * m2.m[3][3];
138 m.m[3][3] = m1.m[0][3] * m2.m[3][0] + m1.m[1][3] * m2.m[3][1] + m1.m[2][3] * m2.m[3][2] + m1.m[3][3] * m2.m[3][3];
139 return m;
140}
141
142void QgsMatrix4x4::scale( const QgsVector3D &vector )
143{
144 m[0][0] *= vector.x();
145 m[0][1] *= vector.x();
146 m[0][2] *= vector.x();
147 m[0][3] *= vector.x();
148
149 m[1][0] *= vector.y();
150 m[1][1] *= vector.y();
151 m[1][2] *= vector.y();
152 m[1][3] *= vector.y();
153
154 m[2][0] *= vector.z();
155 m[2][1] *= vector.z();
156 m[2][2] *= vector.z();
157 m[2][3] *= vector.z();
158}
159
160void QgsMatrix4x4::rotate( double angle, double x, double y, double z )
161{
162 const double length = std::sqrt( x * x + y * y + z * z );
163 if ( qgsDoubleNear( length, 0.0 ) )
164 {
165 return;
166 }
167
168 const double nx = x / length;
169 const double ny = y / length;
170 const double nz = z / length;
171
172 const double angleRad = angle * M_PI / 180.0;
173 const double angleCos = std::cos( angleRad );
174 const double angleSin = std::sin( angleRad );
175 const double angleCosInv = 1.0 - angleCos;
176
177 const double nxny = nx * ny;
178 const double nxnz = nx * nz;
179 const double nynz = ny * nz;
180
181 // Rotation matrix
182 QgsMatrix4x4 rot;
183 rot.m[0][0] = angleCosInv * nx * nx + angleCos;
184 rot.m[0][1] = angleCosInv * nxny + nz * angleSin;
185 rot.m[0][2] = angleCosInv * nxnz - ny * angleSin;
186 rot.m[0][3] = 0.0;
187
188 rot.m[1][0] = angleCosInv * nxny - nz * angleSin;
189 rot.m[1][1] = angleCosInv * ny * ny + angleCos;
190 rot.m[1][2] = angleCosInv * nynz + nx * angleSin;
191 rot.m[1][3] = 0.0;
192
193 rot.m[2][0] = angleCosInv * nxnz + ny * angleSin;
194 rot.m[2][1] = angleCosInv * nynz - nx * angleSin;
195 rot.m[2][2] = angleCosInv * nz * nz + angleCos;
196 rot.m[2][3] = 0.0;
197
198 rot.m[3][0] = 0.0;
199 rot.m[3][1] = 0.0;
200 rot.m[3][2] = 0.0;
201 rot.m[3][3] = 1.0;
202
203 *this = *this * rot;
204}
205
206void QgsMatrix4x4::rotate( double angle, const QgsVector3D &vector )
207{
208 rotate( angle, vector.x(), vector.y(), vector.z() );
209}
void scale(const QgsVector3D &vector)
Multiplies this matrix by another that scales coordinates by the components of a vector.
QgsMatrix4x4()
Initializes identity matrix.
void setToIdentity()
Sets matrix to be identity matrix.
bool isIdentity() const
Returns whether this matrix is an identity matrix.
void translate(const QgsVector3D &vector)
Multiplies this matrix by another that translates coordinates by the components of a vector.
void rotate(double angle, double x, double y, double z)
Multiples this matrix by another that rotates coordinates through angle degrees about the vector (x,...
QList< double > dataList() const
Returns matrix data (in column-major order).
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
Definition qgsvector3d.h:33
double y() const
Returns Y coordinate.
Definition qgsvector3d.h:60
double z() const
Returns Z coordinate.
Definition qgsvector3d.h:62
double x() const
Returns X coordinate.
Definition qgsvector3d.h:58
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:7108
QgsVector3D operator*(const QgsMatrix4x4 &matrix, const QgsVector3D &vector)
Matrix-vector multiplication (vector is converted to homogeneous coordinates [X,Y,...