SPH
AffineMatrix.h
Go to the documentation of this file.
1 #pragma once
2 
7 
9 
11 
14 class AffineMatrix {
15 private:
16  Vector v[3]; // rows
17 
18 public:
19  AffineMatrix() = default;
20 
24  AffineMatrix(const Vector& v1, const Vector& v2, const Vector& v3)
25  : v{ v1, v2, v3 } {}
26 
29  INLINE Float& operator()(const Size i, const Size j) {
30  SPH_ASSERT(i < 3 && j < 4, i, j);
31  return v[i][j];
32  }
33 
34  INLINE Float operator()(const Size i, const Size j) const {
35  SPH_ASSERT(i < 3 && j < 4, i, j);
36  return v[i][j];
37  }
38 
39  INLINE Vector column(const Size idx) const {
40  SPH_ASSERT(idx < 4, idx);
41  return Vector(v[0][idx], v[1][idx], v[2][idx]);
42  }
43 
44  INLINE Vector row(const Size idx) const {
45  SPH_ASSERT(idx < 3, idx);
46  return v[idx];
47  }
48 
50  return Vector(v[0][3], v[1][3], v[2][3]);
51  }
52 
54  v[0][3] = v[1][3] = v[2][3] = 0._f;
55  return *this;
56  }
57 
59  v[0][3] += t[0];
60  v[1][3] += t[1];
61  v[2][3] += t[2];
62  return *this;
63  }
64 
70  AffineMatrix transposed(column(0), column(1), column(2));
71  transposed(0, 3) = v[0][3];
72  transposed(1, 3) = v[1][3];
73  transposed(2, 3) = v[2][3];
74  return transposed;
75  }
76 
81  return v[0][0] * (v[1][1] * v[2][2] - v[2][1] * v[1][2]) -
82  v[0][1] * (v[1][0] * v[2][2] - v[1][2] * v[2][0]) +
83  v[0][2] * (v[1][0] * v[2][1] - v[1][1] * v[2][0]);
84  }
85 
87  const Float det = this->determinant();
88  SPH_ASSERT(det != 0._f);
89 
90  // from https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
91  AffineMatrix inv;
92  inv(0, 0) = v[1][1] * v[2][2] - v[2][1] * v[1][2];
93  inv(1, 0) = -v[1][0] * v[2][2] + v[2][0] * v[1][2];
94  inv(2, 0) = v[1][0] * v[2][1] - v[2][0] * v[1][1];
95  inv(0, 1) = -v[0][1] * v[2][2] + v[2][1] * v[0][2];
96  inv(1, 1) = v[0][0] * v[2][2] - v[2][0] * v[0][2];
97  inv(2, 1) = -v[0][0] * v[2][1] + v[2][0] * v[0][1];
98  inv(0, 2) = v[0][1] * v[1][2] - v[1][1] * v[0][2];
99  inv(1, 2) = -v[0][0] * v[1][2] + v[1][0] * v[0][2];
100  inv(2, 2) = v[0][0] * v[1][1] - v[1][0] * v[0][1];
101  inv(0, 3) = -v[0][1] * v[1][2] * v[2][3] + v[0][1] * v[1][3] * v[2][2] + v[1][1] * v[0][2] * v[2][3] -
102  v[1][1] * v[0][3] * v[2][2] - v[2][1] * v[0][2] * v[1][3] + v[2][1] * v[0][3] * v[1][2];
103  inv(1, 3) = v[0][0] * v[1][2] * v[2][3] - v[0][0] * v[1][3] * v[2][2] - v[1][0] * v[0][2] * v[2][3] +
104  v[1][0] * v[0][3] * v[2][2] + v[2][0] * v[0][2] * v[1][3] - v[2][0] * v[0][3] * v[1][2];
105  inv(2, 3) = -v[0][0] * v[1][1] * v[2][3] + v[0][0] * v[1][3] * v[2][1] + v[1][0] * v[0][1] * v[2][3] -
106  v[1][0] * v[0][3] * v[2][1] - v[2][0] * v[0][1] * v[1][3] + v[2][0] * v[0][3] * v[1][1];
107 
108  return inv / det;
109  }
110 
111  bool isOrthogonal() const {
112  for (Size i = 0; i < 3; ++i) {
113  for (Size j = 0; j < 3; ++j) {
114  const Float x = dot(v[i], v[j]);
115  if (!almostEqual(x, i == j ? 1._f : 0._f, 1.e-6_f)) {
116  return false;
117  }
118  }
119  }
120  return true;
121  }
122 
123  bool isIsotropic() const {
124  return v[0][0] == v[1][1] && v[0][0] == v[2][2] && v[0][1] == 0._f && v[0][2] == 0._f &&
125  v[1][2] == 0._f;
126  }
127 
128  static AffineMatrix null() {
129  return AffineMatrix(Vector(0._f), Vector(0._f), Vector(0._f));
130  }
131 
133  return AffineMatrix(Vector(1._f, 0._f, 0._f), Vector(0._f, 1._f, 0._f), Vector(0._f, 0._f, 1._f));
134  }
135 
136  static AffineMatrix scale(const Vector& scaling) {
137  return AffineMatrix(
138  Vector(scaling[X], 0._f, 0._f), Vector(0._f, scaling[Y], 0._f), Vector(0._f, 0._f, scaling[Z]));
139  }
140 
141  static AffineMatrix rotateX(const Float angle) {
142  const Float c = cos(angle);
143  const Float s = sin(angle);
144  return AffineMatrix(Vector(1._f, 0._f, 0._f), Vector(0._f, c, -s), Vector(0._f, s, c));
145  }
146 
147  static AffineMatrix rotateY(const Float angle) {
148  const Float c = cos(angle);
149  const Float s = sin(angle);
150  return AffineMatrix(Vector(c, 0._f, s), Vector(0._f, 1._f, 0._f), Vector(-s, 0._f, c));
151  }
152 
153  static AffineMatrix rotateZ(const Float angle) {
154  const Float c = cos(angle);
155  const Float s = sin(angle);
156  return AffineMatrix(Vector(c, -s, 0._f), Vector(s, c, 0._f), Vector(0._f, 0._f, 1._f));
157  }
158 
159  static AffineMatrix rotateAxis(const Vector& axis, const Float angle) {
160  SPH_ASSERT(almostEqual(getSqrLength(axis), 1._f), getSqrLength(axis));
161  const Float u = axis[0];
162  const Float v = axis[1];
163  const Float w = axis[2];
164  const Float s = sin(angle);
165  const Float c = cos(angle);
166  return {
167  Vector(u * u + (v * v + w * w) * c, u * v * (1 - c) - w * s, u * w * (1 - c) + v * s),
168  Vector(u * v * (1 - c) + w * s, v * v + (u * u + w * w) * c, v * w * (1 - c) - u * s),
169  Vector(u * w * (1 - c) - v * s, v * w * (1 - c) + u * s, w * w + (u * u + v * v) * c),
170  };
171  }
172 
174  return {
175  Vector(0._f, -a[Z], a[Y]),
176  Vector(a[Z], 0._f, -a[X]),
177  Vector(-a[Y], a[X], 0._f),
178  };
179  }
180 
182  return AffineMatrix(v[0] + other.v[0], v[1] + other.v[1], v[2] + other.v[2]);
183  }
184 
186  return AffineMatrix(v[0] - other.v[0], v[1] - other.v[1], v[2] - other.v[2]);
187  }
188 
192  for (Size i = 0; i < 3; ++i) {
193  for (Size j = 0; j < 3; ++j) {
194  result(i, j) = dot(this->row(i), other.column(j));
195  }
196  }
197  // add translation part
198  Vector t(0._f);
199  const Vector lhs = this->translation();
200  const Vector rhs = other.translation();
201  for (Size i = 0; i < 3; ++i) {
202  t[i] = dot(this->row(i), rhs) + lhs[i];
203  }
204  result.translate(t);
205  return result;
206  }
207 
208  INLINE Vector operator*(const Vector& u) const {
209  return Vector(dot(v[0], u) + v[0][3], dot(v[1], u) + v[1][3], dot(v[2], u) + v[2][3]);
210  }
211 
212  INLINE friend AffineMatrix operator*(const AffineMatrix& t, const Float v) {
213  return AffineMatrix(t.row(0) * v, t.row(1) * v, t.row(2) * v);
214  }
215 
216  INLINE friend AffineMatrix operator*(const Float v, const AffineMatrix& t) {
217  return t * v;
218  }
219 
220  INLINE friend AffineMatrix operator/(const AffineMatrix& t, const Float v) {
221  SPH_ASSERT(v != 0._f);
222  return AffineMatrix(t.row(0) / v, t.row(1) / v, t.row(2) / v);
223  }
224 
226  v[0] += other.v[0];
227  v[1] += other.v[1];
228  v[2] += other.v[2];
229  return *this;
230  }
231 
233  v[0] -= other.v[0];
234  v[1] -= other.v[1];
235  v[2] -= other.v[2];
236  return *this;
237  }
238 
241  v[0] *= value;
242  v[1] *= value;
243  v[2] *= value;
244  return *this;
245  }
246 
248  SPH_ASSERT(value != 0._f);
249  v[0] /= value;
250  v[1] /= value;
251  v[2] /= value;
252  return *this;
253  }
254 
255  INLINE bool operator==(const AffineMatrix& other) const {
256  // vectors check only first 3 components, can be optimized
257  return v[0] == other.v[0] && v[0][3] == other.v[0][3] && //
258  v[1] == other.v[1] && v[1][3] == other.v[1][3] && //
259  v[2] == other.v[2] && v[2][3] == other.v[2][3];
260  }
261 
262  INLINE bool operator!=(const AffineMatrix& other) const {
263  return !(*this == other);
264  }
265 
266  friend std::ostream& operator<<(std::ostream& stream, const AffineMatrix& t) {
267  stream << std::setprecision(PRECISION);
268  for (Size i = 0; i < 3; ++i) {
269  for (Size j = 0; j < 4; ++j) {
270  stream << std::setw(20) << t(i, j);
271  }
272  stream << std::endl;
273  }
274  return stream;
275  }
276 };
277 
278 INLINE bool almostEqual(const AffineMatrix& m1, const AffineMatrix& m2, const Float eps = EPS) {
279  for (Size i = 0; i < 4; ++i) {
280  if (!almostEqual(m1.column(i), m2.column(i), eps)) {
281  return false;
282  }
283  }
284  return true;
285 }
286 
287 
INLINE bool almostEqual(const AffineMatrix &m1, const AffineMatrix &m2, const Float eps=EPS)
Definition: AffineMatrix.h:278
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
constexpr int PRECISION
Number of valid digits of numbers on output.
Definition: Globals.h:25
constexpr Float EPS
Definition: MathUtils.h:30
INLINE T sin(const T f)
Definition: MathUtils.h:296
INLINE T cos(const T f)
Definition: MathUtils.h:291
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
Basic vector algebra. Computations are accelerated using SIMD.
INLINE Float getSqrLength(const Vector &v)
Definition: Vector.h:574
BasicVector< Float > Vector
Definition: Vector.h:539
INLINE float dot(const BasicVector< float > &v1, const BasicVector< float > &v2)
Make sure the vector is trivially constructible and destructible, needed for fast initialization of a...
Definition: Vector.h:548
@ Y
Definition: Vector.h:23
@ X
Definition: Vector.h:22
@ Z
Definition: Vector.h:24
INLINE AffineMatrix & operator*=(const Float value)
Definition: AffineMatrix.h:240
INLINE Float determinant() const
Computes determinant of the matrix.
Definition: AffineMatrix.h:80
static AffineMatrix identity()
Definition: AffineMatrix.h:132
INLINE Vector column(const Size idx) const
Definition: AffineMatrix.h:39
AffineMatrix()=default
INLINE AffineMatrix operator-(const AffineMatrix &other) const
Definition: AffineMatrix.h:185
INLINE AffineMatrix operator+(const AffineMatrix &other) const
Definition: AffineMatrix.h:181
static AffineMatrix scale(const Vector &scaling)
Definition: AffineMatrix.h:136
INLINE Vector translation() const
Definition: AffineMatrix.h:49
INLINE AffineMatrix & operator/=(const Float value)
Definition: AffineMatrix.h:247
INLINE AffineMatrix & operator-=(const AffineMatrix &other)
Definition: AffineMatrix.h:232
INLINE Float & operator()(const Size i, const Size j)
Definition: AffineMatrix.h:29
INLINE AffineMatrix & translate(const Vector &t)
Definition: AffineMatrix.h:58
bool isIsotropic() const
Definition: AffineMatrix.h:123
INLINE AffineMatrix transpose() const
Returns the transposed matrix.
Definition: AffineMatrix.h:69
AffineMatrix(const Vector &v1, const Vector &v2, const Vector &v3)
Construct the matrix from vectors as rows.
Definition: AffineMatrix.h:24
static AffineMatrix rotateY(const Float angle)
Definition: AffineMatrix.h:147
INLINE AffineMatrix operator*(const AffineMatrix &other) const
Matrix multiplication.
Definition: AffineMatrix.h:190
INLINE AffineMatrix & operator+=(const AffineMatrix &other)
Definition: AffineMatrix.h:225
INLINE Vector row(const Size idx) const
Definition: AffineMatrix.h:44
static AffineMatrix rotateAxis(const Vector &axis, const Float angle)
Definition: AffineMatrix.h:159
static AffineMatrix rotateX(const Float angle)
Definition: AffineMatrix.h:141
static AffineMatrix rotateZ(const Float angle)
Definition: AffineMatrix.h:153
AffineMatrix inverse() const
Definition: AffineMatrix.h:86
INLINE AffineMatrix & removeTranslation()
Definition: AffineMatrix.h:53
INLINE friend AffineMatrix operator/(const AffineMatrix &t, const Float v)
Definition: AffineMatrix.h:220
INLINE Vector operator*(const Vector &u) const
Definition: AffineMatrix.h:208
INLINE bool operator==(const AffineMatrix &other) const
Definition: AffineMatrix.h:255
INLINE Float operator()(const Size i, const Size j) const
Definition: AffineMatrix.h:34
friend std::ostream & operator<<(std::ostream &stream, const AffineMatrix &t)
Definition: AffineMatrix.h:266
INLINE friend AffineMatrix operator*(const Float v, const AffineMatrix &t)
Definition: AffineMatrix.h:216
INLINE bool operator!=(const AffineMatrix &other) const
Definition: AffineMatrix.h:262
bool isOrthogonal() const
Definition: AffineMatrix.h:111
static AffineMatrix crossProductOperator(const Vector &a)
Definition: AffineMatrix.h:173
INLINE friend AffineMatrix operator*(const AffineMatrix &t, const Float v)
Definition: AffineMatrix.h:212