Blame c++/vector/matrix.h

Ivan Mahonin 145120
#ifndef MATRIX_H
Ivan Mahonin 145120
#define MATRIX_H
Ivan Mahonin 145120
Ivan Mahonin 145120
Ivan Mahonin 145120
#include <cmath>
Ivan Mahonin 145120
Ivan Mahonin 145120
#include "vector.h"
Ivan Mahonin 145120
Ivan Mahonin 145120
Ivan Mahonin 145120
class Matrix {
Ivan Mahonin 145120
public:
Ivan Mahonin 145120
	union {
Ivan Mahonin 145120
		Real m[3][3];
Ivan Mahonin 145120
		struct {
Ivan Mahonin 145120
			Real m00, m01, m02;
Ivan Mahonin 145120
			Real m10, m11, m12;
Ivan Mahonin 145120
			Real m20, m21, m22;
Ivan Mahonin 145120
		};
Ivan Mahonin 145120
	};
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix(
Ivan Mahonin 145120
		Real m00, Real m01, Real m02,
Ivan Mahonin 145120
		Real m10, Real m11, Real m12,
Ivan Mahonin 145120
		Real m20, Real m21, Real m22
Ivan Mahonin 145120
	):
Ivan Mahonin 145120
		m00(m00), m01(m01), m02(m02),
Ivan Mahonin 145120
		m10(m10), m11(m11), m12(m12),
Ivan Mahonin 145120
		m20(m20), m21(m21), m22(m22)
Ivan Mahonin 145120
	{ }
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix(): Matrix(
Ivan Mahonin 145120
		1, 0, 0,
Ivan Mahonin 145120
		0, 1, 0,
Ivan Mahonin 145120
		0, 0, 1 ) { }
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix(
Ivan Mahonin 145120
		const Vector &axis_x,
Ivan Mahonin 145120
		const Vector &axis_y,
Ivan Mahonin 145120
		const Vector &offset = Vector()
Ivan Mahonin 145120
	): Matrix(
Ivan Mahonin 145120
		axis_x.x, axis_x.y, 0,
Ivan Mahonin 145120
		axis_y.x, axis_y.y, 0,
Ivan Mahonin 145120
		offset.x, offset.y, 1 ) { }
Ivan Mahonin 145120
Ivan Mahonin 145120
	const Vector& axis(int index) const { return *(const Vector*)(m[index]); }
Ivan Mahonin 145120
	const Vector& axis_x() const { return axis(0); }
Ivan Mahonin 145120
	const Vector& axis_y() const { return axis(1); }
Ivan Mahonin 145120
	const Vector& offset() const { return axis(2); }
Ivan Mahonin 145120
Ivan Mahonin 145120
	Vector& axis(int index) { return *(Vector*)(m[index]); }
Ivan Mahonin 145120
	Vector& axis_x() { return axis(0); }
Ivan Mahonin 145120
	Vector& axis_y() { return axis(1); }
Ivan Mahonin 145120
	Vector& offset() { return axis(2); }
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix& set_identity()
Ivan Mahonin 145120
		{ return *this = Matrix(); }
Ivan Mahonin 145120
	bool is_identity() const
Ivan Mahonin 145120
		{ return *this == Matrix(); }
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix& set_scale(const Real &x, const Real &y) {
Ivan Mahonin 145120
		return *this = Matrix( x, 0, 0,
Ivan Mahonin 145120
							   0, y, 0,
Ivan Mahonin 145120
							   0, 0, 1 );
Ivan Mahonin 145120
	}
Ivan Mahonin 145120
	Matrix& set_scale(const Real &s)
Ivan Mahonin 145120
		{ return set_scale(s, s); }
Ivan Mahonin 145120
	Matrix& set_scale(const Vector &s)
Ivan Mahonin 145120
		{ return set_scale(s.x, s.y); }
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix& set_rotate(const Real &angle) {
Ivan Mahonin 145120
		Real s = sin(angle), c = cos(angle);
Ivan Mahonin 145120
		return *this = Matrix( c, s, 0,
Ivan Mahonin 145120
							  -s, c, 0,
Ivan Mahonin 145120
							   0, 0, 1 );
Ivan Mahonin 145120
	}
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix& set_translate(const Real &x, const Real &y) {
Ivan Mahonin 145120
		return *this = Matrix( 1, 0, 0,
Ivan Mahonin 145120
							   0, 1, 0,
Ivan Mahonin 145120
							   x, y, 1 );
Ivan Mahonin 145120
	}
Ivan Mahonin 145120
	Matrix& set_translate(const Vector &t)
Ivan Mahonin 145120
		{ return set_translate(t.x, t.y); }
Ivan Mahonin 145120
Ivan Mahonin 145120
	void transform(
Ivan Mahonin 145120
		Real &out_x, Real &out_y, Real &out_z,
Ivan Mahonin 145120
		const Real &x, const Real &y, const Real &z ) const
Ivan Mahonin 145120
	{
Ivan Mahonin 145120
		out_x = x*m00 + y*m10 + z*m20;
Ivan Mahonin 145120
		out_y = x*m01 + y*m11 + z*m21;
Ivan Mahonin 145120
		out_z = x*m02 + y*m12 + z*m22;
Ivan Mahonin 145120
	}
Ivan Mahonin 145120
	void transform(Real &out_x, Real &out_y, const Real &x, const Real &y, bool translate = true) const
Ivan Mahonin 145120
		{ Real z; transform(out_x, out_y, z, x, y, translate ? 1.0 : 0.0); }
Ivan Mahonin 145120
	Vector transform(const Vector &v, bool translate = true)const
Ivan Mahonin 145120
		{ Vector vv; transform(vv.x, vv.y, v.x, v.y, translate); return vv; }
Ivan Mahonin 145120
Ivan Mahonin 145120
	bool operator==(const Matrix &other) const {
Ivan Mahonin 145120
		return equal(m00, other.m00) && equal(m01, other.m01) && equal(m02, other.m02)
Ivan Mahonin 145120
			&& equal(m10, other.m10) && equal(m11, other.m11) && equal(m12, other.m12)
Ivan Mahonin 145120
			&& equal(m20, other.m20) && equal(m21, other.m21) && equal(m22, other.m22);
Ivan Mahonin 145120
	}
Ivan Mahonin 145120
	bool operator!=(const Matrix &other) const
Ivan Mahonin 145120
		{ return !(*this == other); }
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix& operator*=(const Matrix &other)
Ivan Mahonin 145120
		{ return *this = *this * other; }
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix operator*(const Matrix &other) const {
Ivan Mahonin 145120
		Matrix m;
Ivan Mahonin 145120
		transform(m.m00, m.m01, m.m02, other.m00, other.m01, other.m02);
Ivan Mahonin 145120
		transform(m.m10, m.m11, m.m12, other.m10, other.m11, other.m12);
Ivan Mahonin 145120
		transform(m.m20, m.m21, m.m22, other.m20, other.m21, other.m22);
Ivan Mahonin 145120
		return m;
Ivan Mahonin 145120
	}
Ivan Mahonin 145120
Ivan Mahonin 145120
	Real det() const {
Ivan Mahonin 145120
		return m00*(m11*m22 - m12*m21)
Ivan Mahonin 145120
			 - m01*(m10*m22 - m12*m20)
Ivan Mahonin 145120
			 + m02*(m10*m21 - m11*m20);
Ivan Mahonin 145120
	}
Ivan Mahonin 145120
	
Ivan Mahonin 145120
	bool is_invertible() const
Ivan Mahonin 145120
		{ return !equal(det(), 0); }
Ivan Mahonin 145120
	
Ivan Mahonin 145120
	Matrix get_inverted() const;
Ivan Mahonin 145120
Ivan Mahonin 145120
	Matrix& invert()
Ivan Mahonin 145120
		{ return *this = get_inverted(); }
Ivan Mahonin 145120
};
Ivan Mahonin 145120
Ivan Mahonin 145120
#endif