NAVTOR SDK  v.3.0
Software Development Kit for fast and efficient development of ECDIS, ECS and generic marine applications
matrix3x3.h
Go to the documentation of this file.
1 #ifndef SDK_MATRIX_3X3_H_
11 #define SDK_MATRIX_3X3_H_
12 
13 #define _USE_MATH_DEFINES
14 #include <math.h>
15 #include <base/inc/base_types.h>
17 #include "math_const.h"
18 #include "matrix_base_types.h"
19 
20 namespace sdk {
21 
24 template <class _SDKMatrix3X3>
25 class Matrix3X3T : public _SDKMatrix3X3
26 {
28 public:
29  typedef _SDKMatrix3X3 SDKMatrix3X3;
30  typedef typename SDKMatrix3X3::coordinate_type coordinate_type;
31  Matrix3X3T() noexcept
32  {
33  SetIdentity();
34  }
35  Matrix3X3T(const SDKMatrixF3X2& m) noexcept
36  {
37  // Source matrix can be 3X2, the additional row will be added
38  this->_11 = coordinate_type(m._11); this->_12 = coordinate_type(m._12); this->_13 = 0;
39  this->_21 = coordinate_type(m._21); this->_22 = coordinate_type(m._22); this->_23 = 0;
40  this->_31 = coordinate_type(m._31); this->_32 = coordinate_type(m._32); this->_33 = 1;
41  }
42  Matrix3X3T(const SDKMatrixD3X2& m) noexcept
43  {
44  // Source matrix can be 3X2, the additional row will be added
45  this->_11 = coordinate_type(m._11); this->_12 = coordinate_type(m._12); this->_13 = 0;
46  this->_21 = coordinate_type(m._21); this->_22 = coordinate_type(m._22); this->_23 = 0;
47  this->_31 = coordinate_type(m._31); this->_32 = coordinate_type(m._32); this->_33 = 1;
48  }
49  Matrix3X3T(const SDKMatrixF3X3& m) noexcept
50  {
51  this->_11 = coordinate_type(m._11); this->_12 = coordinate_type(m._12); this->_13 = coordinate_type(m._13);
52  this->_21 = coordinate_type(m._21); this->_22 = coordinate_type(m._22); this->_23 = coordinate_type(m._23);
53  this->_31 = coordinate_type(m._31); this->_32 = coordinate_type(m._32); this->_33 = coordinate_type(m._33);
54  }
55  Matrix3X3T(const SDKMatrixD3X3& m) noexcept
56  {
57  this->_11 = coordinate_type(m._11); this->_12 = coordinate_type(m._12); this->_13 = coordinate_type(m._13);
58  this->_21 = coordinate_type(m._21); this->_22 = coordinate_type(m._22); this->_23 = coordinate_type(m._23);
59  this->_31 = coordinate_type(m._31); this->_32 = coordinate_type(m._32); this->_33 = coordinate_type(m._33);
60  }
61  Matrix3X3T(double s11, double s12, double s13,
62  double s21, double s22, double s23,
63  double s31, double s32, double s33) noexcept
64  {
65  this->_11 = coordinate_type(s11); this->_12 = coordinate_type(s12); this->_13 = coordinate_type(s13);
66  this->_21 = coordinate_type(s21); this->_22 = coordinate_type(s22); this->_23 = coordinate_type(s23);
67  this->_31 = coordinate_type(s31); this->_32 = coordinate_type(s32); this->_33 = coordinate_type(s33);
68  }
69 
70  _MyType& operator=(const SDKMatrixF3X2& m) noexcept
71  {
72  this->_11 = coordinate_type(m._11); this->_12 = coordinate_type(m._12); this->_13 = 0;
73  this->_21 = coordinate_type(m._21); this->_22 = coordinate_type(m._22); this->_23 = 0;
74  this->_31 = coordinate_type(m._31); this->_32 = coordinate_type(m._32); this->_33 = 1;
75  return *this;
76  }
77 
78  _MyType& operator=(const SDKMatrixD3X2& m) noexcept
79  {
80  this->_11 = coordinate_type(m._11); this->_12 = coordinate_type(m._12); this->_13 = 0;
81  this->_21 = coordinate_type(m._21); this->_22 = coordinate_type(m._22); this->_23 = 0;
82  this->_31 = coordinate_type(m._31); this->_32 = coordinate_type(m._32); this->_33 = 1;
83  return *this;
84  }
85 
86  _MyType& operator=(const SDKMatrixF3X3& m) noexcept
87  {
88  this->_11 = coordinate_type(m._11); this->_12 = coordinate_type(m._12); this->_13 = coordinate_type(m._13);
89  this->_21 = coordinate_type(m._21); this->_22 = coordinate_type(m._22); this->_23 = coordinate_type(m._23);
90  this->_31 = coordinate_type(m._31); this->_32 = coordinate_type(m._32); this->_33 = coordinate_type(m._33);
91  return *this;
92  }
93 
94  _MyType& operator=(const SDKMatrixD3X3& m) noexcept
95  {
96  this->_11 = coordinate_type(m._11); this->_12 = coordinate_type(m._12); this->_13 = coordinate_type(m._13);
97  this->_21 = coordinate_type(m._21); this->_22 = coordinate_type(m._22); this->_23 = coordinate_type(m._23);
98  this->_31 = coordinate_type(m._31); this->_32 = coordinate_type(m._32); this->_33 = coordinate_type(m._33);
99  return *this;
100  }
101 
102  const SDKMatrix3X3& get() const noexcept
103  {
104  return *this;
105  }
106 
109  {
110  this->_11 = this->_22 = this->_33 = 1;
111  this->_12 = this->_13 = this->_21 = this->_23 = this->_31 = this->_32 = 0;
112  return *this;
113  }
114 
116  double Determinant() const noexcept
117  {
118  return (double(this->_11) * this->_22 * this->_33 -
119  double(this->_11) * this->_23 * this->_32 -
120  double(this->_12) * this->_21 * this->_33 +
121  double(this->_12) * this->_23 * this->_31 +
122  double(this->_13) * this->_21 * this->_32 -
123  double(this->_13) * this->_22 * this->_31);
124  }
125 
129  template <class Point>
130  _MyType& Rotate(double angle_deg, const Point& center) noexcept
131  {
132  return Rotate(angle_deg, center.x, center.y);
133  }
134 
135  _MyType& Rotate(double angle_deg, double center_x, double center_y) noexcept
136  {
137  SetIdentity();
138  double angle_rad = (angle_deg / 180) * kPI;
139  double s = sin(angle_rad);
140  double c = cos(angle_rad);
141 
142  this->_11 = coordinate_type(c);
143  this->_12 = coordinate_type(s);
144  this->_21 = coordinate_type(-s);
145  this->_22 = coordinate_type(c);
146  this->_31 = coordinate_type(-center_x * (c - 1) + center_y * s);
147  this->_32 = coordinate_type(-center_y * (c - 1) - center_x * s);
148 
149  return *this;
150  }
151 
153  _MyType& Translate(double shift_x, double shift_y) noexcept
154  {
155  SetIdentity();
156  this->_31 = coordinate_type(shift_x);
157  this->_32 = coordinate_type(shift_y);
158  return *this;
159  }
160 
162  _MyType& Scale(double scale_x, double scale_y) noexcept
163  {
164  SetIdentity();
165  this->_11 = coordinate_type(scale_x);
166  this->_22 = coordinate_type(scale_y);
167  return *this;
168  }
169 
170  // Transforms a point according to this matrix.
171  // / a b c \ / a * x + d * y + g \ T
172  // (x y 1) * | d e f | = | b * x + e * y + h |
173  // \ g h i / \ c * x + f * y + i /
174  SDKPointD2D Transform(const SDKPointD2D& point) const noexcept
175  {
176  SDKPointD2D res;
177  res.x = double(this->_11) * point.x + double(this->_21) * point.y + this->_31;
178  res.y = double(this->_12) * point.x + double(this->_22) * point.y + this->_32;
179  double w = double(this->_13) * point.x + double(this->_23) * point.y + this->_33;
180  res.x /= w;
181  res.y /= w;
182  return res;
183  }
184  SDKPointF2D Transform(const SDKPointF2D& point) const noexcept
185  {
186  SDKPointD2D res_d = {point.x, point.y};
187  res_d = Transform(res_d);
188  SDKPointF2D res = {float(res_d.x), float(res_d.y)};
189  return res;
190  }
191  SDKPointI2D Transform(const SDKPointI2D& point) const noexcept
192  {
193  SDKPointD2D res_d = {double(point.x), double(point.y)};
194  res_d = Transform(res_d);
195  SDKPointI2D res = {
196  RoundToNearest<SDKInt32>(res_d.x),
197  RoundToNearest<SDKInt32>(res_d.y)};
198  return res;
199  }
200  SDKRectD2D Transform(const SDKRectD2D& rect) const noexcept
201  {
202  SDKPointD2D pt_sw = { rect.x, rect.y };
203  SDKPointD2D pt_nw = { rect.x, rect.y + rect.height };
204  SDKPointD2D pt_se = { rect.x + rect.width, rect.y };
205  SDKPointD2D pt_ne = { rect.x + rect.width, rect.y + rect.height };
206  pt_sw = Transform(pt_sw);
207  pt_nw = Transform(pt_nw);
208  pt_se = Transform(pt_se);
209  pt_ne = Transform(pt_ne);
210  SDKRectD2D res;
211  res.x = min4dbl(pt_sw.x, pt_nw.x, pt_se.x, pt_ne.x);
212  res.y = min4dbl(pt_sw.y, pt_nw.y, pt_se.y, pt_ne.y);
213  res.width = max4dbl(pt_sw.x, pt_nw.x, pt_se.x, pt_ne.x) - res.x;
214  res.height = max4dbl(pt_sw.y, pt_nw.y, pt_se.y, pt_ne.y) - res.y;
215  return res;
216  }
217  SDKRectF2D Transform(const SDKRectF2D& rect) const noexcept
218  {
219  SDKRectD2D res_d = {
220  double(rect.x), double(rect.y),
221  double(rect.width), double(rect.height)};
222  res_d = Transform(res_d);
223  SDKRectF2D res = {
224  float(res_d.x),
225  float(res_d.y),
226  float(res_d.width),
227  float(res_d.height)};
228  return res;
229  }
230  SDKRectI2D Transform(const SDKRectI2D& rect) const noexcept
231  {
232  SDKRectD2D res_d = {
233  double(rect.x), double(rect.y),
234  double(rect.width), double(rect.height)};
235  res_d = Transform(res_d);
236  SDKRectI2D res = {
237  RoundToNearest<SDKInt32>(res_d.x),
238  RoundToNearest<SDKInt32>(res_d.y),
239  RoundToNearest<SDKUInt32>(res_d.width),
240  RoundToNearest<SDKUInt32>(res_d.height)
241  };
242  return res;
243  }
244 
246  _MyType& Transpose() noexcept
247  {
248  double v;
249  v = this->_12; this->_12 = this->_21; this->_21 = coordinate_type(v);
250  v = this->_13; this->_13 = this->_31; this->_31 = coordinate_type(v);
251  v = this->_23; this->_23 = this->_32; this->_32 = coordinate_type(v);
252  return *this;
253  }
254 
255  static _MyType Transpose(const SDKMatrix3X3& m2) noexcept
256  {
257  _MyType m(m2);
258  m.Transpose();
259  return m;
260  }
261 
263  _MyType& Multiply(const SDKMatrix3X3& m2) noexcept
264  {
265  double a, b, c;
266  a = double(this->_11) * m2._11 + double(this->_12) * m2._21 + double(this->_13) * m2._31;
267  b = double(this->_11) * m2._12 + double(this->_12) * m2._22 + double(this->_13) * m2._32;
268  c = double(this->_11) * m2._13 + double(this->_12) * m2._23 + double(this->_13) * m2._33;
269  this->_11 = coordinate_type(a);
270  this->_12 = coordinate_type(b);
271  this->_13 = coordinate_type(c);
272 
273  a = double(this->_21) * m2._11 + double(this->_22) * m2._21 + double(this->_23) * m2._31;
274  b = double(this->_21) * m2._12 + double(this->_22) * m2._22 + double(this->_23) * m2._32;
275  c = double(this->_21) * m2._13 + double(this->_22) * m2._23 + double(this->_23) * m2._33;
276  this->_21 = coordinate_type(a);
277  this->_22 = coordinate_type(b);
278  this->_23 = coordinate_type(c);
279 
280  a = double(this->_31) * m2._11 + double(this->_32) * m2._21 + double(this->_33) * m2._31;
281  b = double(this->_31) * m2._12 + double(this->_32) * m2._22 + double(this->_33) * m2._32;
282  c = double(this->_31) * m2._13 + double(this->_32) * m2._23 + double(this->_33) * m2._33;
283  this->_31 = coordinate_type(a);
284  this->_32 = coordinate_type(b);
285  this->_33 = coordinate_type(c);
286  return *this;
287  }
288 
289  static _MyType Multiply(const SDKMatrix3X3& m1, const SDKMatrix3X3& m2)
290  {
291  _MyType m(m1);
292  m.Multiply(m2);
293  return m;
294  }
295 
297  bool Invert() noexcept
298  {
299  return this->Invert(*this);
300  }
301  bool Invert(SDKMatrixF3X3& inverted_matrix) const noexcept
302  {
303  Matrix3X3T<SDKMatrixD3X3> inv = *this;
304  if (!inv.Invert())
305  return false;
306  inverted_matrix = inv;
307  return true;
308  }
309  bool Invert(SDKMatrixD3X3& inverted_matrix) const noexcept;
310 };
311 
312 template <class _SDKMatrix3X3>
313 bool Matrix3X3T<_SDKMatrix3X3>::Invert(SDKMatrixD3X3& inverted_matrix) const noexcept
314 {
315  // | a11 a12 a13 |-1 | a33a22-a32a23 -(a33a12-a32a13) a23a12-a22a13 |
316  // | a21 a22 a23 | = 1/DET * | -(a33a21-a31a23) a33a11-a31a13 -(a23a11-a21a13) |
317  // | a31 a32 a33 | | a32a21-a31a22 -(a32a11-a31a12) a22a11-a21a12 |
318  // with DET = a11*(a33*a22-a32*a23)-a21*(a33*a12-a32*a13)+a31*(a23*a12-a22*a13)
319  SDKMatrixD3X3 inv;
320  inv._11 = +double(this->_33) * this->_22 - double(this->_32) * this->_23;
321  inv._12 = -double(this->_33) * this->_12 + double(this->_32) * this->_13;
322  inv._13 = +double(this->_23) * this->_12 - double(this->_22) * this->_13;
323 
324  double det = this->_11 * inv._11 + this->_21 * inv._12 + this->_31 * inv._13;
325  if (0 == det)
326  return false;
327  det = 1 / det;
328 
329  inv._21 = -double(this->_33) * this->_21 + double(this->_31) * this->_23;
330  inv._22 = +double(this->_33) * this->_11 - double(this->_31) * this->_13;
331  inv._23 = -double(this->_23) * this->_11 + double(this->_21) * this->_13;
332  inv._31 = +double(this->_32) * this->_21 - double(this->_31) * this->_22;
333  inv._32 = -double(this->_32) * this->_11 + double(this->_31) * this->_12;
334  inv._33 = +double(this->_22) * this->_11 - double(this->_21) * this->_12;
335 
336  inverted_matrix._11 = coordinate_type(inv._11 * det);
337  inverted_matrix._12 = coordinate_type(inv._12 * det);
338  inverted_matrix._13 = coordinate_type(inv._13 * det);
339 
340  inverted_matrix._21 = coordinate_type(inv._21 * det);
341  inverted_matrix._22 = coordinate_type(inv._22 * det);
342  inverted_matrix._23 = coordinate_type(inv._23 * det);
343 
344  inverted_matrix._31 = coordinate_type(inv._31 * det);
345  inverted_matrix._32 = coordinate_type(inv._32 * det);
346  inverted_matrix._33 = coordinate_type(inv._33 * det);
347 
348  return true;
349 }
350 
351 typedef Matrix3X3T<SDKMatrix3X3> Matrix3X3, CMatrix3X3;
352 typedef Matrix3X3T<SDKMatrixD3X3> MatrixD3X3, CMatrixD3X3;
353 typedef Matrix3X3T<SDKMatrixF3X3> MatrixF3X3, CMatrixF3X3;
354 
355 } // namespace sdk
356 
357 #endif // SDK_MATRIX_3X3_H_
SDKMatrixD3X2
Matrix 3x2.
Definition: matrix_base_types.h:120
sdk::Matrix3X3T::Invert
bool Invert() noexcept
Inverts matrix, if possible.
Definition: matrix3x3.h:297
base_types.h
SDK base types.
SDKMatrixF3X3
Matrix 3X3.
Definition: matrix_base_types.h:62
sdk::Matrix3X3T::Multiply
_MyType & Multiply(const SDKMatrix3X3 &m2) noexcept
Multiplication of matrices.
Definition: matrix3x3.h:263
SDKMatrixD3X3
Matrix 3X3.
Definition: matrix_base_types.h:149
SDKRectD2D
2D Rectangle
Definition: geometry_base_types.h:1356
SDKRectF2D
2D Rectangle
Definition: geometry_base_types.h:1295
sdk::Matrix3X3T::Rotate
_MyType & Rotate(double angle_deg, const Point &center) noexcept
Rotate around specified point on specified angle. Negative angle - clockwise rotation in SDK coordina...
Definition: matrix3x3.h:130
SDKRectI2D
2D Rectangle
Definition: geometry_base_types.h:1417
sdk::Matrix3X3T::Transpose
_MyType & Transpose() noexcept
Multiplication of matrices.
Definition: matrix3x3.h:246
SDKPointF2D
Single 2D point.
Definition: geometry_base_types.h:33
sdk::Matrix3X3T::Determinant
double Determinant() const noexcept
Returns the matrix determinant.
Definition: matrix3x3.h:116
sdk::Matrix3X3T::Scale
_MyType & Scale(double scale_x, double scale_y) noexcept
Creates the scale transformation matrix.
Definition: matrix3x3.h:162
matrix_base_types.h
Matrix base definitions.
geometry_base_types.h
Geometry base types.
sdk::Matrix3X3T
Includes member functions to manipulate SDKMatrix3X3 structure.
Definition: matrix3x3.h:25
SDKPointI2D
Single 2D point.
Definition: geometry_base_types.h:178
sdk::Matrix3X3T::Translate
_MyType & Translate(double shift_x, double shift_y) noexcept
Creates a translation transformation that has the specified x and y displacements.
Definition: matrix3x3.h:153
kPI
#define kPI
PI.
Definition: math_const.h:16
SDKMatrixF3X2
Matrix 3x2.
Definition: matrix_base_types.h:33
sdk::Matrix3X3T::SetIdentity
_MyType & SetIdentity()
Sets to identity.
Definition: matrix3x3.h:108
math_const.h
Math constants definition.
SDKPointD2D
A two dimensional point.
Definition: geometry_base_types.h:242