1 /* === S Y N F I G ========================================================= */
2 /*!	\file matrix.h
3 **	\brief Matrix definitions for 2D affine transformations
4 **
5 **	$Id$
6 **
7 **	\legal
8 **	Copyright (c) 2008 Carlos López & Chirs Moore
9 **
10 **	This package is free software; you can redistribute it and/or
11 **	modify it under the terms of the GNU General Public License as
12 **	published by the Free Software Foundation; either version 2 of
13 **	the License, or (at your option) any later version.
14 **
15 **	This package is distributed in the hope that it will be useful,
16 **	but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **	General Public License for more details.
19 **	\endlegal
20 */
21 /* ========================================================================= */
22 
23 /* === S T A R T =========================================================== */
24 
25 #ifndef __SYNFIG_MATRIX_H
26 #define __SYNFIG_MATRIX_H
27 
28 /* === H E A D E R S ======================================================= */
29 
30 #include "angle.h"
31 #include "real.h"
32 #include "vector.h"
33 #include "string.h"
34 #include <cassert>
35 #include <cmath>
36 #include <iostream>
37 #include <ETL/stringf>
38 
39 /* === M A C R O S ========================================================= */
40 
41 #define COUT_MATRIX(m)													\
42 	cout<<"["<<m.m00<<"]["<<m.m01<<"]["<<m.m02<<"]"<<endl;				\
43 	cout<<"["<<m.m10<<"]["<<m.m11<<"]["<<m.m12<<"]"<<endl;				\
44 	cout<<"["<<m.m20<<"]["<<m.m21<<"]["<<m.m22<<"]"<<endl
45 
46 /* === T Y P E D E F S ===================================================== */
47 
48 /* === C L A S S E S & S T R U C T S ======================================= */
49 
50 namespace synfig {
51 
52 /*!	\class Matrix2
53 **	\todo writeme (Matrix 2x2)
54 */
55 class Matrix2
56 {
57 public:
58 	typedef Real value_type;
59 
60 public:
61 	//! The matrix array
62 	union {
63 		value_type m[2][2];
64 		struct
65 		{
66 			value_type m00, m01;
67 			value_type m10, m11;
68 		};
69 	};
70 
71 	//!Default constructor makes an identity matrix
Matrix2()72 	Matrix2(): m00(1.0), m01(0.0), m10(0.0), m11(1.0) { }
73 
Matrix2(value_type m00,value_type m01,value_type m10,value_type m11)74 	Matrix2(value_type m00, value_type m01, value_type m10, value_type m11):
75 		m00(m00), m01(m01), m10(m10), m11(m11) { }
76 
Matrix2(const Vector & axis_x,const Vector & axis_y)77 	Matrix2(const Vector &axis_x, const Vector &axis_y):
78 		m00(axis_x[0]), m01(axis_x[1]), m10(axis_y[0]), m11(axis_y[1]) { }
79 
get_axis_x()80 	Vector get_axis_x()const { return Vector(m00, m01); }
get_axis_y()81 	Vector get_axis_y()const { return Vector(m10, m11); }
82 
83 	//!set_identity member. Set an identity matrix
set_identity()84 	Matrix2 &set_identity()
85 		{ return *this = Matrix2(); }
86 
is_identity()87 	bool is_identity() const
88 		{ return *this == Matrix2(); }
89 
90 	//!set_scale member function. Sets a scale matrix
91 	//! @param sx Scale by X axis
92 	//! @param sy Scale by Y axis
93 	//! @return A matrix reference filled with the sx, sy values
94 	Matrix2 &set_scale(const value_type &sx, const value_type &sy);
95 
96 	//!set_scale member fucntion. Sets a scale matrix
97 	//! @param sxy Scale by X and Y axis
98 	//! @return A matrix reference filled with the sxy values
set_scale(const value_type & sxy)99 	Matrix2 &set_scale(const value_type &sxy)
100 		{ return set_scale(sxy, sxy); }
101 
102 	//!set_scale member fucntion. Sets a scale matrix
103 	//! @param s Vector that defines the scale
104 	//! @return A matrix reference filled with the proper scale parameters
set_scale(const Vector & s)105 	Matrix2 &set_scale(const Vector &s)
106 		{ return set_scale(s[0], s[1]); }
107 
108 	//!set_rotate member function. Sets a rotate matrix
109 	//! @param a Rotation angle counter clockwise
110 	//! @return A matrix reference filled with the proper rotation parameters
111 	Matrix2 &set_rotate(const Angle &a);
112 
113 	void get_transformed(value_type &out_x, value_type &out_y, const value_type x, const value_type y)const;
114 
115 	//!get_transformed member function.
116 	//! @param v 2D Vector to transform
117 	//! @return The Vector result
get_transformed(const Vector & v)118 	Vector get_transformed(const Vector &v)const
119 		{ Vector vv; get_transformed(vv[0], vv[1], v[0], v[1]); return vv; }
120 
121 	bool operator==(const Matrix2 &rhs) const;
122 	bool operator!=(const Matrix2 &rhs) const
123 		{ return !(*this == rhs); }
124 
125 	//! operator*=. Multiplication and assignment of one matrix by another
126 	//! @param rhs the right hand side of the multiplication operation
127 	//! @return the modified resulting matrix
128 	Matrix2 operator*=(const Matrix2 &rhs);
129 
130 	//! operator*=. Multiplication and assignment of one matrix by a scalar
131 	//! @param rhs the number to multiply by
132 	//! @return the modifed resulting matrix
133 	Matrix2 operator*=(const value_type &rhs);
134 
135 	//! operator+=. Sum and assignment of two matrixes
136 	//! @param rhs the matrix to sum
137 	//! @return modified matrix with the summed matrix
138 	Matrix2 operator+=(const Matrix2 &rhs);
139 
140 	//! operator*. Multiplication of one matrix by another
141 	//! @param rhs the right hand side of the multiplication operation
142 	//! @return the resulting matrix
143 	Matrix2 operator*(const Matrix2 &rhs)const
144 		{ return Matrix2(*this) *= rhs; }
145 
146 	//! operator*. Multiplication of one matrix by a number
147 	//! @param rhs the number to multiply by
148 	//! @return the resulting matrix
149 	Matrix2 operator*(const value_type &rhs)const
150 		{ return Matrix2(*this) *= rhs; }
151 
152 	//! operator+. Sum two matrixes
153 	//! @param rhs the matrix to sum
154 	//! @return the resulting matrix
155 	Matrix2 operator+(const Matrix2 &rhs)const
156 		{ return Matrix2(*this) += rhs; }
157 
158 	bool is_invertible()const;
159 
160 	Matrix2 &invert();
161 
162 	//!Get the string of the Matrix
163 	//!@return String type. A string representation of the matrix
164 	//!components.
165 	String get_string(int spaces = 0, String before = String(), String after = String())const;
166 };
167 
168 
169 /*!	\class Matrix3
170 **	\todo writeme (Matrix 3x3)
171 */
172 class Matrix3
173 {
174 public:
175 	typedef Real value_type;
176 
177 public:
178 	//! The matrix array
179 	union {
180 		value_type m[3][3];
181 		struct
182 		{
183 			value_type m00, m01, m02;
184 			value_type m10, m11, m12;
185 			value_type m20, m21, m22;
186 		};
187 	};
188 
189 	// Index convention
190 	// 00 01 02
191 	// 10 11 12
192 	// 20 21 22
193 	// vectors are premultiplied when the matrix transformation is applied
194 	// we consider the vectors as [1]x[3] arrays.
195 	// [1]x[3] * [3]x[3] = [1]x[3]
196 	// vector  * matrix  = vector
197 	// In affine transformation matrixes the values of
198 	// m02=0, m12=0 and m22=1 for non projective transformations.
199 
200 	//!Default constructor makes an identity matrix
Matrix3()201 	Matrix3():
202 		m00(1.0), m01(0.0), m02(0.0),
203 		m10(0.0), m11(1.0), m12(0.0),
204 		m20(0.0), m21(0.0), m22(1.0) { }
205 
Matrix3(value_type m00,value_type m01,value_type m02,value_type m10,value_type m11,value_type m12,value_type m20,value_type m21,value_type m22)206 	Matrix3(
207 		value_type m00, value_type m01, value_type m02,
208 		value_type m10, value_type m11, value_type m12,
209 		value_type m20, value_type m21, value_type m22
210 	):
211 		m00(m00), m01(m01), m02(m02),
212 		m10(m10), m11(m11), m12(m12),
213 		m20(m20), m21(m21), m22(m22)
214 	{ }
215 
Matrix3(Vector axis_x,Vector axis_y,Vector offset)216 	Matrix3(Vector axis_x, Vector axis_y, Vector offset):
217 		m00(axis_x[0]), m01(axis_x[1]), m02(0.0),
218 		m10(axis_y[0]), m11(axis_y[1]), m12(0.0),
219 		m20(offset[0]), m21(offset[1]), m22(1.0)
220 	{ }
221 
get_axis_x()222 	Vector get_axis_x()const { return Vector(m00, m01); }
get_axis_y()223 	Vector get_axis_y()const { return Vector(m10, m11); }
get_offset()224 	Vector get_offset()const { return Vector(m20, m21); }
225 
226 	//!set_identity member. Set an identity matrix
set_identity()227 	Matrix3 &set_identity()
228 		{ return *this = Matrix3(); }
229 
is_identity()230 	bool is_identity() const
231 		{ return *this == Matrix3(); }
232 
233 	//!set_scale member function. Sets a scale matrix
234 	//! @param sx Scale by X axis
235 	//! @param sy Scale by Y axis
236 	//! @return A matrix reference filled with the sx, sy values
237 	Matrix3 &set_scale(const value_type &sx, const value_type &sy);
238 
239 	//!set_scale member fucntion. Sets a scale matrix
240 	//! @param sxy Scale by X and Y axis
241 	//! @return A matrix reference filled with the sxy values
set_scale(const value_type & sxy)242 	Matrix3 &set_scale(const value_type &sxy)
243 		{ return set_scale(sxy, sxy); }
244 
245 	//!set_scale member fucntion. Sets a scale matrix
246 	//! @param s Vector that defines the scale
247 	//! @return A matrix reference filled with the proper scale parameters
set_scale(const Vector & s)248 	Matrix3 &set_scale(const Vector &s)
249 		{ return set_scale(s[0], s[1]); }
250 
251 	//!set_rotate member function. Sets a rotate matrix
252 	//! @param a Rotation angle counter clockwise
253 	//! @return A matrix reference filled with the proper rotation parameters
254 	Matrix3 &set_rotate(const Angle &a);
255 
256 	//!translate member function. Sets a translate matrix
257 	//! @param t Vector that defines the translation
258 	//! @return A matrix reference filled with the proper translation parameters
set_translate(const Vector & t)259 	Matrix3 &set_translate(const Vector &t)
260 		{ return set_translate(t[0], t[1]); }
261 
262 	//!translate member function. Sets a translate matrix
263 	//! @param x Scalar that defines the x component of the translation
264 	//! @param y Scalar that defines the y component of the translation
265 	//! @return A matrix reference filled with the proper translation parameters
266 	Matrix3 &set_translate(value_type x, value_type y);
267 
268 	void get_transformed(value_type &out_x, value_type &out_y, const value_type x, const value_type y, bool translate = true)const;
269 
270 	//!get_transformed member function.
271 	//! @param v 2D Vector to transform
272 	//! @return The Vector result
273 	Vector get_transformed(const Vector &v, bool translate = true)const
274 		{ Vector vv; get_transformed(vv[0], vv[1], v[0], v[1], translate); return vv; }
275 
276 	bool operator==(const Matrix3 &rhs) const;
277 	bool operator!=(const Matrix3 &rhs) const
278 		{ return !(*this == rhs); }
279 
280 	//! operator*=. Multiplication and assignment of one matrix by another
281 	//! @param rhs the right hand side of the multiplication operation
282 	//! @return the modified resulting matrix
283 	Matrix3 operator*=(const Matrix3 &rhs);
284 
285 	//! operator*=. Multiplication and assignment of one matrix by a scalar
286 	//! @param rhs the number to multiply by
287 	//! @return the modifed resulting matrix
288 	Matrix3 operator*=(const value_type &rhs);
289 
290 	//! operator+=. Sum and assignment of two matrixes
291 	//! @param rhs the matrix to sum
292 	//! @return modified matrix with the summed matrix
293 	Matrix3 operator+=(const Matrix3 &rhs);
294 
295 	//! operator*. Multiplication of one matrix by another
296 	//! @param rhs the right hand side of the multiplication operation
297 	//! @return the resulting matrix
298 	Matrix3 operator*(const Matrix3 &rhs)const
299 		{ return Matrix3(*this) *= rhs; }
300 
301 	//! operator*. Multiplication of one matrix by a number
302 	//! @param rhs the number to multiply by
303 	//! @return the resulting matrix
304 	Matrix3 operator*(const value_type &rhs)const
305 		{ return Matrix3(*this) *= rhs; }
306 
307 	//! operator+. Sum two matrixes
308 	//! @param rhs the matrix to sum
309 	//! @return the resulting matrix
310 	Matrix3 operator+(const Matrix3 &rhs)const
311 		{ return Matrix3(*this) += rhs; }
312 
313 	bool is_invertible()const;
314 
315 	//         (m00 m01 0)       1               (     m11     )   (    -m01     )   (      0      )
316 	// inverse (m10 m11 0)  =  -----          x  (    -m10     )   (     m00     )   (      0      )
317 	//         (m20 m21 1)     m00m11-m01m10     (m10m21-m11m20)   (m01m20-m00m21)   (m00m11-m01m10)
318 	Matrix3 &invert();
319 
320 	//!Get the string of the Matrix
321 	//!@return String type. A string representation of the matrix
322 	//!components.
323 	String get_string(int spaces = 0, String before = String(), String after = String())const;
324 };
325 
326 typedef Matrix3 Matrix;
327 
328 }; // END of namespace synfig
329 
330 #endif
331