Blame synfig-core/src/synfig/matrix.h

Carlos Lopez a09598
/* === S Y N F I G ========================================================= */
Carlos Lopez a09598
/*!	\file matrix.h
Carlos Lopez a09598
**	\brief Matrix definitions for 2D affine transformations
Carlos Lopez a09598
**
Carlos Lopez a09598
**	$Id$
Carlos Lopez a09598
**
Carlos Lopez a09598
**	\legal
Nikita Kitaev dc5e35
**	Copyright (c) 2008 Carlos Lรณpez & Chirs Moore
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is free software; you can redistribute it and/or
Carlos Lopez a09598
**	modify it under the terms of the GNU General Public License as
Carlos Lopez a09598
**	published by the Free Software Foundation; either version 2 of
Carlos Lopez a09598
**	the License, or (at your option) any later version.
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is distributed in the hope that it will be useful,
Carlos Lopez a09598
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Carlos Lopez a09598
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Carlos Lopez a09598
**	General Public License for more details.
Carlos Lopez a09598
**	\endlegal
Carlos Lopez a09598
*/
Carlos Lopez a09598
/* ========================================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === S T A R T =========================================================== */
Carlos Lopez a09598
Carlos Lopez a09598
#ifndef __SYNFIG_MATRIX_H
Carlos Lopez a09598
#define __SYNFIG_MATRIX_H
Carlos Lopez a09598
Carlos Lopez a09598
/* === H E A D E R S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
#include "angle.h"
Carlos Lopez a09598
#include "real.h"
Carlos Lopez a09598
#include "vector.h"
Nikita Kitaev dc5e35
#include "string.h"
Nikita Kitaev dc5e35
#include <cassert></cassert>
caryoscelus 77c779
#include <cmath></cmath>
Nikita Kitaev dc5e35
#include <iostream></iostream>
Nikita Kitaev dc5e35
#include <etl stringf=""></etl>
Carlos Lopez a09598
Carlos Lopez a09598
/* === M A C R O S ========================================================= */
Carlos Lopez a09598
Nikita Kitaev dc5e35
#define COUT_MATRIX(m)													\
Nikita Kitaev dc5e35
	cout<<"["<
Nikita Kitaev dc5e35
	cout<<"["<
Nikita Kitaev dc5e35
	cout<<"["<
Carlos Lopez a09598
Carlos Lopez a09598
/* === T Y P E D E F S ===================================================== */
Carlos Lopez a09598
Carlos Lopez a09598
/* === C L A S S E S & S T R U C T S ======================================= */
Carlos Lopez a09598
Carlos Lopez a09598
namespace synfig {
Carlos Lopez a09598
ab6e41
/*!	\class Matrix2
ab6e41
**	\todo writeme (Matrix 2x2)
Carlos Lopez a09598
*/
ab6e41
class Matrix2
Carlos Lopez a09598
{
Carlos Lopez a09598
public:
Carlos Lopez a09598
	typedef Real value_type;
Carlos Lopez a09598
802529
public:
Carlos Lopez a09598
	//! The matrix array
ab6e41
	union {
ab6e41
		value_type m[2][2];
ab6e41
		struct
ab6e41
		{
ab6e41
			value_type m00, m01;
ab6e41
			value_type m10, m11;
ab6e41
		};
ab6e41
	};
ab6e41
ab6e41
	//!Default constructor makes an identity matrix
ab6e41
	Matrix2(): m00(1.0), m01(0.0), m10(0.0), m11(1.0) { }
ab6e41
ab6e41
	Matrix2(value_type m00, value_type m01, value_type m10, value_type m11):
ab6e41
		m00(m00), m01(m01), m10(m10), m11(m11) { }
ab6e41
3a4aaf
	Matrix2(const Vector &row_x, const Vector &row_y):
3a4aaf
		m00(row_x[0]), m01(row_x[1]), m10(row_y[0]), m11(row_y[1]) { }
3a4aaf
3a4aaf
	const Vector& row(int index) const { return *(const Vector*)(m[index]); }
3a4aaf
	const Vector& row_x() const { return row(0); }
3a4aaf
	const Vector& row_y() const { return row(1); }
3a4aaf
	const Vector& axis(int index) const { return row(index); }
3a4aaf
	const Vector& axis_x() const { return row_x(); }
3a4aaf
	const Vector& axis_y() const { return row_y(); }
3a4aaf
3a4aaf
	Vector& row(int index) { return *(Vector*)(m[index]); }
3a4aaf
	Vector& row_x() { return row(0); }
3a4aaf
	Vector& row_y() { return row(1); }
3a4aaf
	Vector& axis(int index) { return row(index); }
3a4aaf
	Vector& axis_x() { return row_x(); }
3a4aaf
	Vector& axis_y() { return row_y(); }
ab6e41
ab6e41
	//!set_identity member. Set an identity matrix
3a4aaf
	Matrix2& set_identity()
ab6e41
		{ return *this = Matrix2(); }
ab6e41
ab6e41
	bool is_identity() const
ab6e41
		{ return *this == Matrix2(); }
ab6e41
34a685
	Matrix2& set_zero()
34a685
		{ return *this = Matrix2(Vector(), Vector()); }
34a685
ab6e41
	//!set_scale member function. Sets a scale matrix
ab6e41
	//! @param sx Scale by X axis
ab6e41
	//! @param sy Scale by Y axis
ab6e41
	//! @return A matrix reference filled with the sx, sy values
3a4aaf
	Matrix2& set_scale(const value_type &sx, const value_type &sy);
ab6e41
luz.paz 99f3ef
	//!set_scale member function. Sets a scale matrix
ab6e41
	//! @param sxy Scale by X and Y axis
ab6e41
	//! @return A matrix reference filled with the sxy values
3a4aaf
	Matrix2& set_scale(const value_type &sxy)
ab6e41
		{ return set_scale(sxy, sxy); }
ab6e41
luz.paz 99f3ef
	//!set_scale member function. Sets a scale matrix
ab6e41
	//! @param s Vector that defines the scale
ab6e41
	//! @return A matrix reference filled with the proper scale parameters
3a4aaf
	Matrix2& set_scale(const Vector &s)
ab6e41
		{ return set_scale(s[0], s[1]); }
ab6e41
ab6e41
	//!set_rotate member function. Sets a rotate matrix
ab6e41
	//! @param a Rotation angle counter clockwise
ab6e41
	//! @return A matrix reference filled with the proper rotation parameters
3a4aaf
	Matrix2& set_rotate(const Angle &a);
ab6e41
ab6e41
	void get_transformed(value_type &out_x, value_type &out_y, const value_type x, const value_type y)const;
ab6e41
ab6e41
	//!get_transformed member function.
ab6e41
	//! @param v 2D Vector to transform
ab6e41
	//! @return The Vector result
ab6e41
	Vector get_transformed(const Vector &v)const
ab6e41
		{ Vector vv; get_transformed(vv[0], vv[1], v[0], v[1]); return vv; }
ab6e41
ab6e41
	bool operator==(const Matrix2 &rhs) const;
34d03e
	bool operator!=(const Matrix2 &rhs) const
34d03e
		{ return !(*this == rhs); }
ab6e41
3a4aaf
	Vector operator*(const Vector &v)
3a4aaf
		{ return get_transformed(v); }
3a4aaf
ab6e41
	//! operator*=. Multiplication and assignment of one matrix by another
ab6e41
	//! @param rhs the right hand side of the multiplication operation
ab6e41
	//! @return the modified resulting matrix
3a4aaf
	Matrix2& operator*=(const Matrix2 &rhs)
3a4aaf
		{ return *this = *this * rhs; }
ab6e41
ab6e41
	//! operator*=. Multiplication and assignment of one matrix by a scalar
ab6e41
	//! @param rhs the number to multiply by
luz.paz 99f3ef
	//! @return the modified resulting matrix
3a4aaf
	Matrix2& operator*=(const value_type &rhs);
ab6e41
ab6e41
	//! operator+=. Sum and assignment of two matrixes
ab6e41
	//! @param rhs the matrix to sum
ab6e41
	//! @return modified matrix with the summed matrix
3a4aaf
	Matrix2& operator+=(const Matrix2 &rhs);
ab6e41
ab6e41
	//! operator*. Multiplication of one matrix by another
ab6e41
	//! @param rhs the right hand side of the multiplication operation
ab6e41
	//! @return the resulting matrix
3a4aaf
	Matrix2 operator*(const Matrix2 &rhs)const;
3a4aaf
3a4aaf
	Vector operator*(const Vector &v)const
3a4aaf
		{ return get_transformed(v); }
ab6e41
ab6e41
	//! operator*. Multiplication of one matrix by a number
ab6e41
	//! @param rhs the number to multiply by
ab6e41
	//! @return the resulting matrix
3a4aaf
	Matrix2 operator*(const value_type &rhs)const;
ab6e41
ab6e41
	//! operator+. Sum two matrixes
ab6e41
	//! @param rhs the matrix to sum
ab6e41
	//! @return the resulting matrix
ab6e41
	Matrix2 operator+(const Matrix2 &rhs)const
ab6e41
		{ return Matrix2(*this) += rhs; }
ab6e41
34a685
	value_type det() const;
34a685
ab6e41
	bool is_invertible()const;
ab6e41
3a4aaf
	Matrix2& invert();
ab6e41
ab6e41
	//!Get the string of the Matrix
ab6e41
	//!@return String type. A string representation of the matrix
ab6e41
	//!components.
ab6e41
	String get_string(int spaces = 0, String before = String(), String after = String())const;
ab6e41
};
ab6e41
ab6e41
ab6e41
/*!	\class Matrix3
ab6e41
**	\todo writeme (Matrix 3x3)
ab6e41
*/
ab6e41
class Matrix3
ab6e41
{
ab6e41
public:
ab6e41
	typedef Real value_type;
ab6e41
ab6e41
public:
ab6e41
	//! The matrix array
ab6e41
	union {
ab6e41
		value_type m[3][3];
ab6e41
		struct
ab6e41
		{
ab6e41
			value_type m00, m01, m02;
ab6e41
			value_type m10, m11, m12;
ab6e41
			value_type m20, m21, m22;
ab6e41
		};
ab6e41
	};
ab6e41
Carlos Lopez a09598
	// Index convention
Carlos Lopez a09598
	// 00 01 02
Carlos Lopez a09598
	// 10 11 12
Carlos Lopez a09598
	// 20 21 22
Carlos Lopez a09598
	// vectors are premultiplied when the matrix transformation is applied
Carlos Lopez a09598
	// we consider the vectors as [1]x[3] arrays.
Carlos Lopez a09598
	// [1]x[3] * [3]x[3] = [1]x[3]
Carlos Lopez a09598
	// vector  * matrix  = vector
Carlos Lopez a09598
	// In affine transformation matrixes the values of
Carlos Lopez a09598
	// m02=0, m12=0 and m22=1 for non projective transformations.
Carlos Lopez a09598
Nikita Kitaev dc5e35
	//!Default constructor makes an identity matrix
ab6e41
	Matrix3():
ab6e41
		m00(1.0), m01(0.0), m02(0.0),
ab6e41
		m10(0.0), m11(1.0), m12(0.0),
ab6e41
		m20(0.0), m21(0.0), m22(1.0) { }
Nikita Kitaev dc5e35
ab6e41
	Matrix3(
802529
		value_type m00, value_type m01, value_type m02,
802529
		value_type m10, value_type m11, value_type m12,
802529
		value_type m20, value_type m21, value_type m22
802529
	):
802529
		m00(m00), m01(m01), m02(m02),
802529
		m10(m10), m11(m11), m12(m12),
802529
		m20(m20), m21(m21), m22(m22)
802529
	{ }
802529
3a4aaf
	Matrix3(
3a4aaf
		const Vector &axis_x,
3a4aaf
		const Vector &axis_y,
3a4aaf
		const Vector &offset
3a4aaf
	):
ab6e41
		m00(axis_x[0]), m01(axis_x[1]), m02(0.0),
ab6e41
		m10(axis_y[0]), m11(axis_y[1]), m12(0.0),
ab6e41
		m20(offset[0]), m21(offset[1]), m22(1.0)
f08c7d
	{ }
f08c7d
3a4aaf
	Matrix3(
3a4aaf
		const Vector3 &row_x,
3a4aaf
		const Vector3 &row_y,
3a4aaf
		const Vector3 &row_z
3a4aaf
	):
3a4aaf
		m00(row_x[0]), m01(row_x[1]), m02(row_x[2]),
3a4aaf
		m10(row_y[0]), m11(row_y[1]), m12(row_y[2]),
3a4aaf
		m20(row_z[0]), m21(row_z[1]), m22(row_z[2])
3a4aaf
	{ }
3a4aaf
3a4aaf
	const Vector3& row(int index) const { return *(const Vector3*)(m[index]); }
3a4aaf
	const Vector3& row_x() const { return row(0); }
3a4aaf
	const Vector3& row_y() const { return row(1); }
3a4aaf
	const Vector3& row_z() const { return row(2); }
3a4aaf
	const Vector& axis(int index) const { return *(const Vector*)(m[index]); }
3a4aaf
	const Vector& axis_x() const { return axis(0); }
3a4aaf
	const Vector& axis_y() const { return axis(1); }
3a4aaf
	const Vector& offset() const { return axis(2); }
3a4aaf
3a4aaf
	Vector3& row(int index) { return *(Vector3*)(m[index]); }
3a4aaf
	Vector3& row_x() { return row(0); }
3a4aaf
	Vector3& row_y() { return row(1); }
3a4aaf
	Vector3& row_z() { return row(2); }
3a4aaf
	Vector& axis(int index) { return *(Vector*)(m[index]); }
3a4aaf
	Vector& axis_x() { return axis(0); }
3a4aaf
	Vector& axis_y() { return axis(1); }
3a4aaf
	Vector& offset() { return axis(2); }
f08c7d
Carlos Lopez a09598
	//!set_identity member. Set an identity matrix
3a4aaf
	Matrix3& set_identity()
ab6e41
		{ return *this = Matrix3(); }
Nikita Kitaev dc5e35
ab6e41
	bool is_identity() const
ab6e41
		{ return *this == Matrix3(); }
813bad
34a685
	Matrix3& set_zero()
34a685
		{ return *this = Matrix3(Vector3(), Vector3(), Vector3()); }
34a685
		
Nikita Kitaev dc5e35
	//!set_scale member function. Sets a scale matrix
Carlos Lopez a09598
	//! @param sx Scale by X axis
Carlos Lopez a09598
	//! @param sy Scale by Y axis
Carlos Lopez a09598
	//! @return A matrix reference filled with the sx, sy values
3a4aaf
	Matrix3& set_scale(const value_type &sx, const value_type &sy);
Nikita Kitaev dc5e35
luz.paz 99f3ef
	//!set_scale member function. Sets a scale matrix
Nikita Kitaev dc5e35
	//! @param sxy Scale by X and Y axis
Nikita Kitaev dc5e35
	//! @return A matrix reference filled with the sxy values
3a4aaf
	Matrix3& set_scale(const value_type &sxy)
ab6e41
		{ return set_scale(sxy, sxy); }
Nikita Kitaev dc5e35
luz.paz 99f3ef
	//!set_scale member function. Sets a scale matrix
Nikita Kitaev dc5e35
	//! @param s Vector that defines the scale
Nikita Kitaev dc5e35
	//! @return A matrix reference filled with the proper scale parameters
3a4aaf
	Matrix3& set_scale(const Vector &s)
ab6e41
		{ return set_scale(s[0], s[1]); }
Nikita Kitaev dc5e35
Carlos Lopez a09598
	//!set_rotate member function. Sets a rotate matrix
Nikita Kitaev dc5e35
	//! @param a Rotation angle counter clockwise
Carlos Lopez a09598
	//! @return A matrix reference filled with the proper rotation parameters
3a4aaf
	Matrix3& set_rotate(const Angle &a);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	//!translate member function. Sets a translate matrix
Carlos Lopez a09598
	//! @param t Vector that defines the translation
Carlos Lopez a09598
	//! @return A matrix reference filled with the proper translation parameters
3a4aaf
	Matrix3& set_translate(const Vector &t)
ab6e41
		{ return set_translate(t[0], t[1]); }
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	//!translate member function. Sets a translate matrix
Nikita Kitaev dc5e35
	//! @param x Scalar that defines the x component of the translation
Nikita Kitaev dc5e35
	//! @param y Scalar that defines the y component of the translation
Nikita Kitaev dc5e35
	//! @return A matrix reference filled with the proper translation parameters
3a4aaf
	Matrix3& set_translate(value_type x, value_type y);
3a4aaf
3a4aaf
	void get_transformed(
3a4aaf
		value_type &out_x, value_type &out_y, value_type &out_z,
3a4aaf
		const value_type x, const value_type y, const value_type z )const;
ab6e41
3a4aaf
	void get_transformed(value_type &out_x, value_type &out_y, const value_type x, const value_type y, bool translate = true)const
3a4aaf
		{ value_type z; get_transformed(out_x, out_y, z, x, y, translate ? 1.0 : 0.0); }
3a4aaf
3a4aaf
	Vector3 get_transformed(const Vector3 &v)const
3a4aaf
		{ Vector3 vv; get_transformed(vv[0], vv[1], vv[2], v[0], v[1], v[2]); return vv; }
Carlos Lopez a09598
Carlos Lopez a09598
	//!get_transformed member function.
Carlos Lopez a09598
	//! @param v 2D Vector to transform
Carlos Lopez a09598
	//! @return The Vector result
ab6e41
	Vector get_transformed(const Vector &v, bool translate = true)const
ab6e41
		{ Vector vv; get_transformed(vv[0], vv[1], v[0], v[1], translate); return vv; }
ab6e41
ab6e41
	bool operator==(const Matrix3 &rhs) const;
34d03e
	bool operator!=(const Matrix3 &rhs) const
34d03e
		{ return !(*this == rhs); }
Carlos Lopez a09598
Nikita Kitaev dc5e35
	//! operator*=. Multiplication and assignment of one matrix by another
Carlos Lopez a09598
	//! @param rhs the right hand side of the multiplication operation
Nikita Kitaev dc5e35
	//! @return the modified resulting matrix
3a4aaf
	Matrix3& operator*=(const Matrix3 &rhs)
3a4aaf
		{ return *this = *this * rhs; }
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	//! operator*=. Multiplication and assignment of one matrix by a scalar
Carlos Lopez a09598
	//! @param rhs the number to multiply by
luz.paz 99f3ef
	//! @return the modified resulting matrix
3a4aaf
	Matrix3& operator*=(const value_type &rhs);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	//! operator+=. Sum and assignment of two matrixes
Carlos Lopez a09598
	//! @param rhs the matrix to sum
Carlos Lopez a09598
	//! @return modified matrix with the summed matrix
3a4aaf
	Matrix3& operator+=(const Matrix3 &rhs);
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	//! operator*. Multiplication of one matrix by another
Nikita Kitaev dc5e35
	//! @param rhs the right hand side of the multiplication operation
Nikita Kitaev dc5e35
	//! @return the resulting matrix
3a4aaf
	Matrix3 operator*(const Matrix3 &rhs)const;
3a4aaf
3a4aaf
	Vector3 operator*(const Vector3 &v)const
3a4aaf
		{ return get_transformed(v); }
Nikita Kitaev dc5e35
Nikita Kitaev dc5e35
	//! operator*. Multiplication of one matrix by a number
Carlos Lopez a09598
	//! @param rhs the number to multiply by
Nikita Kitaev dc5e35
	//! @return the resulting matrix
ab6e41
	Matrix3 operator*(const value_type &rhs)const
ab6e41
		{ return Matrix3(*this) *= rhs; }
Carlos Lopez a09598
Nikita Kitaev dc5e35
	//! operator+. Sum two matrixes
Carlos Lopez a09598
	//! @param rhs the matrix to sum
Nikita Kitaev dc5e35
	//! @return the resulting matrix
ab6e41
	Matrix3 operator+(const Matrix3 &rhs)const
ab6e41
		{ return Matrix3(*this) += rhs; }
Nikita Kitaev dc5e35
23f768
	value_type det() const;
23f768
Nikita Kitaev dc5e35
	bool is_invertible()const;
Nikita Kitaev dc5e35
23f768
	Matrix3 get_inverted() const;
23f768
23f768
	Matrix3& invert()
23f768
		{ return *this = get_inverted(); }
34a685
	
fc7a04
	Matrix3 get_normalized_by_det() const
fc7a04
		{ return Matrix3(*this).normalize_by_det(); }
34a685
	
fc7a04
	Matrix3& normalize_by_det();
34a685
	
Nikita Kitaev dc5e35
	//!Get the string of the Matrix
Nikita Kitaev dc5e35
	//!@return String type. A string representation of the matrix
Nikita Kitaev dc5e35
	//!components.
Nikita Kitaev dc5e35
	String get_string(int spaces = 0, String before = String(), String after = String())const;
Carlos Lopez a09598
};
Carlos Lopez a09598
ab6e41
typedef Matrix3 Matrix;
ab6e41
Carlos Lopez a09598
}; // END of namespace synfig
Carlos Lopez a09598
Carlos Lopez a09598
#endif