GenericMatrix.h
Go to the documentation of this file.
1 /********************************************************************
2  *
3  * Project Artec 3D Scanning SDK
4  *
5  * Purpose: Definition of template matrix classes for use in
6  * geometric transformations
7  *
8  * Copyright: Artec Group
9  *
10  ********************************************************************/
11 
12 #ifndef _GENERICMATRIX_H_
13 #define _GENERICMATRIX_H_
14 
15 #include <assert.h>
16 #include <cstring>
17 #include <stdexcept>
18 #include <vector>
19 #include <artec/sdk/base/Point.h>
20 
21 namespace artec { namespace sdk { namespace base
22 {
23 
24 template< int rows, int cols, typename Type = double >
26 {
27 public:
28  typedef Type value_type;
29 
31 
32  template< typename Type2, std::size_t sizeOfArray >
33  explicit GenericMatrix(const Type2 (&values)[sizeOfArray])
34  {
35  int c_assert[(rows * cols == sizeOfArray) ? 1 : -1];
36  (c_assert);
37  for(int i = 0; i < size_; i++)
38  data[i] = values[i];
39  }
40 
41  template< typename Type2 >
42  GenericMatrix(const Type2 * values, int rows2, int cols2)
43  {
44  for (int matrixRow = 0; matrixRow < rows; ++matrixRow) {
45  for (int matrixCol = 0; matrixCol < cols; ++matrixCol) {
46  if (matrixCol < cols2 && matrixRow < rows2)
47  m[matrixRow][matrixCol] = values[matrixRow * cols2 + matrixCol];
48  else if (matrixCol == matrixRow)
49  m[matrixRow][matrixCol] = Type(1);
50  else
51  m[matrixRow][matrixCol] = Type(0);
52  }
53  }
54  }
55 
56  /// Copying constructor
57  GenericMatrix(const GenericMatrix & second) { *this = second; }
58 
59  /// Copying constructor with type conversion
60  template< typename Type2 >
62  {
63  for(int i = 0; i < size_; i++) data[i] = (Type)second.data[i];
64  }
65 
66  /// Copying constructor with size conversion
67  template< int rows2, int cols2, typename Type2 >
68  explicit GenericMatrix(const GenericMatrix< rows2, cols2, Type2 > & second) { *this = second; }
69 
70  ///@{
71  /// Assignment operators
72  template< int rows2, int cols2 >
74  {
75  for (int matrixRow = 0; matrixRow < rows; ++matrixRow) {
76  for (int matrixCol = 0; matrixCol < cols; ++matrixCol) {
77  if (matrixCol < cols2 && matrixRow < rows2)
78  m[matrixRow][matrixCol] = second.m[matrixRow][matrixCol];
79  else if (matrixCol == matrixRow)
80  m[matrixRow][matrixCol] = Type(1);
81  else
82  m[matrixRow][matrixCol] = Type(0);
83  }
84  }
85  return *this;
86  }
87 
89  {
90  memcpy(data, second.data, size_*sizeof(Type));
91  return *this;
92  }
93  ///@}
94 
95  /// Fill matrix with value
96  void fill(const Type & value)
97  {
98  for(int i = 0; i < size_; i++)
99  data[i] = value;
100  }
101 
102  ///@{
103  /// Arithmetical operations
104  /// Matrix - Matrix (element-wise)
106  {
107  for(int i = 0; i < size_; i++) data[i] += mat.data[i];
108  return *this;
109  }
111  {
112  for(int i = 0; i < size_; i++) data[i] -= mat.data[i];
113  return *this;
114  }
116  {
117  *this = *this * other;
118  return *this;
119  }
120 
122  {
123  GenericMatrix m = *this;
124  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] + mat.data[i];
125  return m;
126  }
127 
129  {
130  GenericMatrix m = *this;
131  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] - mat.data[i];
132  return m;
133  }
134  ///@}
135 
136  /// Matrix - matrix multiplication
137  template< int cols2 >
139  {
141  for(int i = 0; i < rows; i++)
142  for(int j = 0; j < cols2; j++)
143  {
144  Type sum = 0;
145  for(int k = 0; k < cols; k++)
146  sum += m[i][k]*mat.m[k][j];
147 
148  res.m[i][j] = sum;
149  }
150  return res;
151  }
152 
153  ///@{
154  /// Matrix - Scalar
155  GenericMatrix & operator+=(const Type & val)
156  {
157  for(int i = 0; i < size_; i++) data[i] += val;
158  return *this;
159  }
160  GenericMatrix & operator-=(const Type & val)
161  {
162  for(int i = 0; i < size_; i++) data[i] -= val;
163  return *this;
164  }
165  GenericMatrix & operator*=(const Type & val)
166  {
167  for(int i = 0; i < size_; i++) data[i] *= val;
168  return *this;
169  }
170  GenericMatrix & operator/=(const Type & val)
171  {
172  for(int i = 0; i < size_; i++) data[i] /= val;
173  return *this;
174  }
175 
176  GenericMatrix operator+(const Type & val) const
177  {
178  GenericMatrix m = *this;
179  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] + val;
180  return m;
181  }
182  GenericMatrix operator-(const Type & val) const
183  {
184  GenericMatrix m = *this;
185  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] - val;
186  return m;
187  }
188  GenericMatrix operator*(const Type & val) const
189  {
190  GenericMatrix m = *this;
191  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] * val;
192  return m;
193  }
194  GenericMatrix operator/(const Type & val) const
195  {
196  GenericMatrix m = *this;
197  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] / val;
198  return m;
199  }
200  ///@}
201 
202  /// Unary minus
204  {
205  GenericMatrix m = *this;
206  for(int i = 0; i < size_; i++) m.data[i] = -m.data[i];
207  return m;
208  }
209 
210  /// check matrices are equal
211  bool operator==(const GenericMatrix& m)const
212  {
213  for(int i = 0; i < size_; i++)
214  if (data[i] != m.data[i])
215  return false;
216  return true;
217  }
218 
219  /// check matrices are not equal
220  bool operator!=(const GenericMatrix& m)const
221  {
222  return !(*this == m);
223  }
224 
225  Type& operator()(int row, int col)
226  {
227  return m[row][col];
228  }
229 
230  const Type& operator()(int row, int col) const
231  {
232  return m[row][col];
233  }
234 
235  /// Identity matrix
237  /// Make current matrix to identity
239  {
240  for(int x = 0; x < rows; x++)
241  for(int y = 0; y < cols; y++)
242  {
243  m[x][y] = x != y ? Type() : Type(1.0);
244  }
245  }
246  /// Check if matrix is an identity matrix
247  bool isIdentity() const
248  {
249  for(int x = 0; x < rows; x++)
250  for(int y = 0; y < cols; y++)
251  {
252  Type value = x != y ? Type() : Type(1.0);
253  if (m[x][y] != value)
254  return false;
255  }
256  return true;
257  }
258  /// Return transposed matrix copy
260  {
262  for(size_t i = 0; i < rows; i++)
263  for(size_t j = 0; j < cols; j++)
264  res.m[j][i] = m[i][j];
265 
266  return res;
267  }
268 
269  ///@{
270  /// Conversion to plain data pointer operator
271  operator Type * () { return data; }
272  operator const Type * () const { return data; }
273  ///@}
274  /// Returns the number of elements in the matrix
275  int size() const { return size_; }
276 
277  /// matrix data
278  union
279  {
280  struct
281  {
282  Type m[rows][cols];
283  };
284 
285  Type data[rows*cols];
286  };
287 
288 private:
289 
290  static int const size_;
291 };
292 
293 template< int rows, int cols, typename Type > int const GenericMatrix<rows, cols, Type>::size_ = rows * cols;
294 
295 template < typename Type, typename Type2 > inline
297  const Point3< Type2 > & point)
298 {
299  Point3< Type2 > res;
300  for(int i = 0; i < 3; i++)
301  {
302  double sum = 0.0;
303  for(int j = 0; j < 3; j++)
304  sum += matrix.m[i][j]*point.data[j];
305 
306  res.data[i] = (Type2)sum;
307  }
308 
309  return res;
310 }
311 
312 template< int rows, int cols, typename Type >
314 {
316  m.setToIdentity();
317  return m;
318 }
319 
320 /// Inversion
321 /// Return false if matrix is singular and can't be inverted, otherwise true
322 template < typename Type, int size > inline
324 {
325  //Copy source matrix
326  GenericMatrix< size, size, Type > work = matrix;
327 
328  //build identity matrix
329  result.setToIdentity();
330 
331  for(int i = 0; i < size; i++)
332  {
333  int j;
334 
335  for(j = i; (j < size) && (isZero(work[j*size+i])); j++) {};
336 
337  // matrix is singular
338  if (j == size)
339  return false;
340 
341  if (i != j)
342  for(int k = 0; k < size; k++)
343  {
344  Type tmp = result[i*size+k]; result[i*size+k] = result[j*size+k]; result[j*size+k] = tmp;
345  tmp = work[i*size+k]; work[i*size+k] = work[j*size+k]; work[j*size+k] = tmp;
346  }
347 
348  Type d = 1/work[i*size+i];
349  for(j = 0; j < size; j++)
350  {
351  result[i*size+j] *= d;
352  work[i*size+j] *= d;
353  }
354 
355  for(j = i+1; j < size; j++)
356  {
357  d = work[j*size+i];
358  for(int k = 0; k < size; k++)
359  {
360  result[j*size+k] -= result[i*size+k] * d;
361  work[j*size+k] -= work[i*size+k] * d;
362  }
363  }
364  }
365 
366  for(int i = size-1; i > 0; i--)
367  for(int j = 0; j < i; j++)
368  {
369  Type d = work[j*size+i];
370  for(int k = 0; k < size; k++)
371  {
372  result[j*size+k] -= result[i*size+k] * d;
373  work[j*size+k] -= work[i*size+k] * d;
374  }
375  }
376 
377  return true;
378 }
379 
380 /// Inversion (another one form) Given matrix shouldn't be singular.
381 /// Throws std::runtime_error() if matrix is singular, otherwise return inverse matrix
382 template < int size, typename Type > inline
384 {
386  if (invert(matrix,res))
387  return res;
388  else
389  throw std::runtime_error("artec::sdk::base::invert: Try to invert singular matrix");
390 }
391 
392 
393 template<int rows, int cols, typename MatType, typename Type>
395 {
396  if (vec.size() != rows * cols)
397  throw std::runtime_error("invalid matrix size");
398  return GenericMatrix<rows, cols, MatType>(&vec[0], rows, cols);
399 }
400 
401 template<int rows, int cols, typename Type>
402 GenericMatrix<rows, cols, Type> vectorToMatrix(const std::vector<Type>& vec)
403 {
404  if (vec.size() != rows * cols)
405  throw std::runtime_error("invalid matrix size");
406  return GenericMatrix<rows, cols, Type>(&vec[0], rows, cols);
407 }
408 
409 } } } // namespace artec::sdk::base
410 
411 
412 #endif //_GENERICMATRIX_H_
GenericMatrix & operator-=(const GenericMatrix &mat)
void setToIdentity()
Make current matrix to identity.
GenericMatrix & operator*=(const GenericMatrix &other)
bool isIdentity() const
Check if matrix is an identity matrix.
Point3< Type2 > operator*(const GenericMatrix< 3, 3, Type > &matrix, const Point3< Type2 > &point)
GenericMatrix & operator/=(const Type &val)
GenericMatrix operator-(const GenericMatrix &mat) const
GenericMatrix< cols, rows, Type > transposed() const
Return transposed matrix copy.
const Type & operator()(int row, int col) const
GenericMatrix operator/(const Type &val) const
GenericMatrix & operator=(const GenericMatrix &second)
Definition: GenericMatrix.h:88
GenericMatrix(const GenericMatrix< rows, cols, Type2 > &second)
Copying constructor with type conversion.
Definition: GenericMatrix.h:61
bool invert(const GenericMatrix< size, size, Type > &matrix, GenericMatrix< size, size, Type > &result)
void fill(const Type &value)
Fill matrix with value.
Definition: GenericMatrix.h:96
GenericMatrix operator*(const Type &val) const
GenericMatrix< rows, cols2, Type > operator*(const GenericMatrix< cols, cols2, Type > &mat) const
Matrix - matrix multiplication.
GenericMatrix & operator*=(const Type &val)
GenericMatrix< rows, cols, MatType > vectorToMatrix(const std::vector< Type > &vec)
Type & operator()(int row, int col)
GenericMatrix & operator-=(const Type &val)
GenericMatrix(const GenericMatrix< rows2, cols2, Type2 > &second)
Copying constructor with size conversion.
Definition: GenericMatrix.h:68
GenericMatrix(const Type2 *values, int rows2, int cols2)
Definition: GenericMatrix.h:42
bool operator!=(const GenericMatrix &m) const
check matrices are not equal
GenericMatrix operator-(const Type &val) const
GenericMatrix operator+(const Type &val) const
static GenericMatrix< rows, cols, Type > identity()
Identity matrix.
GenericMatrix & operator=(const GenericMatrix< rows2, cols2, Type > &second)
Definition: GenericMatrix.h:73
GenericMatrix(const Type2(&values)[sizeOfArray])
Definition: GenericMatrix.h:33
bool operator==(const GenericMatrix &m) const
check matrices are equal
GenericMatrix operator+(const GenericMatrix &mat) const
GenericMatrix operator-() const
Unary minus.
bool isZero(const Tf &some)
Equality expression for types which are not exact.
Definition: Point.h:25
GenericMatrix(const GenericMatrix &second)
Copying constructor.
Definition: GenericMatrix.h:57
GenericMatrix & operator+=(const GenericMatrix &mat)
GenericMatrix & operator+=(const Type &val)