FastEngine 0.9.3
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
C_matrix.inl
1/*
2 * Copyright 2024 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17namespace fge
18{
19
20template<class T>
22 g_msize(0, 0)
23{}
24
25template<class T>
26Matrix<T>::Matrix(std::initializer_list<std::initializer_list<T>> data)
27{
28 this->set(data);
29}
30
31template<class T>
32template<class Tvec>
33Matrix<T>::Matrix(fge::Vector2<Tvec> const& msize)
34{
35 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
36 this->setSize(static_cast<std::size_t>(msize.x), static_cast<std::size_t>(msize.y));
37}
38template<class T>
39Matrix<T>::Matrix(std::size_t sizex, std::size_t sizey)
40{
41 this->setSize(sizex, sizey);
42}
43
44template<class T>
45template<class Tvec>
46Matrix<T>::Matrix(fge::Vector2<Tvec> const& msize, T const& defaultValue)
47{
48 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
49 this->setSize(static_cast<std::size_t>(msize.x), static_cast<std::size_t>(msize.y));
50 this->fill(defaultValue);
51}
52template<class T>
53Matrix<T>::Matrix(std::size_t sizex, std::size_t sizey, T const& defaultValue)
54{
55 this->setSize(sizex, sizey);
56 this->fill(defaultValue);
58
59template<class T>
61{
62 this->setSize(m.g_msize);
63 for (std::size_t i = 0; i < m.getTotalSize(); ++i)
64 {
65 this->g_mdata[i] = m.g_mdata[i];
66 }
67}
68template<class T>
70 g_msize(m.g_msize),
71 g_mdata(std::move(m.g_mdata))
72{
73 m.g_msize.y = 0;
74 m.g_msize.x = 0;
75}
76
77template<class T>
79{
80 this->g_mdata.reset();
81 this->g_msize.x = 0;
82 this->g_msize.y = 0;
84
85template<class T>
87{
88 this->setSize(m.g_msize);
89 for (std::size_t i = 0; i < m.getTotalSize(); ++i)
90 {
91 this->g_mdata[i] = m.g_mdata[i];
92 }
93 return *this;
94}
95template<class T>
96fge::Matrix<T>& Matrix<T>::operator=(fge::Matrix<T>&& m) noexcept
97{
98 this->g_msize = m.g_msize;
99 m.g_msize.y = 0;
100 m.g_msize.x = 0;
101 this->g_mdata = std::move(m.g_mdata);
102 return *this;
103}
104
105template<class T>
106T* Matrix<T>::operator[](std::size_t x)
107{
108 return FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, 0);
109}
110template<class T>
111T const* Matrix<T>::operator[](std::size_t x) const
113 return FGE_MATRIX_GET(T const, this->g_mdata.get(), this->g_msize.y, x, 0);
114}
115
116template<class T>
117T const& Matrix<T>::get(std::size_t x, std::size_t y) const
118{
119 return *FGE_MATRIX_GET(T const, this->g_mdata.get(), this->g_msize.y, x, y);
120}
121template<class T>
122template<class Tvec>
123T const& Matrix<T>::get(fge::Vector2<Tvec> const& coord) const
124{
125 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
126 return *FGE_MATRIX_GET(T const, this->g_mdata.get(), this->g_msize.y, static_cast<std::size_t>(coord.x),
127 static_cast<std::size_t>(coord.y));
128}
129template<class T>
130T& Matrix<T>::get(std::size_t x, std::size_t y)
131{
132 return *FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, y);
133}
134template<class T>
135template<class Tvec>
136T& Matrix<T>::get(fge::Vector2<Tvec> const& coord)
137{
138 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
139 return *FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, static_cast<std::size_t>(coord.x),
140 static_cast<std::size_t>(coord.y));
141}
142
143template<class T>
144bool Matrix<T>::get(std::size_t x, std::size_t y, T& buff) const
145{
146 if ((x < this->g_msize.x) && (y < this->g_msize.y))
147 {
148 buff = *FGE_MATRIX_GET(T const, this->g_mdata.get(), this->g_msize.y, x, y);
149 return true;
150 }
151 return false;
152}
153template<class T>
154template<class Tvec>
155bool Matrix<T>::get(fge::Vector2<Tvec> const& coord, T& buff) const
156{
157 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
158 return this->get(static_cast<std::size_t>(coord.x), static_cast<std::size_t>(coord.y), buff);
159}
160
161template<class T>
162T* Matrix<T>::getPtr(std::size_t x, std::size_t y)
164 if ((x < this->g_msize.x) && (y < this->g_msize.y))
165 {
166 return FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, y);
167 }
168 return nullptr;
169}
170template<class T>
171template<class Tvec>
172T* Matrix<T>::getPtr(fge::Vector2<Tvec> const& coord)
173{
174 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
175 return this->getPtr(static_cast<std::size_t>(coord.x), static_cast<std::size_t>(coord.y));
176}
177template<class T>
178T const* Matrix<T>::getPtr(std::size_t x, std::size_t y) const
179{
180 if ((x < this->g_msize.x) && (y < this->g_msize.y))
181 {
182 return FGE_MATRIX_GET(T const, this->g_mdata.get(), this->g_msize.y, x, y);
183 }
184 return nullptr;
185}
186template<class T>
187template<class Tvec>
188T const* Matrix<T>::getPtr(fge::Vector2<Tvec> const& coord) const
189{
190 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
191 return this->getPtr(static_cast<std::size_t>(coord.x), static_cast<std::size_t>(coord.y));
192}
194template<class T>
195void Matrix<T>::set(std::size_t x, std::size_t y, T&& value)
196{
197 *FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, y) = std::move(value);
198}
199template<class T>
200template<class Tvec>
201void Matrix<T>::set(fge::Vector2<Tvec> const& coord, T&& value)
202{
203 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
204 *FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, static_cast<std::size_t>(coord.x),
205 static_cast<std::size_t>(coord.y)) = std::move(value);
206}
207template<class T>
208void Matrix<T>::set(std::size_t x, std::size_t y, T const& value)
209{
210 *FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, y) = value;
211}
212template<class T>
213template<class Tvec>
214void Matrix<T>::set(fge::Vector2<Tvec> const& coord, T const& value)
215{
216 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
217 *FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, static_cast<std::size_t>(coord.x),
218 static_cast<std::size_t>(coord.y)) = value;
220
221template<class T>
222void Matrix<T>::set(std::initializer_list<std::initializer_list<T>> data)
223{
224 std::size_t const sizey = data.size();
225 std::size_t sizex = 0;
226 if (sizey > 0)
227 {
228 auto it = data.begin();
229 sizex = it->size();
230 for (++it; it != data.end(); ++it)
231 {
232 if (it->size() != sizex)
233 {
234 throw fge::Exception("Matrix : size must be constant between rows");
235 }
236 }
237 }
239 this->setSize(sizex, sizey);
240
241 std::size_t ycount = 0;
242 for (auto datay: data)
243 {
244 std::size_t xcount = 0;
245 for (auto datax: datay)
246 {
247 *FGE_MATRIX_GET(T, this->g_mdata.get(), sizey, xcount, ycount) = std::move(datax);
248 ++xcount;
249 }
250 ++ycount;
252}
253
254template<class T>
255inline std::size_t Matrix<T>::getTotalSize() const
256{
257 return this->g_msize.x * this->g_msize.y;
258}
259template<class T>
260fge::Vector2<std::size_t> const& Matrix<T>::getSize() const
261{
262 return this->g_msize;
263}
264template<class T>
265std::size_t Matrix<T>::getSizeX() const
267 return this->g_msize.x;
268}
269template<class T>
270std::size_t Matrix<T>::getSizeY() const
271{
272 return this->g_msize.y;
274
275template<class T>
276inline T const* Matrix<T>::get() const
277{
278 return this->g_mdata;
279}
280template<class T>
281inline T* Matrix<T>::get()
282{
283 return this->g_mdata;
284}
286template<class T>
287typename Matrix<T>::iterator Matrix<T>::begin()
288{
289 return this->g_mdata.get();
290}
291template<class T>
292typename Matrix<T>::iterator Matrix<T>::end()
293{
294 return this->g_mdata.get() + this->getTotalSize();
296template<class T>
297typename Matrix<T>::const_iterator Matrix<T>::begin() const
298{
299 return this->g_mdata.get();
300}
301template<class T>
302typename Matrix<T>::const_iterator Matrix<T>::end() const
303{
304 return this->g_mdata.get() + this->getTotalSize();
306
307template<class T>
308template<class Tvec>
309void Matrix<T>::setSize(fge::Vector2<Tvec> const& msize)
310{
311 static_assert(std::is_integral<Tvec>::value, "Tvec must be an integral type");
312 this->setSize(static_cast<std::size_t>(msize.x), static_cast<std::size_t>(msize.y));
313}
314template<class T>
315void Matrix<T>::setSize(std::size_t sizex, std::size_t sizey)
317 if (sizex == this->g_msize.x && sizey == this->g_msize.y)
318 { //Same size, ignoring
319 return;
320 }
321 if (sizex == 0 || sizey == 0)
322 { //Null size, aborting
323 throw fge::Exception("Matrix : size cannot be 0");
324 }
325
326 this->g_mdata.reset(new T[sizex * sizey]);
327 this->g_msize.x = sizex;
328 this->g_msize.y = sizey;
329}
330
331template<class T>
332void Matrix<T>::fill(T const& value)
333{
334 for (std::size_t x = 0; x < this->g_msize.x; ++x)
335 {
336 for (std::size_t y = 0; y < this->g_msize.y; ++y)
337 {
338 *FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, y) = value;
339 }
340 }
341}
342
343template<class T>
345{
346 Matrix<T> newMatrix(this->g_msize.y, this->g_msize.x);
347
348 for (std::size_t y = 0; y < this->g_msize.y; ++y)
349 {
350 for (std::size_t x = 0; x < this->g_msize.x; ++x)
351 {
352 newMatrix[newMatrix.g_msize.x - y - 1][x] =
353 std::move(*FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, y));
354 }
355 }
356 this->g_mdata = std::move(newMatrix.g_mdata);
357 this->g_msize = newMatrix.g_msize;
358}
359template<class T>
361{
362 Matrix<T> newMatrix(this->g_msize.y, this->g_msize.x);
363
364 for (std::size_t y = 0; y < this->g_msize.y; ++y)
365 {
366 for (std::size_t x = 0; x < this->g_msize.x; ++x)
367 {
368 newMatrix[y][newMatrix.g_msize.y - x - 1] =
369 std::move(*FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, y));
370 }
371 }
372 this->g_mdata = std::move(newMatrix.g_mdata);
373 this->g_msize = newMatrix.g_msize;
374}
375
376template<class T>
377void Matrix<T>::rotateClockwise(unsigned int n)
378{
379 n %= 4;
380 while (n > 0)
381 {
382 this->rotateClockwise();
383 --n;
384 }
385}
386template<class T>
388{
389 n %= 4;
390 while (n > 0)
391 {
392 this->rotateCounterClockwise();
393 --n;
394 }
395}
396
397template<class T>
399{
400 Matrix<T> newMatrix(this->g_msize.x, this->g_msize.y);
401
402 for (std::size_t x = 0; x < this->g_msize.x; ++x)
403 {
404 for (std::size_t y = 0; y < this->g_msize.y; ++y)
405 {
406 newMatrix[x][y] =
407 std::move(*FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, this->g_msize.x - 1 - x, y));
408 }
409 }
410 this->g_mdata = std::move(newMatrix.g_mdata);
411 this->g_msize = newMatrix.g_msize;
412}
413
414template<class T>
416{
417 Matrix<T> newMatrix(this->g_msize.x, this->g_msize.y);
418
419 for (std::size_t x = 0; x < this->g_msize.x; ++x)
420 {
421 for (std::size_t y = 0; y < this->g_msize.y; ++y)
422 {
423 newMatrix[x][y] =
424 std::move(*FGE_MATRIX_GET(T, this->g_mdata.get(), this->g_msize.y, x, this->g_msize.y - 1 - y));
425 }
426 }
427 this->g_mdata = std::move(newMatrix.g_mdata);
428 this->g_msize = newMatrix.g_msize;
429}
430
431template<class T>
432void Matrix<T>::toVector(std::vector<T>& buff) const
433{
434 buff.assign(this->g_mdata.get(), this->g_mdata.get() + this->g_msize.x * this->g_msize.y);
435}
436
437template<class T>
438void to_json(nlohmann::json& j, fge::Matrix<T> const& r)
439{
440 nlohmann::json data = {{"sizeX", r.getSizeX()}, {"sizeY", r.getSizeY()}};
441
442 nlohmann::json& datay = data["data"];
443 datay = nlohmann::json::array();
444
445 for (std::size_t y = 0; y < r.getSizeY(); ++y)
446 {
447 nlohmann::json datax = nlohmann::json::array();
448 for (std::size_t x = 0; x < r.getSizeX(); ++x)
449 {
450 datax += r[x][y];
451 }
452 datay += datax;
453 }
454 j = data;
455}
456template<class T>
457void from_json(nlohmann::json const& j, fge::Matrix<T>& r)
458{
459 std::size_t sizex;
460 std::size_t sizey;
461
462 j.at("sizeX").get_to(sizex);
463 j.at("sizeY").get_to(sizey);
464
465 nlohmann::json const& datay = j.at("data");
466
467 if (!datay.is_array())
468 {
469 throw fge::Exception("Matrix json : must be an array");
470 }
471 if (datay.size() != sizey)
472 {
473 throw fge::Exception("Matrix json : size y is not the same");
474 }
475
476 r.setSize(sizex, sizey);
477
478 std::size_t y = 0;
479 for (nlohmann::json::const_iterator ity = datay.begin(); ity != datay.end(); ++ity)
480 {
481 if (!(*ity).is_array())
482 {
483 throw fge::Exception("Matrix json : must be an array");
484 }
485 if ((*ity).size() != sizex)
486 {
487 throw fge::Exception("Matrix json : size x is not the same");
488 }
489
490 std::size_t x = 0;
491 for (nlohmann::json::const_iterator itx = (*ity).begin(); itx != (*ity).end(); ++itx)
492 {
493 (*itx).get_to(r[x][y]);
494 ++x;
495 }
496 ++y;
497 }
498}
499
500} // namespace fge
Definition fge_except.hpp:28
A container to store a 2D matrix of any type.
Definition C_matrix.hpp:40
void rotateCounterClockwise()
Rotate the matrix by 90 degrees counter-clockwise.
Definition C_matrix.inl:360
void clear()
Clear the matrix and set the size to 0,0.
Definition C_matrix.inl:78
void set(std::size_t x, std::size_t y, T &&value)
Set the specified value by moving it.
Definition C_matrix.inl:195
void fill(T const &value)
Fill the matrix by copying a value.
Definition C_matrix.inl:332
void setSize(fge::Vector2< Tvec > const &msize)
Set the size of the matrix.
Definition C_matrix.inl:309
T * operator[](std::size_t x)
Get the specified row.
Definition C_matrix.inl:106
std::size_t getTotalSize() const
Get the total number of elements in the matrix.
Definition C_matrix.inl:255
Matrix()
Construct a empty matrix.
Definition C_matrix.inl:21
void flipVertically()
Flip the matrix vertically.
Definition C_matrix.inl:415
T const & get(std::size_t x, std::size_t y) const
Get the specified value.
Definition C_matrix.inl:117
fge::Vector2< std::size_t > const & getSize() const
Get the size of the matrix as a vector2.
Definition C_matrix.inl:260
std::size_t getSizeY() const
Get the y size of the matrix.
Definition C_matrix.inl:270
void rotateClockwise()
Rotate the matrix by 90 degrees clockwise.
Definition C_matrix.inl:344
void toVector(std::vector< T > &buff) const
Insert all elements of the matrix in a 1D vector.
Definition C_matrix.inl:432
void flipHorizontally()
Flip the matrix horizontally.
Definition C_matrix.inl:398
std::size_t getSizeX() const
Get the x size of the matrix.
Definition C_matrix.inl:265
T const * get() const
Get the 2D array of the matrix.
Definition C_matrix.inl:276
T * getPtr(std::size_t x, std::size_t y)
Get the specified value as a pointer.
Definition C_matrix.inl:162