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] = static_cast<Type>(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 
166  GenericMatrix operator*(const Type & val) const
167  {
168  GenericMatrix m = *this;
169  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] * val;
170  return m;
171  }
172  GenericMatrix operator/(const Type & val) const
173  {
174  GenericMatrix m = *this;
175  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] / val;
176  return m;
177  }
178  ///@}
179 
180  /// Unary minus
182  {
183  GenericMatrix m = *this;
184  for(int i = 0; i < size_; i++) m.data[i] = -m.data[i];
185  return m;
186  }
187 
188  /// check matrices are equal
189  bool operator==(const GenericMatrix& m)const
190  {
191  for(int i = 0; i < size_; i++)
192  if (data[i] != m.data[i])
193  return false;
194  return true;
195  }
196 
197  /// check matrices are not equal
198  bool operator!=(const GenericMatrix& m)const
199  {
200  return !(*this == m);
201  }
202 
203  Type& operator()(int row, int col)
204  {
205  return m[row][col];
206  }
207 
208  const Type& operator()(int row, int col) const
209  {
210  return m[row][col];
211  }
212 
213  /// Identity matrix
215  /// Make current matrix to identity
217  {
218  for(int x = 0; x < rows; x++)
219  for(int y = 0; y < cols; y++)
220  {
221  m[x][y] = x != y ? Type() : Type(1.0);
222  }
223  }
224  /// Check if matrix is an identity matrix
225  bool isIdentity() const
226  {
227  for(int x = 0; x < rows; x++)
228  for(int y = 0; y < cols; y++)
229  {
230  Type value = x != y ? Type() : Type(1.0);
231  if (m[x][y] != value)
232  return false;
233  }
234  return true;
235  }
236  /// Return transposed matrix copy
238  {
240  for(size_t i = 0; i < rows; i++)
241  for(size_t j = 0; j < cols; j++)
242  res.m[j][i] = m[i][j];
243 
244  return res;
245  }
246 
247  ///@{
248  /// Conversion to plain data pointer operator
249  operator Type * () { return data; }
250  operator const Type * () const { return data; }
251  ///@}
252  /// Returns the number of elements in the matrix
253  int size() const { return size_; }
254 
255  /// matrix data
256  union
257  {
258  struct
259  {
260  Type m[rows][cols];
261  };
262 
263  Type data[rows*cols];
264  };
265 
266 private:
267 
268  static int const size_;
269 };
270 
271 template< int rows, int cols, typename Type > int const GenericMatrix<rows, cols, Type>::size_ = rows * cols;
272 
273 template < typename Type, typename Type2 > inline
275  const Point3< Type2 > & point)
276 {
277  Point3< Type2 > res;
278  for(int i = 0; i < 3; i++)
279  {
280  double sum = 0.0;
281  for(int j = 0; j < 3; j++)
282  sum += matrix.m[i][j]*point.data[j];
283 
284  res.data[i] = (Type2)sum;
285  }
286 
287  return res;
288 }
289 
290 template< int rows, int cols, typename Type >
292 {
294  m.setToIdentity();
295  return m;
296 }
297 
298 /// Inversion
299 /// Return false if matrix is singular and can't be inverted, otherwise true
300 template < typename Type, int size > inline
302 {
303  //Copy source matrix
304  GenericMatrix< size, size, Type > work = matrix;
305 
306  //build identity matrix
307  result.setToIdentity();
308 
309  for(int i = 0; i < size; i++)
310  {
311  int j;
312 
313  for(j = i; (j < size) && (isZero(work[j*size+i])); j++) {};
314 
315  // matrix is singular
316  if (j == size)
317  return false;
318 
319  if (i != j)
320  for(int k = 0; k < size; k++)
321  {
322  Type tmp = result[i*size+k]; result[i*size+k] = result[j*size+k]; result[j*size+k] = tmp;
323  tmp = work[i*size+k]; work[i*size+k] = work[j*size+k]; work[j*size+k] = tmp;
324  }
325 
326  Type d = 1/work[i*size+i];
327  for(j = 0; j < size; j++)
328  {
329  result[i*size+j] *= d;
330  work[i*size+j] *= d;
331  }
332 
333  for(j = i+1; j < size; j++)
334  {
335  d = work[j*size+i];
336  for(int k = 0; k < size; k++)
337  {
338  result[j*size+k] -= result[i*size+k] * d;
339  work[j*size+k] -= work[i*size+k] * d;
340  }
341  }
342  }
343 
344  for(int i = size-1; i > 0; i--)
345  for(int j = 0; j < i; j++)
346  {
347  Type d = work[j*size+i];
348  for(int k = 0; k < size; k++)
349  {
350  result[j*size+k] -= result[i*size+k] * d;
351  work[j*size+k] -= work[i*size+k] * d;
352  }
353  }
354 
355  return true;
356 }
357 
358 /// Inversion (another one form) Given matrix shouldn't be singular.
359 /// Throws std::runtime_error() if matrix is singular, otherwise return inverse matrix
360 template < int size, typename Type > inline
362 {
364  if (invert(matrix,res))
365  return res;
366  else
367  throw std::runtime_error("artec::sdk::base::invert: Try to invert singular matrix");
368 }
369 
370 
371 template<int rows, int cols, typename MatType, typename Type>
373 {
374  if (vec.size() != rows * cols)
375  throw std::runtime_error("invalid matrix size");
376  return GenericMatrix<rows, cols, MatType>(&vec[0], rows, cols);
377 }
378 
379 template<int rows, int cols, typename Type>
380 GenericMatrix<rows, cols, Type> vectorToMatrix(const std::vector<Type>& vec)
381 {
382  if (vec.size() != rows * cols)
383  throw std::runtime_error("invalid matrix size");
384  return GenericMatrix<rows, cols, Type>(&vec[0], rows, cols);
385 }
386 
387 } } } // namespace artec::sdk::base
388 
389 
390 #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(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
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)