Artec 3D Scanning SDK  2.0
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 // Suppress 'nameless struct/union' warning
25 #pragma warning(push)
26 #pragma warning(disable: 4201)
27 
28 template< int rows, int cols, typename Type = double >
29 /// Matrix of unspecified size
31 {
32 public:
33  typedef Type value_type;
34 
36 
37  template< typename Type2, std::size_t sizeOfArray >
38  explicit GenericMatrix(const Type2 (&values)[sizeOfArray])
39  {
40  int c_assert[(rows * cols == sizeOfArray) ? 1 : -1];
41  (c_assert);
42  for(int i = 0; i < size_; i++)
43  data[i] = values[i];
44  }
45 
46  template< typename Type2 >
47  GenericMatrix(const Type2 * values, int rows2, int cols2)
48  {
49  for (int matrixRow = 0; matrixRow < rows; ++matrixRow) {
50  for (int matrixCol = 0; matrixCol < cols; ++matrixCol) {
51  if (matrixCol < cols2 && matrixRow < rows2)
52  m[matrixRow][matrixCol] = static_cast<Type>(values[matrixRow * cols2 + matrixCol]);
53  else if (matrixCol == matrixRow)
54  m[matrixRow][matrixCol] = Type(1);
55  else
56  m[matrixRow][matrixCol] = Type(0);
57  }
58  }
59  }
60 
61  /// Copying constructor
62  GenericMatrix(const GenericMatrix & second) { *this = second; }
63 
64  /// Copying constructor with type conversion
65  template< typename Type2 >
67  {
68  for(int i = 0; i < size_; i++) data[i] = (Type)second.data[i];
69  }
70 
71  /// Copying constructor with size conversion
72  template< int rows2, int cols2, typename Type2 >
73  explicit GenericMatrix(const GenericMatrix< rows2, cols2, Type2 > & second) { *this = second; }
74 
75  ///@{
76  /// Assignment operators
77  template< int rows2, int cols2 >
79  {
80  for (int matrixRow = 0; matrixRow < rows; ++matrixRow) {
81  for (int matrixCol = 0; matrixCol < cols; ++matrixCol) {
82  if (matrixCol < cols2 && matrixRow < rows2)
83  m[matrixRow][matrixCol] = second.m[matrixRow][matrixCol];
84  else if (matrixCol == matrixRow)
85  m[matrixRow][matrixCol] = Type(1);
86  else
87  m[matrixRow][matrixCol] = Type(0);
88  }
89  }
90  return *this;
91  }
92 
94  {
95  memcpy(data, second.data, size_*sizeof(Type));
96  return *this;
97  }
98  ///@}
99 
100  /// Populate matrix with value
101  void fill(const Type & value)
102  {
103  for(int i = 0; i < size_; i++)
104  data[i] = value;
105  }
106 
107  ///@{
108  /// Arithmetical operations
109  /// Matrix-Matrix (element-wise)
111  {
112  for(int i = 0; i < size_; i++) data[i] += mat.data[i];
113  return *this;
114  }
116  {
117  for(int i = 0; i < size_; i++) data[i] -= mat.data[i];
118  return *this;
119  }
121  {
122  *this = *this * other;
123  return *this;
124  }
125 
127  {
128  GenericMatrix m = *this;
129  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] + mat.data[i];
130  return m;
131  }
132 
134  {
135  GenericMatrix res = *this;
136  for(int i = 0; i < size_; i++) res.data[i] = res.data[i] - mat.data[i];
137  return res;
138  }
139  ///@}
140 
141  /// Matrix-matrix multiplication
142  template< int cols2 >
144  {
146  for(int i = 0; i < rows; i++)
147  for(int j = 0; j < cols2; j++)
148  {
149  Type sum = 0;
150  for(int k = 0; k < cols; k++)
151  sum += m[i][k]*mat.m[k][j];
152 
153  res.m[i][j] = sum;
154  }
155  return res;
156  }
157 
158  ///@{
159  /// Matrix-Scalar
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 
171  GenericMatrix operator*(const Type & val) const
172  {
173  GenericMatrix m = *this;
174  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] * val;
175  return m;
176  }
177  GenericMatrix operator/(const Type & val) const
178  {
179  GenericMatrix m = *this;
180  for(int i = 0; i < size_; i++) m.data[i] = m.data[i] / val;
181  return m;
182  }
183  ///@}
184 
185  /// Unary minus
187  {
188  GenericMatrix m = *this;
189  for(int i = 0; i < size_; i++) m.data[i] = -m.data[i];
190  return m;
191  }
192 
193  /// Check whether the matrices are equal
194  bool operator==(const GenericMatrix& other)const
195  {
196  for(int i = 0; i < size_; i++)
197  if (data[i] != other.data[i])
198  return false;
199  return true;
200  }
201 
202  /// Check matrices whether the are not equal
203  bool operator!=(const GenericMatrix& m)const
204  {
205  return !(*this == m);
206  }
207 
208  Type& operator()(int row, int col)
209  {
210  return m[row][col];
211  }
212 
213  const Type& operator()(int row, int col) const
214  {
215  return m[row][col];
216  }
217 
218  /// Identity matrix
220  /// Convert current matrix to identity one
222  {
223  for(int x = 0; x < rows; x++)
224  for(int y = 0; y < cols; y++)
225  {
226  m[x][y] = x != y ? Type() : Type(1.0);
227  }
228  }
229  /// Check whether the matrix is an identity one
230  bool isIdentity() const
231  {
232  for(int x = 0; x < rows; x++)
233  for(int y = 0; y < cols; y++)
234  {
235  Type value = x != y ? Type() : Type(1.0);
236  if (m[x][y] != value)
237  return false;
238  }
239  return true;
240  }
241  /// Return transposed matrix copy
243  {
245  for(size_t i = 0; i < rows; i++)
246  for(size_t j = 0; j < cols; j++)
247  res.m[j][i] = m[i][j];
248 
249  return res;
250  }
251 
252  ///@{
253  /// Conversion to plain data pointer operator
254  operator Type * () { return data; }
255  operator const Type * () const { return data; }
256  ///@}
257  /// Return the number of elements in the matrix
258  int size() const { return size_; }
259 
260  /// Matrix data
261  union
262  {
263  struct
264  {
265  Type m[rows][cols];
266  };
267 
268  Type data[rows*cols];
269  };
270 
271 private:
272 
273  static int const size_;
274 };
275 
276 template< int rows, int cols, typename Type > int const GenericMatrix<rows, cols, Type>::size_ = rows * cols;
277 
278 template < typename Type, typename Type2 > inline
280  const Point3< Type2 > & point)
281 {
282  Point3< Type2 > res;
283  for(int i = 0; i < 3; i++)
284  {
285  double sum = 0.0;
286  for(int j = 0; j < 3; j++)
287  sum += matrix.m[i][j]*point.data[j];
288 
289  res.data[i] = (Type2)sum;
290  }
291 
292  return res;
293 }
294 
295 template< int rows, int cols, typename Type >
297 {
299  m.setToIdentity();
300  return m;
301 }
302 
303 /// Inversion
304 /// It returns "false", if the matrix is singular and can't be inverted, otherwise the value is "true"
305 template < typename Type, int size > inline
307 {
308  //Copy source matrix
309  GenericMatrix< size, size, Type > work = matrix;
310 
311  //Build identity matrix
312  result.setToIdentity();
313 
314  for(int i = 0; i < size; i++)
315  {
316  int j;
317 
318  for(j = i; (j < size) && (isZero(work[j*size+i])); j++) {};
319 
320  // Matrix is singular
321  if (j == size)
322  return false;
323 
324  if (i != j)
325  for(int k = 0; k < size; k++)
326  {
327  Type tmp = result[i*size+k]; result[i*size+k] = result[j*size+k]; result[j*size+k] = tmp;
328  tmp = work[i*size+k]; work[i*size+k] = work[j*size+k]; work[j*size+k] = tmp;
329  }
330 
331  Type d = 1/work[i*size+i];
332  for(j = 0; j < size; j++)
333  {
334  result[i*size+j] *= d;
335  work[i*size+j] *= d;
336  }
337 
338  for(j = i+1; j < size; j++)
339  {
340  d = work[j*size+i];
341  for(int k = 0; k < size; k++)
342  {
343  result[j*size+k] -= result[i*size+k] * d;
344  work[j*size+k] -= work[i*size+k] * d;
345  }
346  }
347  }
348 
349  for(int i = size-1; i > 0; i--)
350  for(int j = 0; j < i; j++)
351  {
352  Type d = work[j*size+i];
353  for(int k = 0; k < size; k++)
354  {
355  result[j*size+k] -= result[i*size+k] * d;
356  work[j*size+k] -= work[i*size+k] * d;
357  }
358  }
359 
360  return true;
361 }
362 
363 /// Inversion (another form). The given matrix shouldn't be singular.
364 /// It throws std::runtime_error() if matrix is singular, otherwise returns an inversed matrix.
365 template < int size, typename Type > inline
367 {
369  if (invert(matrix,res))
370  return res;
371  else
372  throw std::runtime_error("artec::sdk::base::invert: Try to invert singular matrix");
373 }
374 
375 
376 template<int rows, int cols, typename MatType, typename Type>
378 {
379  if (vec.size() != rows * cols)
380  throw std::runtime_error("invalid matrix size");
381  return GenericMatrix<rows, cols, MatType>(&vec[0], rows, cols);
382 }
383 
384 template<int rows, int cols, typename Type>
385 GenericMatrix<rows, cols, Type> vectorToMatrix(const std::vector<Type>& vec)
386 {
387  if (vec.size() != rows * cols)
388  throw std::runtime_error("invalid matrix size");
389  return GenericMatrix<rows, cols, Type>(&vec[0], rows, cols);
390 }
391 
392 } } } // namespace artec::sdk::base
393 
394 #pragma warning(pop)
395 
396 #endif //_GENERICMATRIX_H_
GenericMatrix & operator-=(const GenericMatrix &mat)
void setToIdentity()
Convert current matrix to identity one.
GenericMatrix & operator*=(const GenericMatrix &other)
bool isIdentity() const
Check whether the matrix is an identity one.
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:93
GenericMatrix(const GenericMatrix< rows, cols, Type2 > &second)
Copying constructor with type conversion.
Definition: GenericMatrix.h:66
bool invert(const GenericMatrix< size, size, Type > &matrix, GenericMatrix< size, size, Type > &result)
Inversion It returns "false", if the matrix is singular and can't be inverted, otherwise the value is...
void fill(const Type &value)
Populate matrix with value.
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)
3-dimensional point class.
Definition: Point.h:25
GenericMatrix(const GenericMatrix< rows2, cols2, Type2 > &second)
Copying constructor with size conversion.
Definition: GenericMatrix.h:73
GenericMatrix(const Type2 *values, int rows2, int cols2)
Definition: GenericMatrix.h:47
bool operator==(const GenericMatrix &other) const
Check whether the matrices are equal.
bool operator!=(const GenericMatrix &m) const
Check matrices whether the are not equal.
Matrix of unspecified size.
Definition: GenericMatrix.h:30
static GenericMatrix< rows, cols, Type > identity()
Identity matrix.
int size() const
Return the number of elements in the matrix.
GenericMatrix & operator=(const GenericMatrix< rows2, cols2, Type > &second)
Definition: GenericMatrix.h:78
GenericMatrix(const Type2(&values)[sizeOfArray])
Definition: GenericMatrix.h:38
GenericMatrix operator+(const GenericMatrix &mat) const
GenericMatrix operator-() const
Unary minus.
bool isZero(const Tf &some)
Equality expression for the types which are not exact.
Definition: Point.h:29
GenericMatrix(const GenericMatrix &second)
Copying constructor.
Definition: GenericMatrix.h:62
GenericMatrix & operator+=(const GenericMatrix &mat)