synfig-core  1.0.3
transformation.h
Go to the documentation of this file.
1 /* === S Y N F I G ========================================================= */
21 /* ========================================================================= */
22 
23 /* === S T A R T =========================================================== */
24 
25 #ifndef __SYNFIG_TRANSFORMATION_H
26 #define __SYNFIG_TRANSFORMATION_H
27 
28 /* === H E A D E R S ======================================================= */
29 
30 #include "vector.h"
31 #include "matrix.h"
32 #include "rect.h"
33 
34 /* === M A C R O S ========================================================= */
35 
36 /* === T Y P E D E F S ===================================================== */
37 
38 /* === C L A S S E S & S T R U C T S ======================================= */
39 
40 namespace synfig {
41 
46 {
47 public:
52 
54  offset(0.0, 0.0),
55  angle(Angle::rad(0.0)),
56  skew_angle(Angle::rad(0.0)),
57  scale(1.0, 1.0)
58  { }
59 
61  const Vector &offset,
62  const Angle &angle = Angle::rad(0.0),
63  const Angle &skew_angle = Angle::rad(0.0),
64  const Vector &scale = Vector(1.0, 1.0)
65  ):
66  offset(offset),
67  angle(angle),
69  scale(scale)
70  { }
71 
72  bool is_valid()const
73  {
74  return offset.is_valid()
75  && !isnan(Angle::rad(angle).get())
76  && !isnan(Angle::rad(skew_angle).get())
77  && scale.is_valid();
78  }
79 
80  bool
81  operator==(const Transformation &rhs)const
82  {
83  return offset==rhs.offset
84  && angle==rhs.angle
85  && skew_angle==rhs.skew_angle
86  && scale==rhs.scale;
87  }
88 
89  bool
90  operator!=(const Transformation &rhs)const
91  {
92  return offset!=rhs.offset
93  || angle!=rhs.angle
94  || skew_angle!=rhs.skew_angle
95  || scale!=rhs.scale;
96  }
97 
98  bool is_equal_to(const Transformation& rhs)const
99  {
100  static const Angle::rad epsilon_angle(0.0000000000001);
101  Angle::rad a = angle - rhs.angle;
102  Angle::rad sa = skew_angle - rhs.skew_angle;
103  return offset.is_equal_to(rhs.offset)
104  && a < epsilon_angle && a > -epsilon_angle
105  && sa < epsilon_angle && sa > -epsilon_angle
106  && scale.is_equal_to(rhs.scale);
107  }
108 
109  bool is_identity()const
110  {
111  return is_equal_to(Transformation());
112  }
113 
115  {
116  if (is_identity()) return Matrix();
117  Vector axis_x(scale[0], angle);
118  Vector axis_y(scale[1], angle + skew_angle + Angle::deg(90.0));
119  return Matrix(axis_x, axis_y, offset);
120  }
121 
122  void set_matrix(const Matrix &matrix)
123  {
124  if (matrix.is_identity()) *this = Transformation();
125  Vector axis_x(matrix.get_axis_x());
126  Vector axis_y(matrix.get_axis_y());
127  angle = axis_x.angle();
128  skew_angle = axis_y.angle() - angle - Angle::deg(90.0);
129  scale[0] = axis_x.mag();
130  scale[1] = axis_y.mag();
131  offset = matrix.get_offset();
132  }
133 
134  explicit Transformation(const Matrix &matrix)
135  { set_matrix(matrix); }
136 
138  { return get_matrix().invert(); }
139 
141  { return Transformation(get_inverted_matrix()); }
142 
143  static Rect transform_bounds(const Matrix &matrix, const Rect &bounds)
144  {
145  if (isnan(bounds.minx) || isinf(bounds.minx)
146  || isnan(bounds.maxx) || isinf(bounds.maxx)
147  || isnan(bounds.miny) || isinf(bounds.miny)
148  || isnan(bounds.maxy) || isinf(bounds.maxy))
149  return Rect::infinite();
150 
151  Rect transformed_bounds(
152  matrix.get_transformed(
153  Vector(bounds.minx, bounds.miny) ));
154  transformed_bounds.expand(
155  matrix.get_transformed(
156  Vector(bounds.minx, bounds.maxy) ));
157  transformed_bounds.expand(
158  matrix.get_transformed(
159  Vector(bounds.maxx, bounds.miny) ));
160  transformed_bounds.expand(
161  matrix.get_transformed(
162  Vector(bounds.maxx, bounds.maxy) ));
163  return transformed_bounds;
164  }
165 
166  Vector transform(const Vector &v, bool translate = true) const
167  { return get_matrix().get_transformed(v, translate); }
168  Transformation transform(const Transformation &transformation) const
169  { return Transformation( transformation.get_matrix()*get_matrix() ); }
170  Matrix transform(const Matrix &matrix) const
171  { return matrix*get_matrix(); }
172  Rect transform_bounds(const Rect &bounds) const
173  { return transform_bounds(get_matrix(), bounds); }
174 
175  Vector back_transform(const Vector &v, bool translate = true) const
176  { return get_inverted_matrix().get_transformed(v, translate); }
177  Transformation back_transform(const Transformation &transformation) const
178  { return Transformation( transformation.get_matrix()*get_inverted_matrix() ); }
179  Matrix back_transform(const Matrix &matrix) const
180  { return matrix*get_inverted_matrix(); }
181  Rect back_transform_bounds(const Rect &bounds) const
182  { return transform_bounds(get_inverted_matrix(), bounds); }
183 
184  static const Transformation identity() { return Transformation(); }
185 };
186 
187 }; // END of namespace synfig
188 
189 /* === E N D =============================================================== */
190 
191 #endif