xref: /haiku/headers/os/interface/AffineTransform.h (revision 37c7d5d83a2372a6971e383411d5bacbeef0ebdc)
1 /*
2  * Copyright 2008-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephen Deken, stephen.deken@gmail.com
7  *		Stephan Aßmus <superstippi@gmx.de>
8  */
9 //----------------------------------------------------------------------------
10 // Anti-Grain Geometry - Version 2.4
11 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
12 //
13 // Permission to copy, use, modify, sell and distribute this software
14 // is granted provided this copyright notice appears in all copies.
15 // This software is provided "as is" without express or implied
16 // warranty, and with no claim as to its suitability for any purpose.
17 //
18 //----------------------------------------------------------------------------
19 // Contact: mcseem@antigrain.com
20 //          mcseemagg@yahoo.com
21 //          http://www.antigrain.com
22 //----------------------------------------------------------------------------
23 #ifndef _AFFINE_TRANSFORM_H
24 #define _AFFINE_TRANSFORM_H
25 
26 
27 #include <Flattenable.h>
28 #include <Point.h>
29 
30 #include <math.h>
31 
32 
33 class BAffineTransform : public BFlattenable {
34 public:
35 
36 	static	const double			kDefaultEpsilon = 1e-14;
37 
38 public:
39 									BAffineTransform();
40 									BAffineTransform(double sx, double shy,
41 										double shx, double sy, double tx,
42 										double ty);
43 									BAffineTransform(
44 										const BAffineTransform& copyFrom);
45 	virtual							~BAffineTransform();
46 
47 	// BFlattenable interface
48 	virtual	bool					IsFixedSize() const;
49 	virtual	type_code				TypeCode() const;
50 	virtual	ssize_t					FlattenedSize() const;
51 	virtual	status_t				Flatten(void* buffer,
52 										ssize_t size) const;
53 	virtual	status_t				Unflatten(type_code code,
54 										const void* buffer, ssize_t size);
55 
56 	// Construction
57 	static	BAffineTransform		AffineTranslation(double x, double y);
58 	static	BAffineTransform		AffineRotation(double angle);
59 	static	BAffineTransform		AffineScaling(double x, double y);
60 	static	BAffineTransform		AffineScaling(double scale);
61 	static	BAffineTransform		AffineShearing(double x, double y);
62 
63 	// Application
64 	inline	void					Apply(double* x, double* y) const;
65 	inline	void					ApplyInverse(double* x, double* y) const;
66 
67 			BPoint					Apply(const BPoint& point) const;
68 			BPoint					ApplyInverse(const BPoint& point) const;
69 
70 			void					Apply(BPoint* point) const;
71 			void					ApplyInverse(BPoint* point) const;
72 
73 			void					Apply(BPoint* points, uint32 count) const;
74 			void					ApplyInverse(BPoint* points,
75 										uint32 count) const;
76 
77 	// Translation
78 	inline	const BAffineTransform&	TranslateBy(double x, double y);
79 			const BAffineTransform&	TranslateBy(const BPoint& delta);
80 
81 			BAffineTransform		TranslateByCopy(double x, double y) const;
82 			BAffineTransform		TranslateByCopy(const BPoint& delta) const;
83 
84 //			const BAffineTransform&	SetTranslation(double x, double y);
85 
86 	// Rotation
87 	inline	const BAffineTransform&	RotateBy(double angle);
88 			const BAffineTransform&	RotateBy(const BPoint& center,
89 										double angle);
90 
91 			BAffineTransform		RotateByCopy(double angle) const;
92 			BAffineTransform		RotateByCopy(const BPoint& center,
93 										double angle) const;
94 
95 //			const BAffineTransform&	SetRotation(double angle);
96 
97 	// Scaling
98 	inline	const BAffineTransform&	ScaleBy(double scale);
99 			const BAffineTransform&	ScaleBy(const BPoint& center,
100 										double scale);
101 	inline	const BAffineTransform&	ScaleBy(double x, double y);
102 			const BAffineTransform&	ScaleBy(const BPoint& center, double x,
103 										double y);
104 			const BAffineTransform&	ScaleBy(const BPoint& scale);
105 			const BAffineTransform&	ScaleBy(const BPoint& center,
106 										const BPoint& scale);
107 
108 			BAffineTransform		ScaleByCopy(double scale) const;
109 			BAffineTransform		ScaleByCopy(const BPoint& center,
110 										double scale) const;
111 			BAffineTransform		ScaleByCopy(double x, double y) const;
112 			BAffineTransform		ScaleByCopy(const BPoint& center,
113 										double x, double y) const;
114 			BAffineTransform		ScaleByCopy(const BPoint& scale) const;
115 			BAffineTransform		ScaleByCopy(const BPoint& center,
116 										const BPoint& scale) const;
117 
118 			const BAffineTransform&	SetScale(double scale);
119 			const BAffineTransform&	SetScale(double x, double y);
120 
121 	// Shearing
122 	inline	const BAffineTransform&	ShearBy(double x, double y);
123 			const BAffineTransform&	ShearBy(const BPoint& center, double x,
124 										double y);
125 			const BAffineTransform&	ShearBy(const BPoint& shear);
126 			const BAffineTransform&	ShearBy(const BPoint& center,
127 										const BPoint& shear);
128 
129 			BAffineTransform		ShearByCopy(double x, double y) const;
130 			BAffineTransform		ShearByCopy(const BPoint& center,
131 										double x, double y) const;
132 			BAffineTransform		ShearByCopy(const BPoint& shear) const;
133 			BAffineTransform		ShearByCopy(const BPoint& center,
134 										const BPoint& shear) const;
135 
136 //			const BAffineTransform&	SetShear(double x, double y);
137 
138 	// Multiplication
139 	inline	const BAffineTransform&	Multiply(const BAffineTransform& other);
140 			const BAffineTransform&	PreMultiply(const BAffineTransform& other);
141 	inline	const BAffineTransform&	MultiplyInverse(
142 										const BAffineTransform& other);
143 	inline	const BAffineTransform&	PreMultiplyInverse(
144 										const BAffineTransform& other);
145 
146 	// Operators
147 	inline	BAffineTransform&		operator=(
148 										const BAffineTransform& copyFrom);
149 
150 	inline	bool					operator==(
151 										const BAffineTransform& other) const;
152 	inline	bool					operator!=(
153 										const BAffineTransform& other) const;
154 
155 	inline	const BAffineTransform&	operator*=(const BAffineTransform& other);
156 	inline	const BAffineTransform&	operator/=(const BAffineTransform& other);
157 
158 	inline	BAffineTransform		operator*(
159 										const BAffineTransform& other) const;
160 	inline	BAffineTransform		operator/(
161 										const BAffineTransform& other) const;
162 
163 	inline	BAffineTransform		operator~() const;
164 
165 	// Utility
166 			bool					IsValid(double epsilon
167 										= kDefaultEpsilon) const;
168 			bool					IsIdentity(double epsilon
169 										= kDefaultEpsilon) const;
170 			bool					IsEqual(const BAffineTransform& other,
171 										double epsilon
172 											= kDefaultEpsilon) const;
173 
174 			const BAffineTransform&	Invert();
175 			const BAffineTransform&	FlipX();
176 			const BAffineTransform&	FlipY();
177 			const BAffineTransform&	Reset();
178 
179 	inline	double					Determinant() const;
180 	inline	double					InverseDeterminant() const;
181 			void					GetTranslation(double* tx,
182 										double* ty) const;
183 			double					Rotation() const;
184 			double					Scale() const;
185 			void					GetScale(double* sx, double* sy) const;
186 			void					GetScaleAbs(double* sx,
187 										double* sy) const;
188 			bool					GetAffineParameters(double* translationX,
189 										double* translationY, double* rotation,
190 										double* scaleX, double* scaleY,
191 										double* shearX, double* shearY) const;
192 
193 public:
194 			double					sx;
195 			double					shy;
196 			double					shx;
197 			double					sy;
198 			double					tx;
199 			double					ty;
200 };
201 
202 
203 extern const BAffineTransform B_AFFINE_IDENTITY_TRANSFORM;
204 
205 
206 // #pragma mark - inline methods
207 
208 
209 inline void
210 BAffineTransform::Apply(double* x, double* y) const
211 {
212 	register double tmp = *x;
213 	*x = tmp * sx + *y * shx + tx;
214 	*y = tmp * shy + *y * sy + ty;
215 }
216 
217 
218 inline void
219 BAffineTransform::ApplyInverse(double* x, double* y) const
220 {
221 	register double d = InverseDeterminant();
222 	register double a = (*x - tx) * d;
223 	register double b = (*y - ty) * d;
224 	*x = a * sy - b * shx;
225 	*y = b * sx - a * shy;
226 }
227 
228 
229 // #pragma mark -
230 
231 
232 inline const BAffineTransform&
233 BAffineTransform::TranslateBy(double x, double y)
234 {
235 	tx += x;
236 	ty += y;
237 	return *this;
238 }
239 
240 
241 inline const BAffineTransform&
242 BAffineTransform::RotateBy(double angle)
243 {
244 	double ca = cos(angle);
245 	double sa = sin(angle);
246 	double t0 = sx * ca - shy * sa;
247 	double t2 = shx * ca - sy * sa;
248 	double t4 = tx * ca - ty * sa;
249 	shy = sx * sa + shy * ca;
250 	sy = shx * sa + sy * ca;
251 	ty = tx * sa + ty * ca;
252 	sx = t0;
253 	shx = t2;
254 	tx = t4;
255 	return *this;
256 }
257 
258 
259 inline const BAffineTransform&
260 BAffineTransform::ScaleBy(double x, double y)
261 {
262 	double mm0 = x;
263 		// Possible hint for the optimizer
264 	double mm3 = y;
265 	sx *= mm0;
266 	shx *= mm0;
267 	tx *= mm0;
268 	shy *= mm3;
269 	sy *= mm3;
270 	ty *= mm3;
271 	return *this;
272 }
273 
274 
275 inline const BAffineTransform&
276 BAffineTransform::ScaleBy(double s)
277 {
278 	double m = s;
279 		// Possible hint for the optimizer
280 	sx *= m;
281 	shx *= m;
282 	tx *= m;
283 	shy *= m;
284 	sy *= m;
285 	ty *= m;
286 	return *this;
287 }
288 
289 
290 inline const BAffineTransform&
291 BAffineTransform::ShearBy(double x, double y)
292 {
293 	BAffineTransform shearTransform = AffineShearing(x, y);
294 	return PreMultiply(shearTransform);
295 }
296 
297 
298 // #pragma mark -
299 
300 
301 inline const BAffineTransform&
302 BAffineTransform::Multiply(const BAffineTransform& other)
303 {
304 	BAffineTransform t(other);
305 	return *this = t.PreMultiply(*this);
306 }
307 
308 
309 inline const BAffineTransform&
310 BAffineTransform::MultiplyInverse(const BAffineTransform& other)
311 {
312 	BAffineTransform t(other);
313 	t.Invert();
314 	return Multiply(t);
315 }
316 
317 
318 inline const BAffineTransform&
319 BAffineTransform::PreMultiplyInverse(const BAffineTransform& other)
320 {
321 	BAffineTransform t(other);
322 	t.Invert();
323 	return *this = t.Multiply(*this);
324 }
325 
326 
327 // #pragma mark -
328 
329 
330 inline BAffineTransform&
331 BAffineTransform::operator=(const BAffineTransform& other)
332 {
333 	sx = other.sx;
334 	shy = other.shy;
335 	shx = other.shx;
336 	sy = other.sy;
337 	tx = other.tx;
338 	ty = other.ty;
339 	return *this;
340 }
341 
342 inline bool
343 BAffineTransform::operator==(const BAffineTransform& other) const
344 {
345 	return IsEqual(other);
346 }
347 
348 inline bool
349 BAffineTransform::operator!=(const BAffineTransform& other) const
350 {
351 	return !IsEqual(other);
352 }
353 
354 
355 inline const BAffineTransform&
356 BAffineTransform::operator*=(const BAffineTransform& other)
357 {
358 	return Multiply(other);
359 }
360 
361 
362 inline const BAffineTransform&
363 BAffineTransform::operator/=(const BAffineTransform& other)
364 {
365 	return MultiplyInverse(other);
366 }
367 
368 
369 inline BAffineTransform
370 BAffineTransform::operator*(const BAffineTransform& other) const
371 {
372 	return BAffineTransform(*this).Multiply(other);
373 }
374 
375 
376 inline BAffineTransform
377 BAffineTransform::operator/(const BAffineTransform& other) const
378 {
379 	return BAffineTransform(*this).MultiplyInverse(other);
380 }
381 
382 
383 inline BAffineTransform
384 BAffineTransform::operator~() const
385 {
386 	BAffineTransform result(*this);
387 	return result.Invert();
388 }
389 
390 
391 // #pragma mark -
392 
393 
394 inline double
395 BAffineTransform::Determinant() const
396 {
397 	return sx * sy - shy * shx;
398 }
399 
400 
401 inline double
402 BAffineTransform::InverseDeterminant() const
403 {
404 	return 1.0 / (sx * sy - shy * shx);
405 }
406 
407 
408 #endif // _AFFINE_TRANSFORM_H
409