Ignition Math

API Reference

4.0.0
Matrix4.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 #ifndef IGNITION_MATH_MATRIX4_HH_
18 #define IGNITION_MATH_MATRIX4_HH_
19 
20 #include <algorithm>
21 #include <ignition/math/Helpers.hh>
22 #include <ignition/math/Matrix3.hh>
23 #include <ignition/math/Vector3.hh>
24 #include <ignition/math/Pose3.hh>
25 #include <ignition/math/config.hh>
26 
27 namespace ignition
28 {
29  namespace math
30  {
31  // Inline bracket to help doxygen filtering.
32  inline namespace IGNITION_MATH_VERSION_NAMESPACE {
33  //
36  template<typename T>
37  class Matrix4
38  {
40  public: static const Matrix4<T> Identity;
41 
43  public: static const Matrix4<T> Zero;
44 
46  public: Matrix4()
47  {
48  memset(this->data, 0, sizeof(this->data[0][0])*16);
49  }
50 
53  public: Matrix4(const Matrix4<T> &_m)
54  {
55  memcpy(this->data, _m.data, sizeof(this->data[0][0])*16);
56  }
57 
75  public: Matrix4(T _v00, T _v01, T _v02, T _v03,
76  T _v10, T _v11, T _v12, T _v13,
77  T _v20, T _v21, T _v22, T _v23,
78  T _v30, T _v31, T _v32, T _v33)
79  {
80  this->Set(_v00, _v01, _v02, _v03,
81  _v10, _v11, _v12, _v13,
82  _v20, _v21, _v22, _v23,
83  _v30, _v31, _v32, _v33);
84  }
85 
88  public: explicit Matrix4(const Quaternion<T> &_q)
89  {
90  Quaternion<T> qt = _q;
91  qt.Normalize();
92  this->Set(1 - 2*qt.Y()*qt.Y() - 2 *qt.Z()*qt.Z(),
93  2 * qt.X()*qt.Y() - 2*qt.Z()*qt.W(),
94  2 * qt.X() * qt.Z() + 2 * qt.Y() * qt.W(),
95  0,
96 
97  2 * qt.X() * qt.Y() + 2 * qt.Z() * qt.W(),
98  1 - 2*qt.X()*qt.X() - 2 * qt.Z()*qt.Z(),
99  2 * qt.Y() * qt.Z() - 2 * qt.X() * qt.W(),
100  0,
101 
102  2 * qt.X() * qt.Z() - 2 * qt.Y() * qt.W(),
103  2 * qt.Y() * qt.Z() + 2 * qt.X() * qt.W(),
104  1 - 2 * qt.X()*qt.X() - 2 * qt.Y()*qt.Y(),
105  0,
106 
107  0, 0, 0, 1);
108  }
109 
112  public: explicit Matrix4(const Pose3<T> &_pose) : Matrix4(_pose.Rot())
113  {
114  this->SetTranslation(_pose.Pos());
115  }
116 
118  public: virtual ~Matrix4() {}
119 
137  public: void Set(
138  T _v00, T _v01, T _v02, T _v03,
139  T _v10, T _v11, T _v12, T _v13,
140  T _v20, T _v21, T _v22, T _v23,
141  T _v30, T _v31, T _v32, T _v33)
142  {
143  this->data[0][0] = _v00;
144  this->data[0][1] = _v01;
145  this->data[0][2] = _v02;
146  this->data[0][3] = _v03;
147 
148  this->data[1][0] = _v10;
149  this->data[1][1] = _v11;
150  this->data[1][2] = _v12;
151  this->data[1][3] = _v13;
152 
153  this->data[2][0] = _v20;
154  this->data[2][1] = _v21;
155  this->data[2][2] = _v22;
156  this->data[2][3] = _v23;
157 
158  this->data[3][0] = _v30;
159  this->data[3][1] = _v31;
160  this->data[3][2] = _v32;
161  this->data[3][3] = _v33;
162  }
163 
167  public: void Axis(const Vector3<T> &_axis, T _angle)
168  {
169  T c = cos(_angle);
170  T s = sin(_angle);
171  T C = 1-c;
172 
173  this->data[0][0] = _axis.X()*_axis.X()*C + c;
174  this->data[0][1] = _axis.X()*_axis.Y()*C - _axis.Z()*s;
175  this->data[0][2] = _axis.X()*_axis.Z()*C + _axis.Y()*s;
176 
177  this->data[1][0] = _axis.Y()*_axis.X()*C + _axis.Z()*s;
178  this->data[1][1] = _axis.Y()*_axis.Y()*C + c;
179  this->data[1][2] = _axis.Y()*_axis.Z()*C - _axis.X()*s;
180 
181  this->data[2][0] = _axis.Z()*_axis.X()*C - _axis.Y()*s;
182  this->data[2][1] = _axis.Z()*_axis.Y()*C + _axis.X()*s;
183  this->data[2][2] = _axis.Z()*_axis.Z()*C + c;
184  }
185 
189  public: void
190  IGN_DEPRECATED(4)
191  Translate(const Vector3<T> &_t)
192  {
193  this->SetTranslation(_t);
194  }
195 
198  public: void SetTranslation(const Vector3<T> &_t)
199  {
200  this->data[0][3] = _t.X();
201  this->data[1][3] = _t.Y();
202  this->data[2][3] = _t.Z();
203  }
204 
210  public: void
211  IGN_DEPRECATED(4)
212  Translate(T _x, T _y, T _z)
213  {
214  this->SetTranslation(_x, _y, _z);
215  }
216 
221  public: void SetTranslation(T _x, T _y, T _z)
222  {
223  this->data[0][3] = _x;
224  this->data[1][3] = _y;
225  this->data[2][3] = _z;
226  }
227 
230  public: Vector3<T> Translation() const
231  {
232  return Vector3<T>(this->data[0][3], this->data[1][3], this->data[2][3]);
233  }
234 
237  public: Vector3<T> Scale() const
238  {
239  return Vector3<T>(this->data[0][0], this->data[1][1], this->data[2][2]);
240  }
241 
244  public: Quaternion<T> Rotation() const
245  {
246  Quaternion<T> q;
249  T trace = this->data[0][0] + this->data[1][1] + this->data[2][2];
250  T root;
251  if (trace > 0)
252  {
253  root = sqrt(trace + 1.0);
254  q.W(root / 2.0);
255  root = 1.0 / (2.0 * root);
256  q.X((this->data[2][1] - this->data[1][2]) * root);
257  q.Y((this->data[0][2] - this->data[2][0]) * root);
258  q.Z((this->data[1][0] - this->data[0][1]) * root);
259  }
260  else
261  {
262  static unsigned int s_iNext[3] = {1, 2, 0};
263  unsigned int i = 0;
264  if (this->data[1][1] > this->data[0][0])
265  i = 1;
266  if (this->data[2][2] > this->data[i][i])
267  i = 2;
268  unsigned int j = s_iNext[i];
269  unsigned int k = s_iNext[j];
270 
271  root = sqrt(this->data[i][i] - this->data[j][j] -
272  this->data[k][k] + 1.0);
273 
274  T a, b, c;
275  a = root / 2.0;
276  root = 1.0 / (2.0 * root);
277  b = (this->data[j][i] + this->data[i][j]) * root;
278  c = (this->data[k][i] + this->data[i][k]) * root;
279 
280  switch (i)
281  {
282  default:
283  case 0: q.X(a); break;
284  case 1: q.Y(a); break;
285  case 2: q.Z(a); break;
286  };
287  switch (j)
288  {
289  default:
290  case 0: q.X(b); break;
291  case 1: q.Y(b); break;
292  case 2: q.Z(b); break;
293  };
294  switch (k)
295  {
296  default:
297  case 0: q.X(c); break;
298  case 1: q.Y(c); break;
299  case 2: q.Z(c); break;
300  };
301 
302  q.W((this->data[k][j] - this->data[j][k]) * root);
303  }
304 
305  return q;
306  }
307 
312  public: Vector3<T> EulerRotation(bool _firstSolution) const
313  {
314  Vector3<T> euler;
315  Vector3<T> euler2;
316 
317  T m31 = this->data[2][0];
318  T m11 = this->data[0][0];
319  T m12 = this->data[0][1];
320  T m13 = this->data[0][2];
321  T m32 = this->data[2][1];
322  T m33 = this->data[2][2];
323  T m21 = this->data[1][0];
324 
325  if (std::abs(m31) >= 1.0)
326  {
327  euler.Z(0.0);
328  euler2.Z(0.0);
329 
330  if (m31 < 0.0)
331  {
332  euler.Y(IGN_PI / 2.0);
333  euler2.Y(IGN_PI / 2.0);
334  euler.X(atan2(m12, m13));
335  euler2.X(atan2(m12, m13));
336  }
337  else
338  {
339  euler.Y(-IGN_PI / 2.0);
340  euler2.Y(-IGN_PI / 2.0);
341  euler.X(atan2(-m12, -m13));
342  euler2.X(atan2(-m12, -m13));
343  }
344  }
345  else
346  {
347  euler.Y(-asin(m31));
348  euler2.Y(IGN_PI - euler.Y());
349 
350  euler.X(atan2(m32 / cos(euler.Y()), m33 / cos(euler.Y())));
351  euler2.X(atan2(m32 / cos(euler2.Y()), m33 / cos(euler2.Y())));
352 
353  euler.Z(atan2(m21 / cos(euler.Y()), m11 / cos(euler.Y())));
354  euler2.Z(atan2(m21 / cos(euler2.Y()), m11 / cos(euler2.Y())));
355  }
356 
357  if (_firstSolution)
358  return euler;
359  else
360  return euler2;
361  }
362 
365  public: Pose3<T> Pose() const
366  {
367  return Pose3<T>(this->Translation(), this->Rotation());
368  }
369 
372  public: void Scale(const Vector3<T> &_s)
373  {
374  this->data[0][0] = _s.X();
375  this->data[1][1] = _s.Y();
376  this->data[2][2] = _s.Z();
377  this->data[3][3] = 1.0;
378  }
379 
384  public: void Scale(T _x, T _y, T _z)
385  {
386  this->data[0][0] = _x;
387  this->data[1][1] = _y;
388  this->data[2][2] = _z;
389  this->data[3][3] = 1.0;
390  }
391 
394  public: bool IsAffine() const
395  {
396  return equal(this->data[3][0], static_cast<T>(0)) &&
397  equal(this->data[3][1], static_cast<T>(0)) &&
398  equal(this->data[3][2], static_cast<T>(0)) &&
399  equal(this->data[3][3], static_cast<T>(1));
400  }
401 
408  public: Vector3<T>
409  IGN_DEPRECATED(3.0)
410  TransformAffine(const Vector3<T> &_v) const
411  {
412  if (this->IsAffine())
413  {
414  return Vector3<T>(this->data[0][0]*_v.X() + this->data[0][1]*_v.Y() +
415  this->data[0][2]*_v.Z() + this->data[0][3],
416  this->data[1][0]*_v.X() + this->data[1][1]*_v.Y() +
417  this->data[1][2]*_v.Z() + this->data[1][3],
418  this->data[2][0]*_v.X() + this->data[2][1]*_v.Y() +
419  this->data[2][2]*_v.Z() + this->data[2][3]);
420  }
421  else
422  {
423  return Vector3<T>();
424  }
425  }
426 
432  public: bool TransformAffine(const Vector3<T> &_v,
433  Vector3<T> &_result) const
434  {
435  if (!this->IsAffine())
436  return false;
437 
438  _result.Set(this->data[0][0]*_v.X() + this->data[0][1]*_v.Y() +
439  this->data[0][2]*_v.Z() + this->data[0][3],
440  this->data[1][0]*_v.X() + this->data[1][1]*_v.Y() +
441  this->data[1][2]*_v.Z() + this->data[1][3],
442  this->data[2][0]*_v.X() + this->data[2][1]*_v.Y() +
443  this->data[2][2]*_v.Z() + this->data[2][3]);
444  return true;
445  }
446 
449  public: T Determinant() const
450  {
451  T v0, v1, v2, v3, v4, v5, t00, t10, t20, t30;
452 
453  v0 = this->data[2][0]*this->data[3][1]
454  - this->data[2][1]*this->data[3][0];
455  v1 = this->data[2][0]*this->data[3][2]
456  - this->data[2][2]*this->data[3][0];
457  v2 = this->data[2][0]*this->data[3][3]
458  - this->data[2][3]*this->data[3][0];
459  v3 = this->data[2][1]*this->data[3][2]
460  - this->data[2][2]*this->data[3][1];
461  v4 = this->data[2][1]*this->data[3][3]
462  - this->data[2][3]*this->data[3][1];
463  v5 = this->data[2][2]*this->data[3][3]
464  - this->data[2][3]*this->data[3][2];
465 
466  t00 = v5*this->data[1][1] - v4*this->data[1][2] + v3*this->data[1][3];
467  t10 = -v5*this->data[1][0] + v2*this->data[1][2] - v1*this->data[1][3];
468  t20 = v4*this->data[1][0] - v2*this->data[1][1] + v0*this->data[1][3];
469  t30 = -v3*this->data[1][0] + v1*this->data[1][1] - v0*this->data[1][2];
470 
471  return t00 * this->data[0][0]
472  + t10 * this->data[0][1]
473  + t20 * this->data[0][2]
474  + t30 * this->data[0][3];
475  }
476 
480  public: Matrix4<T> Inverse() const
481  {
482  T v0, v1, v2, v3, v4, v5, t00, t10, t20, t30;
483  Matrix4<T> r;
484 
485  v0 = this->data[2][0]*this->data[3][1] -
486  this->data[2][1]*this->data[3][0];
487  v1 = this->data[2][0]*this->data[3][2] -
488  this->data[2][2]*this->data[3][0];
489  v2 = this->data[2][0]*this->data[3][3] -
490  this->data[2][3]*this->data[3][0];
491  v3 = this->data[2][1]*this->data[3][2] -
492  this->data[2][2]*this->data[3][1];
493  v4 = this->data[2][1]*this->data[3][3] -
494  this->data[2][3]*this->data[3][1];
495  v5 = this->data[2][2]*this->data[3][3] -
496  this->data[2][3]*this->data[3][2];
497 
498  t00 = +(v5*this->data[1][1] -
499  v4*this->data[1][2] + v3*this->data[1][3]);
500  t10 = -(v5*this->data[1][0] -
501  v2*this->data[1][2] + v1*this->data[1][3]);
502  t20 = +(v4*this->data[1][0] -
503  v2*this->data[1][1] + v0*this->data[1][3]);
504  t30 = -(v3*this->data[1][0] -
505  v1*this->data[1][1] + v0*this->data[1][2]);
506 
507  T invDet = 1 / (t00 * this->data[0][0] + t10 * this->data[0][1] +
508  t20 * this->data[0][2] + t30 * this->data[0][3]);
509 
510  r(0, 0) = t00 * invDet;
511  r(1, 0) = t10 * invDet;
512  r(2, 0) = t20 * invDet;
513  r(3, 0) = t30 * invDet;
514 
515  r(0, 1) = -(v5*this->data[0][1] -
516  v4*this->data[0][2] + v3*this->data[0][3]) * invDet;
517  r(1, 1) = +(v5*this->data[0][0] -
518  v2*this->data[0][2] + v1*this->data[0][3]) * invDet;
519  r(2, 1) = -(v4*this->data[0][0] -
520  v2*this->data[0][1] + v0*this->data[0][3]) * invDet;
521  r(3, 1) = +(v3*this->data[0][0] -
522  v1*this->data[0][1] + v0*this->data[0][2]) * invDet;
523 
524  v0 = this->data[1][0]*this->data[3][1] -
525  this->data[1][1]*this->data[3][0];
526  v1 = this->data[1][0]*this->data[3][2] -
527  this->data[1][2]*this->data[3][0];
528  v2 = this->data[1][0]*this->data[3][3] -
529  this->data[1][3]*this->data[3][0];
530  v3 = this->data[1][1]*this->data[3][2] -
531  this->data[1][2]*this->data[3][1];
532  v4 = this->data[1][1]*this->data[3][3] -
533  this->data[1][3]*this->data[3][1];
534  v5 = this->data[1][2]*this->data[3][3] -
535  this->data[1][3]*this->data[3][2];
536 
537  r(0, 2) = +(v5*this->data[0][1] -
538  v4*this->data[0][2] + v3*this->data[0][3]) * invDet;
539  r(1, 2) = -(v5*this->data[0][0] -
540  v2*this->data[0][2] + v1*this->data[0][3]) * invDet;
541  r(2, 2) = +(v4*this->data[0][0] -
542  v2*this->data[0][1] + v0*this->data[0][3]) * invDet;
543  r(3, 2) = -(v3*this->data[0][0] -
544  v1*this->data[0][1] + v0*this->data[0][2]) * invDet;
545 
546  v0 = this->data[2][1]*this->data[1][0] -
547  this->data[2][0]*this->data[1][1];
548  v1 = this->data[2][2]*this->data[1][0] -
549  this->data[2][0]*this->data[1][2];
550  v2 = this->data[2][3]*this->data[1][0] -
551  this->data[2][0]*this->data[1][3];
552  v3 = this->data[2][2]*this->data[1][1] -
553  this->data[2][1]*this->data[1][2];
554  v4 = this->data[2][3]*this->data[1][1] -
555  this->data[2][1]*this->data[1][3];
556  v5 = this->data[2][3]*this->data[1][2] -
557  this->data[2][2]*this->data[1][3];
558 
559  r(0, 3) = -(v5*this->data[0][1] -
560  v4*this->data[0][2] + v3*this->data[0][3]) * invDet;
561  r(1, 3) = +(v5*this->data[0][0] -
562  v2*this->data[0][2] + v1*this->data[0][3]) * invDet;
563  r(2, 3) = -(v4*this->data[0][0] -
564  v2*this->data[0][1] + v0*this->data[0][3]) * invDet;
565  r(3, 3) = +(v3*this->data[0][0] -
566  v1*this->data[0][1] + v0*this->data[0][2]) * invDet;
567 
568  return r;
569  }
570 
572  public: void Transpose()
573  {
574  std::swap(this->data[0][1], this->data[1][0]);
575  std::swap(this->data[0][2], this->data[2][0]);
576  std::swap(this->data[0][3], this->data[3][0]);
577  std::swap(this->data[1][2], this->data[2][1]);
578  std::swap(this->data[1][3], this->data[3][1]);
579  std::swap(this->data[2][3], this->data[3][2]);
580  }
581 
584  public: Matrix4<T> Transposed() const
585  {
586  return Matrix4<T>(
587  this->data[0][0], this->data[1][0], this->data[2][0], this->data[3][0],
588  this->data[0][1], this->data[1][1], this->data[2][1], this->data[3][1],
589  this->data[0][2], this->data[1][2], this->data[2][2], this->data[3][2],
590  this->data[0][3], this->data[1][3], this->data[2][3], this->data[3][3]);
591  }
592 
596  public: Matrix4<T> &operator=(const Matrix4<T> &_mat)
597  {
598  memcpy(this->data, _mat.data, sizeof(this->data[0][0])*16);
599  return *this;
600  }
601 
605  public: const Matrix4<T> &operator=(const Matrix3<T> &_mat)
606  {
607  this->data[0][0] = _mat(0, 0);
608  this->data[0][1] = _mat(0, 1);
609  this->data[0][2] = _mat(0, 2);
610 
611  this->data[1][0] = _mat(1, 0);
612  this->data[1][1] = _mat(1, 1);
613  this->data[1][2] = _mat(1, 2);
614 
615  this->data[2][0] = _mat(2, 0);
616  this->data[2][1] = _mat(2, 1);
617  this->data[2][2] = _mat(2, 2);
618 
619  return *this;
620  }
621 
625  public: Matrix4<T> operator*(const Matrix4<T> &_m2) const
626  {
627  return Matrix4<T>(
628  this->data[0][0] * _m2(0, 0) +
629  this->data[0][1] * _m2(1, 0) +
630  this->data[0][2] * _m2(2, 0) +
631  this->data[0][3] * _m2(3, 0),
632 
633  this->data[0][0] * _m2(0, 1) +
634  this->data[0][1] * _m2(1, 1) +
635  this->data[0][2] * _m2(2, 1) +
636  this->data[0][3] * _m2(3, 1),
637 
638  this->data[0][0] * _m2(0, 2) +
639  this->data[0][1] * _m2(1, 2) +
640  this->data[0][2] * _m2(2, 2) +
641  this->data[0][3] * _m2(3, 2),
642 
643  this->data[0][0] * _m2(0, 3) +
644  this->data[0][1] * _m2(1, 3) +
645  this->data[0][2] * _m2(2, 3) +
646  this->data[0][3] * _m2(3, 3),
647 
648  this->data[1][0] * _m2(0, 0) +
649  this->data[1][1] * _m2(1, 0) +
650  this->data[1][2] * _m2(2, 0) +
651  this->data[1][3] * _m2(3, 0),
652 
653  this->data[1][0] * _m2(0, 1) +
654  this->data[1][1] * _m2(1, 1) +
655  this->data[1][2] * _m2(2, 1) +
656  this->data[1][3] * _m2(3, 1),
657 
658  this->data[1][0] * _m2(0, 2) +
659  this->data[1][1] * _m2(1, 2) +
660  this->data[1][2] * _m2(2, 2) +
661  this->data[1][3] * _m2(3, 2),
662 
663  this->data[1][0] * _m2(0, 3) +
664  this->data[1][1] * _m2(1, 3) +
665  this->data[1][2] * _m2(2, 3) +
666  this->data[1][3] * _m2(3, 3),
667 
668  this->data[2][0] * _m2(0, 0) +
669  this->data[2][1] * _m2(1, 0) +
670  this->data[2][2] * _m2(2, 0) +
671  this->data[2][3] * _m2(3, 0),
672 
673  this->data[2][0] * _m2(0, 1) +
674  this->data[2][1] * _m2(1, 1) +
675  this->data[2][2] * _m2(2, 1) +
676  this->data[2][3] * _m2(3, 1),
677 
678  this->data[2][0] * _m2(0, 2) +
679  this->data[2][1] * _m2(1, 2) +
680  this->data[2][2] * _m2(2, 2) +
681  this->data[2][3] * _m2(3, 2),
682 
683  this->data[2][0] * _m2(0, 3) +
684  this->data[2][1] * _m2(1, 3) +
685  this->data[2][2] * _m2(2, 3) +
686  this->data[2][3] * _m2(3, 3),
687 
688  this->data[3][0] * _m2(0, 0) +
689  this->data[3][1] * _m2(1, 0) +
690  this->data[3][2] * _m2(2, 0) +
691  this->data[3][3] * _m2(3, 0),
692 
693  this->data[3][0] * _m2(0, 1) +
694  this->data[3][1] * _m2(1, 1) +
695  this->data[3][2] * _m2(2, 1) +
696  this->data[3][3] * _m2(3, 1),
697 
698  this->data[3][0] * _m2(0, 2) +
699  this->data[3][1] * _m2(1, 2) +
700  this->data[3][2] * _m2(2, 2) +
701  this->data[3][3] * _m2(3, 2),
702 
703  this->data[3][0] * _m2(0, 3) +
704  this->data[3][1] * _m2(1, 3) +
705  this->data[3][2] * _m2(2, 3) +
706  this->data[3][3] * _m2(3, 3));
707  }
708 
712  public: Vector3<T> operator*(const Vector3<T> &_vec) const
713  {
714  return Vector3<T>(
715  this->data[0][0]*_vec.X() + this->data[0][1]*_vec.Y() +
716  this->data[0][2]*_vec.Z() + this->data[0][3],
717  this->data[1][0]*_vec.X() + this->data[1][1]*_vec.Y() +
718  this->data[1][2]*_vec.Z() + this->data[1][3],
719  this->data[2][0]*_vec.X() + this->data[2][1]*_vec.Y() +
720  this->data[2][2]*_vec.Z() + this->data[2][3]);
721  }
722 
729  public: inline const T &operator()(const size_t _row,
730  const size_t _col) const
731  {
732  return this->data[clamp(_row, IGN_ZERO_SIZE_T, IGN_THREE_SIZE_T)][
734  }
735 
743  public: inline T &operator()(const size_t _row, const size_t _col)
744  {
745  return this->data[clamp(_row, IGN_ZERO_SIZE_T, IGN_THREE_SIZE_T)]
747  }
748 
754  public: bool Equal(const Matrix4 &_m, const T &_tol) const
755  {
756  return equal<T>(this->data[0][0], _m(0, 0), _tol)
757  && equal<T>(this->data[0][1], _m(0, 1), _tol)
758  && equal<T>(this->data[0][2], _m(0, 2), _tol)
759  && equal<T>(this->data[0][3], _m(0, 3), _tol)
760  && equal<T>(this->data[1][0], _m(1, 0), _tol)
761  && equal<T>(this->data[1][1], _m(1, 1), _tol)
762  && equal<T>(this->data[1][2], _m(1, 2), _tol)
763  && equal<T>(this->data[1][3], _m(1, 3), _tol)
764  && equal<T>(this->data[2][0], _m(2, 0), _tol)
765  && equal<T>(this->data[2][1], _m(2, 1), _tol)
766  && equal<T>(this->data[2][2], _m(2, 2), _tol)
767  && equal<T>(this->data[2][3], _m(2, 3), _tol)
768  && equal<T>(this->data[3][0], _m(3, 0), _tol)
769  && equal<T>(this->data[3][1], _m(3, 1), _tol)
770  && equal<T>(this->data[3][2], _m(3, 2), _tol)
771  && equal<T>(this->data[3][3], _m(3, 3), _tol);
772  }
773 
778  public: bool operator==(const Matrix4<T> &_m) const
779  {
780  return this->Equal(_m, static_cast<T>(1e-6));
781  }
782 
786  public: bool operator!=(const Matrix4<T> &_m) const
787  {
788  return !(*this == _m);
789  }
790 
795  public: friend std::ostream &operator<<(
796  std::ostream &_out, const ignition::math::Matrix4<T> &_m)
797  {
798  _out << precision(_m(0, 0), 6) << " "
799  << precision(_m(0, 1), 6) << " "
800  << precision(_m(0, 2), 6) << " "
801  << precision(_m(0, 3), 6) << " "
802  << precision(_m(1, 0), 6) << " "
803  << precision(_m(1, 1), 6) << " "
804  << precision(_m(1, 2), 6) << " "
805  << precision(_m(1, 3), 6) << " "
806  << precision(_m(2, 0), 6) << " "
807  << precision(_m(2, 1), 6) << " "
808  << precision(_m(2, 2), 6) << " "
809  << precision(_m(2, 3), 6) << " "
810  << precision(_m(3, 0), 6) << " "
811  << precision(_m(3, 1), 6) << " "
812  << precision(_m(3, 2), 6) << " "
813  << precision(_m(3, 3), 6);
814 
815  return _out;
816  }
817 
822  public: friend std::istream &operator>>(
824  {
825  // Skip white spaces
826  _in.setf(std::ios_base::skipws);
827  T d[16];
828  _in >> d[0] >> d[1] >> d[2] >> d[3]
829  >> d[4] >> d[5] >> d[6] >> d[7]
830  >> d[8] >> d[9] >> d[10] >> d[11]
831  >> d[12] >> d[13] >> d[14] >> d[15];
832 
833  _m.Set(d[0], d[1], d[2], d[3],
834  d[4], d[5], d[6], d[7],
835  d[8], d[9], d[10], d[11],
836  d[12], d[13], d[14], d[15]);
837  return _in;
838  }
839 
849  public: static Matrix4<T> LookAt(const Vector3<T> &_eye,
850  const Vector3<T> &_target, const Vector3<T> &_up = Vector3<T>::UnitZ)
851  {
852  // Most important constraint: direction to point X axis at
853  auto front = _target - _eye;
854 
855  // Case when _eye == _target
856  if (front == Vector3<T>::Zero)
857  front = Vector3<T>::UnitX;
858  front.Normalize();
859 
860  // Desired direction to point Z axis at
861  auto up = _up;
862 
863  // Case when _up == Zero
864  if (up == Vector3<T>::Zero)
865  up = Vector3<T>::UnitZ;
866  else
867  up.Normalize();
868 
869  // Case when _up is parallel to X
870  if (up.Cross(Vector3<T>::UnitX) == Vector3<T>::Zero)
871  up = Vector3<T>::UnitZ;
872 
873  // Find direction to point Y axis at
874  auto left = up.Cross(front);
875 
876  // Case when front is parallel to up
877  if (left == Vector3<T>::Zero)
878  left = Vector3<T>::UnitY;
879  else
880  left.Normalize();
881 
882  // Fix up direction so it's perpendicular to XY
883  up = (front.Cross(left)).Normalize();
884 
885  return Matrix4<T>(
886  front.X(), left.X(), up.X(), _eye.X(),
887  front.Y(), left.Y(), up.Y(), _eye.Y(),
888  front.Z(), left.Z(), up.Z(), _eye.Z(),
889  0, 0, 0, 1);
890  }
891 
893  private: T data[4][4];
894  };
895 
896  template<typename T>
898  1, 0, 0, 0,
899  0, 1, 0, 0,
900  0, 0, 1, 0,
901  0, 0, 0, 1);
902 
903  template<typename T>
905  0, 0, 0, 0,
906  0, 0, 0, 0,
907  0, 0, 0, 0,
908  0, 0, 0, 0);
909 
913  }
914  }
915 }
916 #endif
T setf(T... args)
const Matrix4< T > & operator=(const Matrix3< T > &_mat)
Equal operator for 3x3 matrix.
Definition: Matrix4.hh:605
void SetTranslation(T _x, T _y, T _z)
Set the translational values [ (0, 3) (1, 3) (2, 3) ].
Definition: Matrix4.hh:221
const T & W() const
Get the w component.
Definition: Quaternion.hh:949
Matrix4< T > Transposed() const
Return the transpose of this matrix.
Definition: Matrix4.hh:584
void Set(T _x=0, T _y=0, T _z=0)
Set the contents of the vector.
Definition: Vector3.hh:179
static const Matrix4< T > Zero
Zero matrix.
Definition: Matrix4.hh:43
const T & Z() const
Get the z component.
Definition: Quaternion.hh:970
T precision(const T &_a, const unsigned int &_precision)
get value at a specified precision
Definition: Helpers.hh:580
static const static double const static double const static double const static double const static float const static float const static float const static float const static uint16_t const static uint16_t const static uint16_t const static uint16_t const static int16_t const static int16_t const static int16_t const static int16_t const static uint32_t const static uint32_t const static uint32_t const static uint32_t const static int32_t const static int32_t const static int32_t const static int32_t const static uint64_t const static uint64_t const static uint64_t const static uint64_t const static int64_t const static int64_t const static int64_t const int64_t T clamp(T _v, T _min, T _max)
Simple clamping function.
Definition: Helpers.hh:396
bool Equal(const Matrix4 &_m, const T &_tol) const
Equality test with tolerance.
Definition: Matrix4.hh:754
Quaternion< T > Rotation() const
Get the rotation as a quaternion.
Definition: Matrix4.hh:244
T swap(T... args)
Vector3< T > Translation() const
Get the translational values as a Vector3.
Definition: Matrix4.hh:230
void Normalize()
Normalize the quaternion.
Definition: Quaternion.hh:224
Vector3< T > operator*(const Vector3< T > &_vec) const
Multiplication operator.
Definition: Matrix4.hh:712
void Scale(T _x, T _y, T _z)
Set the scale.
Definition: Matrix4.hh:384
Matrix4< int > Matrix4i
Definition: Matrix4.hh:910
Encapsulates a position and rotation in three space.
Definition: Pose3.hh:34
void Scale(const Vector3< T > &_s)
Set the scale.
Definition: Matrix4.hh:372
const T & operator()(const size_t _row, const size_t _col) const
Get the value at the specified row, column index.
Definition: Matrix4.hh:729
bool operator!=(const Matrix4< T > &_m) const
Inequality test operator.
Definition: Matrix4.hh:786
virtual ~Matrix4()
Destructor.
Definition: Matrix4.hh:118
const T & X() const
Get the x component.
Definition: Quaternion.hh:956
Vector3< T > Scale() const
Get the scale values as a Vector3<T>
Definition: Matrix4.hh:237
A 4x4 matrix class.
Definition: Matrix4.hh:37
Matrix4()
Constructor.
Definition: Matrix4.hh:46
bool equal(const T &_a, const T &_b, const T &_epsilon=T(1e-6))
check if two values are equal, within a tolerance
Definition: Helpers.hh:546
void Set(T _v00, T _v01, T _v02, T _v03, T _v10, T _v11, T _v12, T _v13, T _v20, T _v21, T _v22, T _v23, T _v30, T _v31, T _v32, T _v33)
Change the values.
Definition: Matrix4.hh:137
const T & Y() const
Get the y component.
Definition: Quaternion.hh:963
STL class.
T X() const
Get the x value.
Definition: Vector3.hh:648
T Z() const
Get the z value.
Definition: Vector3.hh:662
bool operator==(const Matrix4< T > &_m) const
Equality operator.
Definition: Matrix4.hh:778
Matrix4(const Matrix4< T > &_m)
Copy constructor.
Definition: Matrix4.hh:53
T Y() const
Get the y value.
Definition: Vector3.hh:655
Matrix4< float > Matrix4f
Definition: Matrix4.hh:912
friend std::ostream & operator<<(std::ostream &_out, const Matrix4< T > &_m)
Stream insertion operator.
Definition: Matrix4.hh:795
Matrix4< double > Matrix4d
Definition: Matrix4.hh:911
A 3x3 matrix class.
Definition: Matrix3.hh:39
Matrix4(const Quaternion< T > &_q)
Construct Matrix4 from a quaternion.
Definition: Matrix4.hh:88
T & operator()(const size_t _row, const size_t _col)
Get a mutable version the value at the specified row, column index.
Definition: Matrix4.hh:743
static const size_t IGN_ZERO_SIZE_T
size_t type with a value of 0
Definition: Helpers.hh:217
void Axis(const Vector3< T > &_axis, T _angle)
Set the upper-left 3x3 matrix from an axis and angle.
Definition: Matrix4.hh:167
friend std::istream & operator>>(std::istream &_in, Matrix4< T > &_m)
Stream extraction operator.
Definition: Matrix4.hh:822
bool IsAffine() const
Return true if the matrix is affine.
Definition: Matrix4.hh:394
Matrix4< T > Inverse() const
Return the inverse matrix. This is a non-destructive operation.
Definition: Matrix4.hh:480
Vector3 Normalize()
Normalize the vector length.
Definition: Vector3.hh:133
void SetTranslation(const Vector3< T > &_t)
Set the translational values [ (0, 3) (1, 3) (2, 3) ].
Definition: Matrix4.hh:198
Matrix4< T > operator*(const Matrix4< T > &_m2) const
Multiplication operator.
Definition: Matrix4.hh:625
Matrix4(const Pose3< T > &_pose)
Construct Matrix4 from a math::Pose3.
Definition: Matrix4.hh:112
The Vector3 class represents the generic vector containing 3 elements. Since it&#39;s commonly used to ke...
Definition: Vector3.hh:40
Pose3< T > Pose() const
Get the transformation as math::Pose.
Definition: Matrix4.hh:365
Matrix4(T _v00, T _v01, T _v02, T _v03, T _v10, T _v11, T _v12, T _v13, T _v20, T _v21, T _v22, T _v23, T _v30, T _v31, T _v32, T _v33)
Constructor.
Definition: Matrix4.hh:75
const Vector3< T > & Pos() const
Get the position.
Definition: Pose3.hh:349
void Transpose()
Transpose this matrix.
Definition: Matrix4.hh:572
Matrix4< T > & operator=(const Matrix4< T > &_mat)
Equal operator. this = _mat.
Definition: Matrix4.hh:596
static const size_t IGN_THREE_SIZE_T
size_t type with a value of 3
Definition: Helpers.hh:226
static const Matrix4< T > Identity
Identity matrix.
Definition: Matrix4.hh:40
bool TransformAffine(const Vector3< T > &_v, Vector3< T > &_result) const
Perform an affine transformation.
Definition: Matrix4.hh:432
Definition: Angle.hh:39
A quaternion class.
Definition: Matrix3.hh:34
#define IGN_PI
Define IGN_PI, IGN_PI_2, and IGN_PI_4. This was put here for Windows support.
Definition: Helpers.hh:174
STL class.
static Matrix4< T > LookAt(const Vector3< T > &_eye, const Vector3< T > &_target, const Vector3< T > &_up=Vector3< T >::UnitZ)
Get transform which translates to _eye and rotates the X axis so it faces the _target. The rotation is such that Z axis is in the _up direction, if possible. The coordinate system is right-handed,.
Definition: Matrix4.hh:849
T Determinant() const
Return the determinant of the matrix.
Definition: Matrix4.hh:449
Vector3< T > EulerRotation(bool _firstSolution) const
Get the rotation as a Euler angles.
Definition: Matrix4.hh:312