1 #pragma once |
1 #pragma once |
2 #include <QGenericMatrix> |
2 #include <QGenericMatrix> |
|
3 #include <type_traits> |
|
4 |
|
5 template<int Rows, int Columns, typename T = double> |
|
6 struct MatrixIterator; |
|
7 |
|
8 template<int Rows, int Columns> |
|
9 struct MatrixIndex |
|
10 { |
|
11 int row; |
|
12 int column; |
|
13 }; |
3 |
14 |
4 template<int Rows, int Columns, typename T = double> |
15 template<int Rows, int Columns, typename T = double> |
5 struct Matrix |
16 struct Matrix |
6 { |
17 { |
|
18 using Iterator = MatrixIterator<Rows, Columns, T>; |
7 T values[Rows][Columns]; |
19 T values[Rows][Columns]; |
|
20 Iterator begin() |
|
21 { |
|
22 return {*this, {0, 0}}; |
|
23 } |
|
24 Iterator end() |
|
25 { |
|
26 return {*this, {Rows, 0}}; |
|
27 } |
8 T& operator()(int row, int column) |
28 T& operator()(int row, int column) |
9 { |
29 { |
10 return this->values[row][column]; |
30 return this->values[row][column]; |
11 } |
31 } |
12 T operator()(int row, int column) const |
32 T operator()(int row, int column) const |
13 { |
33 { |
14 return this->values[row][column]; |
34 return this->values[row][column]; |
15 } |
35 } |
|
36 T& operator[](const MatrixIndex<Rows, Columns>& index) |
|
37 { |
|
38 return (*this)(index.row, index.column); |
|
39 } |
|
40 T operator[](const MatrixIndex<Rows, Columns>& index) const |
|
41 { |
|
42 return (*this)(index.row, index.column); |
|
43 } |
16 }; |
44 }; |
|
45 |
|
46 template<int Rows, int Columns, typename T> |
|
47 struct MatrixIterator |
|
48 { |
|
49 struct Value |
|
50 { |
|
51 const MatrixIndex<Rows, Columns> index; |
|
52 decltype(std::declval<Matrix<Rows, Columns, T>>()(0, 0)) value; |
|
53 }; |
|
54 Matrix<Rows, Columns, T>& matrix; |
|
55 MatrixIndex<Rows, Columns> index; |
|
56 }; |
|
57 |
|
58 template<int Rows, int Columns> |
|
59 auto& operator++(MatrixIndex<Rows, Columns>& index) |
|
60 { |
|
61 index.column += 1; |
|
62 if (index.column >= Columns) |
|
63 { |
|
64 index.row += 1; |
|
65 index.column -= Columns; |
|
66 } |
|
67 return index; |
|
68 } |
|
69 |
|
70 template<int Rows, int Columns> |
|
71 bool operator==( |
|
72 const MatrixIndex<Rows, Columns>& one, |
|
73 const MatrixIndex<Rows, Columns>& other) |
|
74 { |
|
75 return one.row == other.row and one.column == other.column; |
|
76 } |
|
77 template<int Rows, int Columns, typename T> |
|
78 auto& operator++(MatrixIterator<Rows, Columns, T>& iterator) |
|
79 { |
|
80 ++iterator.index; |
|
81 return iterator; |
|
82 } |
|
83 |
|
84 template<int Rows, int Columns, typename T> |
|
85 bool operator==( |
|
86 const MatrixIterator<Rows, Columns, T>& one, |
|
87 const MatrixIterator<Rows, Columns, T>& other) |
|
88 { |
|
89 return &one.matrix == &other.matrix and one.index == other.index; |
|
90 } |
|
91 |
|
92 template<int Rows, int Columns, typename T> |
|
93 bool operator!=( |
|
94 const MatrixIterator<Rows, Columns, T>& one, |
|
95 const MatrixIterator<Rows, Columns, T>& other) |
|
96 { |
|
97 return not (one == other); |
|
98 } |
|
99 |
|
100 template<int Rows, int Columns, typename T> |
|
101 auto operator*(MatrixIterator<Rows, Columns, T>& iterator) |
|
102 -> typename MatrixIterator<Rows, Columns, T>::Value |
|
103 { |
|
104 return {iterator.index, iterator.matrix[iterator.index]}; |
|
105 } |
17 |
106 |
18 template<int Rows, int Columns, typename T> |
107 template<int Rows, int Columns, typename T> |
19 QGenericMatrix<Rows, Columns, T> matrixToQGenericMatrix(const Matrix<Rows, Columns, T>& matrix) |
108 QGenericMatrix<Rows, Columns, T> matrixToQGenericMatrix(const Matrix<Rows, Columns, T>& matrix) |
20 { |
109 { |
21 return {matrix.values}; |
110 return {matrix.values}; |
23 |
112 |
24 template<int Rows, int Columns, typename T> |
113 template<int Rows, int Columns, typename T> |
25 Matrix<Rows, Columns, T> matrixFromQGenericMatrix(const QGenericMatrix<Rows, Columns, T&> matrix) |
114 Matrix<Rows, Columns, T> matrixFromQGenericMatrix(const QGenericMatrix<Rows, Columns, T&> matrix) |
26 { |
115 { |
27 Matrix<Rows, Columns, T> result; |
116 Matrix<Rows, Columns, T> result; |
28 for (int row = 0; row < Rows; row += 1) |
117 for (auto& cell : result) |
29 { |
118 { |
30 for (int column = 0; column < Columns; column += 1) |
119 matrix(cell.index.row, cell.index.column) = result[cell.index]; |
31 { |
|
32 result(row, column) = matrix(row, column); |
|
33 } |
|
34 } |
120 } |
35 return result; |
121 return result; |
36 } |
122 } |
37 |
123 |
38 using Matrix3x3 = Matrix<3, 3>; |
124 using Matrix3x3 = Matrix<3, 3>; |
41 Q_DECLARE_METATYPE(Matrix4x4); |
127 Q_DECLARE_METATYPE(Matrix4x4); |
42 |
128 |
43 template<int Rows, int Columns, typename T> |
129 template<int Rows, int Columns, typename T> |
44 QDataStream& operator<<(QDataStream& stream, const Matrix<Rows, Columns, T>& matrix) |
130 QDataStream& operator<<(QDataStream& stream, const Matrix<Rows, Columns, T>& matrix) |
45 { |
131 { |
46 return stream << matrixToQGenericMatrix(matrix); |
132 for (auto& cell : matrix) |
|
133 { |
|
134 stream << cell.value; |
|
135 } |
|
136 return stream; |
47 } |
137 } |
48 |
138 |
49 template<int Rows, int Columns, typename T> |
139 template<int Rows, int Columns, typename T> |
50 QDataStream& operator>>(QDataStream& stream, Matrix<Rows, Columns, T>& matrix) |
140 QDataStream& operator>>(QDataStream& stream, Matrix<Rows, Columns, T>& matrix) |
51 { |
141 { |
52 QGenericMatrix<Rows, Columns, T> qmatrix; |
142 for (auto& cell : matrix) |
53 stream >> qmatrix; |
143 { |
54 matrix = matrixFromQGenericMatrix(matrix); |
144 stream >> cell.value; |
|
145 } |
55 return stream; |
146 return stream; |
56 } |
147 } |
|
148 |
|
149 static constexpr Matrix3x3 identity3x3 {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}}; |
|
150 static constexpr Matrix4x4 identity4x4 {{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}}; |