Zivid C++ API 2.14.0+e4a0c4a9-1
Matrix.h
Go to the documentation of this file.
1/*******************************************************************************
2 * This file is part of the Zivid API
3 *
4 * Copyright 2015-2024 (C) Zivid AS
5 * All rights reserved.
6 *
7 * Zivid Software License, v1.0
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of Zivid AS nor the names of its contributors may be used
20 * to endorse or promote products derived from this software without specific
21 * prior written permission.
22 *
23 * 4. This software, with or without modification, must not be used with any
24 * other 3D camera than from Zivid AS.
25 *
26 * 5. Any software provided in binary form under this license must not be
27 * reverse engineered, decompiled, modified and/or disassembled.
28 *
29 * THIS SOFTWARE IS PROVIDED BY ZIVID AS "AS IS" AND ANY EXPRESS OR IMPLIED
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31 * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 * DISCLAIMED. IN NO EVENT SHALL ZIVID AS OR CONTRIBUTORS BE LIABLE FOR ANY
33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
36 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Contact: Zivid Customer Success Team <customersuccess@zivid.com>
41 * Info: http://www.zivid.com
42 ******************************************************************************/
43
44#pragma once
45
47
48#include <array>
49#include <exception>
50#include <functional>
51#include <iterator>
52#include <ostream>
53#include <sstream>
54#include <string>
55
56namespace Zivid
57{
61 template<typename T, size_t rowCount, size_t colCount>
62 class Matrix
63 {
64 static_assert(rowCount > 0 && colCount > 0, "rowCount and colCount must be > 0");
65
66 private:
67 using Storage = std::array<T, rowCount * colCount>;
68
69 static constexpr bool invertSupported = ((rowCount == 4 && colCount == 4) || (rowCount == 3 && colCount == 3))
70 && (std::is_same<T, float>::value || std::is_same<T, double>::value);
71
72 static constexpr bool identitySupported = (rowCount == colCount) && (std::is_arithmetic<T>::value);
73
74 public:
78 using ValueType = T;
79
83 using Iterator = typename Storage::iterator;
84
88 using ConstIterator = typename Storage::const_iterator;
89
93 static constexpr size_t rows{ rowCount };
94
98 static constexpr size_t cols{ colCount };
99
101 Matrix() = default;
102
104 Matrix(const std::string &fileName)
105 {
106 load(fileName);
107 }
108
110 explicit Matrix(const std::array<T, colCount * rowCount> &arrArr)
111 : m_mat{ arrArr }
112 {}
113
115 template<typename U>
116 explicit Matrix(const Matrix<U, rowCount, colCount> &sourceMatrix)
117 : Matrix(sourceMatrix.begin(), sourceMatrix.end())
118 {}
119
121 template<typename Iterator>
122 Matrix(Iterator beginIt, Iterator endIt)
123 {
124 if(std::distance(beginIt, endIt) != rows * cols)
125 {
126 /* NOLINT */ throw std::out_of_range(
127 "Matrix constructor got input that does not match matrix size. Expected "
128 + std::to_string(rows * cols) + " items, got " + std::to_string(std::distance(beginIt, endIt))
129 + " items.");
130 }
131
132 std::copy(beginIt, endIt, m_mat.begin());
133 }
134
136 explicit Matrix(std::initializer_list<T> values)
137 : Matrix{ values.begin(), values.end() }
138 {}
139
141 explicit Matrix(std::initializer_list<std::initializer_list<T>> values)
142 {
143 if(values.size() != rows)
144 {
145 throw std::out_of_range(
146 "Matrix constructor got input that does not match matrix size. Expected " + std::to_string(rows)
147 + " rows, got " + std::to_string(values.size()) + " rows");
148 }
149
150 auto iterator = begin();
151 for(const auto &row : values)
152 {
153 if(row.size() != cols)
154 {
155 throw std::out_of_range(
156 "Matrix constructor got input that does not match matrix size. Expected all rows to be of size "
157 + std::to_string(cols) + ", got row with " + std::to_string(row.size()) + " values");
158 }
159 std::copy(std::begin(row), std::end(row), iterator);
160 std::advance(iterator, cols);
161 }
162 }
163
166 template<typename Q = T, typename = typename std::enable_if_t<identitySupported, Q>>
168 {
169 auto matrix = Matrix();
170 for(size_t i = 0; i < Matrix::rows; ++i)
171 {
172 matrix(i, i) = T{ 1 };
173 }
174 return matrix;
175 }
176
179 {
180 return m_mat.begin();
181 }
182
185 {
186 return m_mat.end();
187 }
188
191 {
192 return m_mat.begin();
193 }
194
197 {
198 return m_mat.end();
199 }
200
203 {
204 return m_mat.cbegin();
205 }
206
209 {
210 return m_mat.cend();
211 }
212
214 T &at(size_t row, size_t col)
215 {
216 throwIfOutOfBounds(row, col);
217 return m_mat[row * cols + col];
218 }
219
221 const T &at(size_t row, size_t col) const
222 {
223 throwIfOutOfBounds(row, col);
224 return m_mat[row * cols + col];
225 }
226
228 T &operator()(size_t row, size_t col)
229 {
230 return m_mat[row * cols + col];
231 }
232
234 const T &operator()(size_t row, size_t col) const
235 {
236 return m_mat[row * cols + col];
237 }
238
240 T *data()
241 {
242 return m_mat.data();
243 }
244
246 const T *data() const
247 {
248 return m_mat.data();
249 }
250
255 void save(const std::string &fileName) const;
256
262 void load(const std::string &fileName);
263
269 template<typename Q = T, typename = typename std::enable_if_t<invertSupported, Q>>
271
274 std::string toString() const
275 {
276 std::stringstream ss;
277 ss << "[ ";
278 for(size_t row = 0; row < rowCount; row++)
279 {
280 ss << (row == 0 ? "[" : "\n [");
281 for(size_t col = 0; col < colCount; col++)
282 {
283 const auto value{ m_mat[row * colCount + col] };
284 ss << (value >= 0 ? " " : "") << std::to_string(value);
285 ss << (col == colCount - 1 ? "" : ", ");
286 }
287 ss << (row == rowCount - 1 ? "]" : "], ");
288 }
289 ss << " ]";
290 return ss.str();
291 }
292
293 private:
294 static void throwIfOutOfBounds(size_t row, size_t col)
295 {
296 if(row >= rows)
297 {
298 throw std::out_of_range{ "Trying to access row with index " + std::to_string(row)
299 + ", but allowed range is [0, " + std::to_string(rows - 1) + "]" };
300 }
301 if(col >= cols)
302 {
303 throw std::out_of_range{ "Trying to access column with index " + std::to_string(col)
304 + ", but allowed range is [0, " + std::to_string(cols - 1) + "]" };
305 }
306 }
307
308 Storage m_mat{};
309 };
310
312 template<typename T, size_t rowCount, size_t colCount>
313 std::ostream &operator<<(std::ostream &stream, const Matrix<T, rowCount, colCount> &matrix)
314 {
315 return stream << matrix.toString();
316 }
317
322
327
332
337
338#ifndef NO_DOC
340 namespace Detail
341 {
343 saveFloatMatrix(const float *data, size_t rowCount, size_t colCount, const std::string &fileName);
344
346 loadFloatMatrix(float *data, size_t rowCount, size_t colCount, const std::string &fileName);
347 } // namespace Detail
348#endif
349
350#ifndef NO_DOC
351 extern template ZIVID_CORE_EXPORT Matrix<float, 4, 4> Matrix<float, 4, 4>::inverse<float, float>() const;
352
353 extern template ZIVID_CORE_EXPORT Matrix<double, 4, 4> Matrix<double, 4, 4>::inverse<double, double>() const;
354
355 extern template ZIVID_CORE_EXPORT Matrix<float, 3, 3> Matrix<float, 3, 3>::inverse<float, float>() const;
356
357 extern template ZIVID_CORE_EXPORT Matrix<double, 3, 3> Matrix<double, 3, 3>::inverse<double, double>() const;
358
359 template<typename T, size_t rowCount, size_t colCount>
360 void Matrix<T, rowCount, colCount>::save(const std::string &fileName) const
361 {
362 static_assert(std::is_same<T, float>::value, "Saving matrices of this type is not supported");
363
364 Detail::saveFloatMatrix(data(), rowCount, colCount, fileName);
365 }
366
367 template<typename T, size_t rowCount, size_t colCount>
368 void Matrix<T, rowCount, colCount>::load(const std::string &fileName)
369 {
370 static_assert(std::is_same<T, float>::value, "Loading matrices of this type is not supported");
371
372 Detail::loadFloatMatrix(data(), rowCount, colCount, fileName);
373 }
374
375#endif
376
377} // namespace Zivid
#define ZIVID_CORE_EXPORT
Definition CoreExport.h:56
A fixed size matrix in row major order.
Definition Matrix.h:63
static constexpr size_t rows
The number of rows in the matrix.
Definition Matrix.h:93
T ValueType
The type stored in the matrix.
Definition Matrix.h:78
T * data()
Pointer to the underlying data.
Definition Matrix.h:240
void load(const std::string &fileName)
Load the matrix from the given file.
ConstIterator begin() const
Iterator to the beginning of the matrix.
Definition Matrix.h:190
void save(const std::string &fileName) const
Save the matrix to the given file.
typename Storage::iterator Iterator
The matrix iterator type for mutable access. It iterates over individual matrix elements in row major...
Definition Matrix.h:83
static Matrix identity()
Get the identity matrix of given type and size.
Definition Matrix.h:167
Matrix(Iterator beginIt, Iterator endIt)
Constructor.
Definition Matrix.h:122
Matrix(std::initializer_list< T > values)
Constructor.
Definition Matrix.h:136
Matrix(const std::array< T, colCount *rowCount > &arrArr)
Constructor.
Definition Matrix.h:110
Matrix(const std::string &fileName)
Load the matrix from a file.
Definition Matrix.h:104
const T * data() const
Pointer to the underlying data.
Definition Matrix.h:246
static constexpr size_t cols
The number of columns in the matrix.
Definition Matrix.h:98
Iterator begin()
Iterator to the beginning of the matrix.
Definition Matrix.h:178
Matrix()=default
Constructor.
ConstIterator cbegin() const
Iterator to the beginning of the matrix.
Definition Matrix.h:202
T & at(size_t row, size_t col)
Access specified element with bounds checking.
Definition Matrix.h:214
std::string toString() const
Get string representation of the Matrix.
Definition Matrix.h:274
ConstIterator end() const
Iterator to the end of the matrix.
Definition Matrix.h:196
Matrix(std::initializer_list< std::initializer_list< T > > values)
Constructor.
Definition Matrix.h:141
const T & at(size_t row, size_t col) const
Access specified element with bounds checking.
Definition Matrix.h:221
const T & operator()(size_t row, size_t col) const
Access specified element without bounds checking.
Definition Matrix.h:234
Iterator end()
Iterator to the end of the matrix.
Definition Matrix.h:184
Matrix(const Matrix< U, rowCount, colCount > &sourceMatrix)
Constructor.
Definition Matrix.h:116
ZIVID_CORE_EXPORT Matrix inverse() const
Get the inverse of this matrix.
ConstIterator cend() const
Iterator to the end of the matrix.
Definition Matrix.h:208
T & operator()(size_t row, size_t col)
Access specified element without bounds checking.
Definition Matrix.h:228
typename Storage::const_iterator ConstIterator
The matrix iterator type for immutable access. It iterates over individual matrix elements in row maj...
Definition Matrix.h:88
The main Zivid namespace. All Zivid code is found here.
Definition Application.h:84
std::ostream & operator<<(std::ostream &stream, const Array2D< T > &array)
Serialize array information to a stream.
Definition Array2D.h:283