btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_trans_affine.h
blobea5d9cf9992775b0e34fe6b14070697528b0199d
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 // Affine transformation classes.
18 //----------------------------------------------------------------------------
19 #ifndef AGG_TRANS_AFFINE_INCLUDED
20 #define AGG_TRANS_AFFINE_INCLUDED
22 #include <math.h>
23 #include "agg_basics.h"
25 namespace agg
27 const double affine_epsilon = 1e-14; // About of precision of doubles
29 //============================================================trans_affine
31 // See Implementation agg_trans_affine.cpp
33 // Affine transformation are linear transformations in Cartesian coordinates
34 // (strictly speaking not only in Cartesian, but for the beginning we will
35 // think so). They are rotation, scaling, translation and skewing.
36 // After any affine transformation a line segment remains a line segment
37 // and it will never become a curve.
39 // There will be no math about matrix calculations, since it has been
40 // described many times. Ask yourself a very simple question:
41 // "why do we need to understand and use some matrix stuff instead of just
42 // rotating, scaling and so on". The answers are:
44 // 1. Any combination of transformations can be done by only 4 multiplications
45 // and 4 additions in floating point.
46 // 2. One matrix transformation is equivalent to the number of consecutive
47 // discrete transformations, i.e. the matrix "accumulates" all transformations
48 // in the order of their settings. Suppose we have 4 transformations:
49 // * rotate by 30 degrees,
50 // * scale X to 2.0,
51 // * scale Y to 1.5,
52 // * move to (100, 100).
53 // The result will depend on the order of these transformations,
54 // and the advantage of matrix is that the sequence of discret calls:
55 // rotate(30), scaleX(2.0), scaleY(1.5), move(100,100)
56 // will have exactly the same result as the following matrix transformations:
57 //
58 // affine_matrix m;
59 // m *= rotate_matrix(30);
60 // m *= scaleX_matrix(2.0);
61 // m *= scaleY_matrix(1.5);
62 // m *= move_matrix(100,100);
64 // m.transform_my_point_at_last(x, y);
66 // What is the good of it? In real life we will set-up the matrix only once
67 // and then transform many points, let alone the convenience to set any
68 // combination of transformations.
70 // So, how to use it? Very easy - literally as it's shown above. Not quite,
71 // let us write a correct example:
73 // agg::trans_affine m;
74 // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);
75 // m *= agg::trans_affine_scaling(2.0, 1.5);
76 // m *= agg::trans_affine_translation(100.0, 100.0);
77 // m.transform(&x, &y);
79 // The affine matrix is all you need to perform any linear transformation,
80 // but all transformations have origin point (0,0). It means that we need to
81 // use 2 translations if we want to rotate someting around (100,100):
82 //
83 // m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0)
84 // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate
85 // m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)
86 //----------------------------------------------------------------------
87 class trans_affine
89 public:
90 //------------------------------------------ Construction
91 // Construct an identity matrix - it does not transform anything
92 trans_affine() :
93 m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(0.0)
96 // Construct a custom matrix. Usually used in derived classes
97 trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) :
98 m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5)
101 // Construct a matrix to transform a parallelogram to another one.
102 trans_affine(const double* rect, const double* parl)
104 parl_to_parl(rect, parl);
107 // Construct a matrix to transform a rectangle to a parallelogram.
108 trans_affine(double x1, double y1, double x2, double y2,
109 const double* parl)
111 rect_to_parl(x1, y1, x2, y2, parl);
114 // Construct a matrix to transform a parallelogram to a rectangle.
115 trans_affine(const double* parl,
116 double x1, double y1, double x2, double y2)
118 parl_to_rect(parl, x1, y1, x2, y2);
122 //---------------------------------- Parellelogram transformations
123 // Calculate a matrix to transform a parallelogram to another one.
124 // src and dst are pointers to arrays of three points
125 // (double[6], x,y,...) that identify three corners of the
126 // parallelograms assuming implicit fourth points.
127 // There are also transformations rectangtle to parallelogram and
128 // parellelogram to rectangle
129 const trans_affine& parl_to_parl(const double* src,
130 const double* dst);
132 const trans_affine& rect_to_parl(double x1, double y1,
133 double x2, double y2,
134 const double* parl);
136 const trans_affine& parl_to_rect(const double* parl,
137 double x1, double y1,
138 double x2, double y2);
141 //------------------------------------------ Operations
142 // Reset - actually load an identity matrix
143 const trans_affine& reset();
145 // Multiply matrix to another one
146 const trans_affine& multiply(const trans_affine& m);
148 // Multiply "m" to "this" and assign the result to "this"
149 const trans_affine& premultiply(const trans_affine& m);
151 // Multiply matrix to inverse of another one
152 const trans_affine& multiply_inv(const trans_affine& m);
154 // Multiply inverse of "m" to "this" and assign the result to "this"
155 const trans_affine& premultiply_inv(const trans_affine& m);
157 // Invert matrix. Do not try to invert degenerate matrices,
158 // there's no check for validity. If you set scale to 0 and
159 // then try to invert matrix, expect unpredictable result.
160 const trans_affine& invert();
162 // Mirroring around X
163 const trans_affine& flip_x();
165 // Mirroring around Y
166 const trans_affine& flip_y();
168 //------------------------------------------- Load/Store
169 // Store matrix to an array [6] of double
170 void store_to(double* m) const
172 *m++ = m0; *m++ = m1; *m++ = m2; *m++ = m3; *m++ = m4; *m++ = m5;
175 // Load matrix from an array [6] of double
176 const trans_affine& load_from(const double* m)
178 m0 = *m++; m1 = *m++; m2 = *m++; m3 = *m++; m4 = *m++; m5 = *m++;
179 return *this;
182 //------------------------------------------- Operators
184 // Multiply current matrix to another one
185 const trans_affine& operator *= (const trans_affine& m)
187 return multiply(m);
190 // Multiply current matrix to inverse of another one
191 const trans_affine& operator /= (const trans_affine& m)
193 return multiply_inv(m);
196 // Multiply current matrix to another one and return
197 // the result in a separete matrix.
198 trans_affine operator * (const trans_affine& m) const
200 return trans_affine(*this).multiply(m);
203 // Multiply current matrix to inverse of another one
204 // and return the result in a separete matrix.
205 trans_affine operator / (const trans_affine& m) const
207 return trans_affine(*this).multiply_inv(m);
210 // Calculate and return the inverse matrix
211 trans_affine operator ~ () const
213 trans_affine ret = *this;
214 return ret.invert();
217 // Equal operator with default epsilon
218 bool operator == (const trans_affine& m) const
220 return is_equal(m, affine_epsilon);
223 // Not Equal operator with default epsilon
224 bool operator != (const trans_affine& m) const
226 return !is_equal(m, affine_epsilon);
229 //-------------------------------------------- Transformations
230 // Direct transformation x and y
231 void transform(double* x, double* y) const;
233 // Direct transformation x and y, 2x2 matrix only, no translation
234 void transform_2x2(double* x, double* y) const;
236 // Inverse transformation x and y. It works slower than the
237 // direct transformation, so if the performance is critical
238 // it's better to invert() the matrix and then use transform()
239 void inverse_transform(double* x, double* y) const;
241 //-------------------------------------------- Auxiliary
242 // Calculate the determinant of matrix
243 double determinant() const
245 return 1.0 / (m0 * m3 - m1 * m2);
248 // Get the average scale (by X and Y).
249 // Basically used to calculate the approximation_scale when
250 // decomposinting curves into line segments.
251 double scale() const;
253 // Check to see if it's an identity matrix
254 bool is_identity(double epsilon = affine_epsilon) const;
256 // Check to see if two matrices are equal
257 bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
259 // Determine the major parameters. Use carefully considering degenerate matrices
260 double rotation() const;
261 void translation(double* dx, double* dy) const;
262 void scaling(double* sx, double* sy) const;
263 void scaling_abs(double* sx, double* sy) const
265 *sx = sqrt(m0*m0 + m2*m2);
266 *sy = sqrt(m1*m1 + m3*m3);
269 private:
270 double m0;
271 double m1;
272 double m2;
273 double m3;
274 double m4;
275 double m5;
278 //------------------------------------------------------------------------
279 inline void trans_affine::transform(double* x, double* y) const
281 register double tx = *x;
282 *x = tx * m0 + *y * m2 + m4;
283 *y = tx * m1 + *y * m3 + m5;
286 //------------------------------------------------------------------------
287 inline void trans_affine::transform_2x2(double* x, double* y) const
289 register double tx = *x;
290 *x = tx * m0 + *y * m2;
291 *y = tx * m1 + *y * m3;
294 //------------------------------------------------------------------------
295 inline void trans_affine::inverse_transform(double* x, double* y) const
297 register double d = determinant();
298 register double a = (*x - m4) * d;
299 register double b = (*y - m5) * d;
300 *x = a * m3 - b * m2;
301 *y = b * m0 - a * m1;
304 //------------------------------------------------------------------------
305 inline double trans_affine::scale() const
307 double x = 0.707106781 * m0 + 0.707106781 * m2;
308 double y = 0.707106781 * m1 + 0.707106781 * m3;
309 return sqrt(x*x + y*y);
312 //------------------------------------------------------------------------
313 inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
315 trans_affine t = m;
316 return *this = t.multiply(*this);
319 //------------------------------------------------------------------------
320 inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m)
322 trans_affine t = m;
323 t.invert();
324 multiply(t);
325 return *this;
328 //------------------------------------------------------------------------
329 inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m)
331 trans_affine t = m;
332 t.invert();
333 return *this = t.multiply(*this);
336 //====================================================trans_affine_rotation
337 // Rotation matrix. sin() and cos() are calculated twice for the same angle.
338 // There's no harm because the performance of sin()/cos() is very good on all
339 // modern processors. Besides, this operation is not going to be invoked too
340 // often.
341 class trans_affine_rotation : public trans_affine
343 public:
344 trans_affine_rotation(double a) :
345 trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0)
349 //====================================================trans_affine_scaling
350 // Scaling matrix. sx, sy - scale coefficients by X and Y respectively
351 class trans_affine_scaling : public trans_affine
353 public:
354 trans_affine_scaling(double sx, double sy) :
355 trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0)
358 trans_affine_scaling(double s) :
359 trans_affine(s, 0.0, 0.0, s, 0.0, 0.0)
363 //================================================trans_affine_translation
364 // Translation matrix
365 class trans_affine_translation : public trans_affine
367 public:
368 trans_affine_translation(double tx, double ty) :
369 trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty)
373 //====================================================trans_affine_skewing
374 // Sckewing (shear) matrix
375 class trans_affine_skewing : public trans_affine
377 public:
378 trans_affine_skewing(double sx, double sy) :
379 trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0)
384 //===============================================trans_affine_line_segment
385 // Rotate, Scale and Translate, associating 0...dist with line segment
386 // x1,y1,x2,y2
387 class trans_affine_line_segment : public trans_affine
389 public:
390 trans_affine_line_segment(double x1, double y1, double x2, double y2,
391 double dist)
393 double dx = x2 - x1;
394 double dy = y2 - y1;
395 if(dist > 0.0)
397 multiply(trans_affine_scaling(sqrt(dx * dx + dy * dy) / dist));
399 multiply(trans_affine_rotation(atan2(dy, dx)));
400 multiply(trans_affine_translation(x1, y1));
408 #endif