Reworked the Matrix interface so that less index math is involved

Sat, 28 Jan 2017 17:14:05 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sat, 28 Jan 2017 17:14:05 +0200
changeset 1068
283de3bd8b0e
parent 1067
819973864620
child 1069
220cde0fa2d9

Reworked the Matrix interface so that less index math is involved

src/basics.cpp file | annotate | diff | comparison | revisions
src/editmodes/circleMode.cpp file | annotate | diff | comparison | revisions
src/ldDocument.cpp file | annotate | diff | comparison | revisions
src/ldObject.cpp file | annotate | diff | comparison | revisions
src/mainwindow.cpp file | annotate | diff | comparison | revisions
src/miscallenous.cpp file | annotate | diff | comparison | revisions
src/types/matrix.cpp file | annotate | diff | comparison | revisions
src/types/matrix.h file | annotate | diff | comparison | revisions
--- a/src/basics.cpp	Sat Jan 28 16:30:27 2017 +0200
+++ b/src/basics.cpp	Sat Jan 28 17:14:05 2017 +0200
@@ -37,11 +37,11 @@
 	QVector3D(xpos, ypos, zpos) {}
 
 
-void Vertex::transform (const Matrix& matr, const Vertex& pos)
+void Vertex::transform (const Matrix& matrix, const Vertex& pos)
 {
-	double x2 = (matr[0] * x()) + (matr[1] * y()) + (matr[2] * z()) + pos.x();
-	double y2 = (matr[3] * x()) + (matr[4] * y()) + (matr[5] * z()) + pos.y();
-	double z2 = (matr[6] * x()) + (matr[7] * y()) + (matr[8] * z()) + pos.z();
+	double x2 = (matrix(0, 0) * x()) + (matrix(0, 1) * y()) + (matrix(0, 2) * z()) + pos.x();
+	double y2 = (matrix(1, 0) * x()) + (matrix(1, 1) * y()) + (matrix(1, 2) * z()) + pos.y();
+	double z2 = (matrix(2, 0) * x()) + (matrix(2, 1) * y()) + (matrix(2, 2) * z()) + pos.z();
 	setX (x2);
 	setY (y2);
 	setZ (z2);
--- a/src/editmodes/circleMode.cpp	Sat Jan 28 16:30:27 2017 +0200
+++ b/src/editmodes/circleMode.cpp	Sat Jan 28 17:14:05 2017 +0200
@@ -72,12 +72,12 @@
 
 	Matrix transform = templates[renderer()->camera() % 3];
 
-	for (int i = 0; i < 9; ++i)
+	for (double& value : transform)
 	{
-		if (transform[i] == 2)
-			transform[i] = scale;
-		else if (transform[i] == 1 and renderer()->camera() >= 3)
-			transform[i] = -1;
+		if (value == 2)
+			value = scale;
+		else if (value == 1 and renderer()->camera() >= 3)
+			value = -1;
 	}
 
 	return transform;
--- a/src/ldDocument.cpp	Sat Jan 28 16:30:27 2017 +0200
+++ b/src/ldDocument.cpp	Sat Jan 28 17:14:05 2017 +0200
@@ -494,7 +494,7 @@
 				Matrix transform;
 
 				for (int i = 0; i < 9; ++i)
-					transform[i] = tokens[i + 5].toDouble(); // 5 - 13
+					transform.value(i) = tokens[i + 5].toDouble(); // 5 - 13
 
 				obj->setTransformationMatrix (transform);
 				obj->setFileInfo (document);
--- a/src/ldObject.cpp	Sat Jan 28 16:30:27 2017 +0200
+++ b/src/ldObject.cpp	Sat Jan 28 17:14:05 2017 +0200
@@ -702,13 +702,13 @@
 		Matrix matrixModifier = IdentityMatrix;
 
 		if (axisSet & (1 << X))
-			matrixModifier[0] = -1;
+			matrixModifier(0, 0) = -1;
 
 		if (axisSet & (1 << Y))
-			matrixModifier[4] = -1;
+			matrixModifier(1, 1) = -1;
 
 		if (axisSet & (1 << Z))
-			matrixModifier[8] = -1;
+			matrixModifier(2, 2) = -1;
 
 		setTransformationMatrix (transformationMatrix() * matrixModifier);
 		return;
--- a/src/mainwindow.cpp	Sat Jan 28 16:30:27 2017 +0200
+++ b/src/mainwindow.cpp	Sat Jan 28 17:14:05 2017 +0200
@@ -435,7 +435,7 @@
 				descr = format ("%1 %2, (", ref->fileInfo()->getDisplayName(), ref->position().toString (true));
 
 				for (int i = 0; i < 9; ++i)
-					descr += format ("%1%2", ref->transformationMatrix()[i], (i != 8) ? " " : "");
+					descr += format ("%1%2", ref->transformationMatrix().value(i), (i != 8) ? " " : "");
 
 				descr += ')';
 				break;
--- a/src/miscallenous.cpp	Sat Jan 28 16:30:27 2017 +0200
+++ b/src/miscallenous.cpp	Sat Jan 28 17:14:05 2017 +0200
@@ -75,13 +75,13 @@
 void applyToMatrix (Matrix& a, ApplyToMatrixFunction func)
 {
 	for (int i = 0; i < 9; ++i)
-		func (i, a[i]);
+		func(i, a.value(i));
 }
 
 void applyToMatrix (const Matrix& a, ApplyToMatrixConstFunction func)
 {
 	for (int i = 0; i < 9; ++i)
-		func (i, a[i]);
+		func(i, a.value(i));
 }
 
 
--- a/src/types/matrix.cpp	Sat Jan 28 16:30:27 2017 +0200
+++ b/src/types/matrix.cpp	Sat Jan 28 17:14:05 2017 +0200
@@ -20,15 +20,13 @@
 #include "../format.h"
 #include "matrix.h"
 
-/**
- * @brief Matrix::Matrix
- * Default-constructor for a matrix -- does not actually initialize the member values.
+/*
+ * Default-constructor for a matrix
  */
-Matrix::Matrix() {}
+Matrix::Matrix() :
+    m_values{0} {}
 
-/**
- * @brief Matrix::Matrix
- * @param values
+/*
  * Initializes the matrix from a C array
  * Note: the array must have (at least) 9 values!
  */
@@ -38,20 +36,13 @@
 		m_values[i] = values[i];
 }
 
-/**
- * @brief Matrix::Matrix
- * @param fillvalue
+/*
  * Constructs a matrix from a single fill value.
  */
-Matrix::Matrix (double fillvalue)
-{
-	for (int i = 0; i < 9; ++i)
-		m_values[i] = fillvalue;
-}
+Matrix::Matrix (double fillvalue) :
+    m_values {fillvalue} {}
 
-/**
- * @brief Matrix::Matrix
- * @param values
+/*
  * Constructs a matrix from an initializer list.
  * Note: the initializer list must have exactly 9 values.
  */
@@ -61,8 +52,7 @@
 		memcpy (&m_values[0], values.begin(), sizeof m_values);
 }
 
-/**
- * @brief Matrix::dump
+/*
  * Prints the matrix out.
  */
 void Matrix::dump() const
@@ -76,9 +66,8 @@
 	}
 }
 
-/**
- * @brief Matrix::toString
- * @return a string representation of the matrix
+/*
+ * Returns a string representation of the matrix
  */
 QString Matrix::toString() const
 {
@@ -95,8 +84,7 @@
 	return val;
 }
 
-/**
- * @brief Matrix::zero
+/*
  * Fills the matrix with zeros
  */
 void Matrix::zero()
@@ -104,28 +92,24 @@
 	memset (&m_values[0], 0, sizeof m_values);
 }
 
-/**
- * @brief Matrix::multiply
- * @param other
- * @return this matrix multiplied with @c other.
- * @note @c a.mult(b) is not equivalent to @c b.mult(a)
+/*
+ * Performs matrix multiplication.
+ * Note: A*B is not equivalent to B*A!
  */
 Matrix Matrix::multiply (const Matrix& other) const
 {
 	Matrix result;
-	result.zero();
 
 	for (int i = 0; i < 3; ++i)
 	for (int j = 0; j < 3; ++j)
 	for (int k = 0; k < 3; ++k)
-		result[(i * 3) + j] += m_values[(i * 3) + k] * other[(k * 3) + j];
+		result[i][j] += (*this)[i][k] * other[k][j];
 
 	return result;
 }
 
-/**
- * @brief Matrix::determinant
- * @return the matrix's determinant
+/*
+ * Returns the matrix's determinant
  */
 double Matrix::determinant() const
 {
@@ -137,10 +121,48 @@
 		   (value (0) * value (5) * value (7));
 }
 
-/**
- * @brief Matrix::operator ==
- * @param other
- * @return whether the two matrices are equal
+/*
+ * Returns a value in matrix value (index math must be done manually)
+ */
+double& Matrix::value(int index)
+{
+	return m_values[index];
+}
+
+/*
+ * Returns a value in matrix value (index math must be done manually)
+ */
+const double& Matrix::value(int index) const
+{
+	return m_values[index];
+}
+
+/*
+ * Performs matrix multiplication
+ */
+Matrix Matrix::operator*(const Matrix &other) const
+{
+	return multiply(other);
+}
+
+/*
+ * Returns a row of the matrix
+ */
+Matrix::RowView Matrix::operator[](int row)
+{
+	return RowView {*this, row};
+}
+
+/*
+ * Returns a row of the matrix
+ */
+Matrix::ConstRowView Matrix::operator[](int row) const
+{
+	return ConstRowView {*this, row};
+}
+
+/*
+ * Checks whether the two matrices are equal
  */
 bool Matrix::operator==(const Matrix& other) const
 {
@@ -162,3 +184,70 @@
 	return not operator==(other);
 }
 
+double& Matrix::operator()(int row, int column)
+{
+	return m_values[row * 3 + column];
+}
+
+const double& Matrix::operator()(int row, int column) const
+{
+	return m_values[row * 3 + column];
+}
+
+double* Matrix::begin()
+{
+	return m_values;
+}
+
+const double* Matrix::begin() const
+{
+	return m_values;
+}
+
+double* Matrix::end()
+{
+	return m_values + countof(m_values);
+}
+
+const double* Matrix::end() const
+{
+	return m_values + countof(m_values);
+}
+
+Matrix::RowView::RowView(Matrix &matrix, int row) :
+    _matrix {matrix},
+    _row {row} {}
+
+double& Matrix::RowView::operator[](int column)
+{
+	return _matrix.value(_row * 3 + column);
+}
+
+Matrix& Matrix::RowView::matrix() const
+{
+	return _matrix;
+}
+
+int Matrix::RowView::row()
+{
+	return _row;
+}
+
+Matrix::ConstRowView::ConstRowView(const Matrix &matrix, int row) :
+    _matrix {matrix},
+    _row {row} {}
+
+const double& Matrix::ConstRowView::operator[](int column)
+{
+	return _matrix.value(_row * 3 + column);
+}
+
+const Matrix& Matrix::ConstRowView::matrix() const
+{
+	return _matrix;
+}
+
+int Matrix::ConstRowView::row()
+{
+	return _row;
+}
\ No newline at end of file
--- a/src/types/matrix.h	Sat Jan 28 16:30:27 2017 +0200
+++ b/src/types/matrix.h	Sat Jan 28 17:14:05 2017 +0200
@@ -19,41 +19,73 @@
 #pragma once
 #include <QString>
 
-/**
- * @brief The Matrix class
+/*
  * A mathematical 3 x 3 matrix
  */
 class Matrix
 {
 public:
+	class RowView;
+	class ConstRowView;
+
 	Matrix();
 	Matrix (const std::initializer_list<double>& values);
 	Matrix (double fillval);
 	Matrix (double values[]);
 
+	double* begin();
+	const double* begin() const;
 	double determinant() const;
-	Matrix multiply (const Matrix& other) const;
 	void dump() const;
+	double* end();
+	const double* end() const;
+	Matrix multiply(const Matrix& other) const;
 	QString toString() const;
+	double& value(int index);
+	const double& value(int index) const;
 	void zero();
+
 	bool operator==(const Matrix& other) const;
 	bool operator!=(const Matrix& other) const;
-
-	/// @returns a mutable reference to a value by @c idx.
-	inline double& value (int idx) { return m_values[idx]; }
-
-	/// @returns a const reference to a value by @c idx.
-	inline const double& value (int idx) const { return m_values[idx]; }
-
-	/// @returns this matrix multiplied by @c other.
-	inline Matrix operator* (const Matrix& other) const { return multiply (other); }
-
-	/// @returns a mutable reference to a value by @c idx.
-	inline double& operator[] (int idx) { return value(idx); }
-
-	/// @returns a const reference to a value by @c idx.
-	inline const double& operator[] (int idx) const { return value (idx); }
+	Matrix operator*(const Matrix& other) const;
+	RowView operator[](int row);
+	ConstRowView operator[](int row) const;
+	double& operator()(int row, int column);
+	const double& operator()(int row, int column) const;
 
 private:
 	double m_values[9];
 };
+
+/*
+ * A structure that provides a view into a row in a matrix.
+ * This is returned by operator[] so that the matrix can be accessed by A[i][j]
+ */
+class Matrix::RowView
+{
+public:
+	RowView(Matrix &matrix, int row);
+	double& operator[](int column);
+	Matrix& matrix() const;
+	int row();
+
+private:
+	Matrix& _matrix;
+	const int _row;
+};
+
+/*
+ * Const version of the above
+ */
+class Matrix::ConstRowView
+{
+public:
+	ConstRowView(const Matrix &matrix, int row);
+	const double& operator[](int column);
+	const Matrix& matrix() const;
+	int row();
+
+private:
+	const Matrix& _matrix;
+	const int _row;
+};

mercurial