xref: /haiku/headers/os/interface/AffineTransform.h (revision 3af8011358bd4c624a0979336d48dabb466171ed)
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 #if __cplusplus < 201103L
37 	static	const double			kDefaultEpsilon = 1e-14;
38 #else
39 	static	constexpr double		kDefaultEpsilon = 1e-14;
40 #endif
41 
42 public:
43 									BAffineTransform();
44 									BAffineTransform(double sx, double shy,
45 										double shx, double sy, double tx,
46 										double ty);
47 									BAffineTransform(
48 										const BAffineTransform& copyFrom);
49 	virtual							~BAffineTransform();
50 
51 	// BFlattenable interface
52 	virtual	bool					IsFixedSize() const;
53 	virtual	type_code				TypeCode() const;
54 	virtual	ssize_t					FlattenedSize() const;
55 	virtual	status_t				Flatten(void* buffer,
56 										ssize_t size) const;
57 	virtual	status_t				Unflatten(type_code code,
58 										const void* buffer, ssize_t size);
59 
60 	// Construction
61 	static	BAffineTransform		AffineTranslation(double x, double y);
62 	static	BAffineTransform		AffineRotation(double angle);
63 	static	BAffineTransform		AffineScaling(double x, double y);
64 	static	BAffineTransform		AffineScaling(double scale);
65 	static	BAffineTransform		AffineShearing(double x, double y);
66 
67 	// Application
68 	inline	void					Apply(double* x, double* y) const;
69 	inline	void					ApplyInverse(double* x, double* y) const;
70 
71 			BPoint					Apply(const BPoint& point) const;
72 			BPoint					ApplyInverse(const BPoint& point) const;
73 
74 			void					Apply(BPoint* point) const;
75 			void					ApplyInverse(BPoint* point) const;
76 
77 			void					Apply(BPoint* points, uint32 count) const;
78 			void					ApplyInverse(BPoint* points,
79 										uint32 count) const;
80 
81 	// Translation
82 	inline	const BAffineTransform&	TranslateBy(double x, double y);
83 			const BAffineTransform&	TranslateBy(const BPoint& delta);
84 
85 	inline	const BAffineTransform&	PreTranslateBy(double x, double y);
86 
87 			BAffineTransform		TranslateByCopy(double x, double y) const;
88 			BAffineTransform		TranslateByCopy(const BPoint& delta) const;
89 
90 //			const BAffineTransform&	SetTranslation(double x, double y);
91 
92 	// Rotation
93 	inline	const BAffineTransform&	RotateBy(double angle);
94 			const BAffineTransform&	RotateBy(const BPoint& center,
95 										double angle);
96 
97 	inline	const BAffineTransform&	PreRotateBy(double angleRadians);
98 
99 			BAffineTransform		RotateByCopy(double angle) const;
100 			BAffineTransform		RotateByCopy(const BPoint& center,
101 										double angle) const;
102 
103 //			const BAffineTransform&	SetRotation(double angle);
104 
105 	// Scaling
106 	inline	const BAffineTransform&	ScaleBy(double scale);
107 			const BAffineTransform&	ScaleBy(const BPoint& center,
108 										double scale);
109 	inline	const BAffineTransform&	ScaleBy(double x, double y);
110 			const BAffineTransform&	ScaleBy(const BPoint& center, double x,
111 										double y);
112 			const BAffineTransform&	ScaleBy(const BPoint& scale);
113 			const BAffineTransform&	ScaleBy(const BPoint& center,
114 										const BPoint& scale);
115 
116 	inline	const BAffineTransform&	PreScaleBy(double x, double y);
117 
118 			BAffineTransform		ScaleByCopy(double scale) const;
119 			BAffineTransform		ScaleByCopy(const BPoint& center,
120 										double scale) const;
121 			BAffineTransform		ScaleByCopy(double x, double y) const;
122 			BAffineTransform		ScaleByCopy(const BPoint& center,
123 										double x, double y) const;
124 			BAffineTransform		ScaleByCopy(const BPoint& scale) const;
125 			BAffineTransform		ScaleByCopy(const BPoint& center,
126 										const BPoint& scale) const;
127 
128 			const BAffineTransform&	SetScale(double scale);
129 			const BAffineTransform&	SetScale(double x, double y);
130 
131 	// Shearing
132 	inline	const BAffineTransform&	ShearBy(double x, double y);
133 			const BAffineTransform&	ShearBy(const BPoint& center, double x,
134 										double y);
135 			const BAffineTransform&	ShearBy(const BPoint& shear);
136 			const BAffineTransform&	ShearBy(const BPoint& center,
137 										const BPoint& shear);
138 
139 			BAffineTransform		ShearByCopy(double x, double y) const;
140 			BAffineTransform		ShearByCopy(const BPoint& center,
141 										double x, double y) const;
142 			BAffineTransform		ShearByCopy(const BPoint& shear) const;
143 			BAffineTransform		ShearByCopy(const BPoint& center,
144 										const BPoint& shear) const;
145 
146 //			const BAffineTransform&	SetShear(double x, double y);
147 
148 	// Multiplication
149 	inline	const BAffineTransform&	Multiply(const BAffineTransform& other);
150 			const BAffineTransform&	PreMultiply(const BAffineTransform& other);
151 	inline	const BAffineTransform&	MultiplyInverse(
152 										const BAffineTransform& other);
153 	inline	const BAffineTransform&	PreMultiplyInverse(
154 										const BAffineTransform& other);
155 
156 	// Operators
157 	inline	BAffineTransform&		operator=(
158 										const BAffineTransform& copyFrom);
159 
160 	inline	bool					operator==(
161 										const BAffineTransform& other) const;
162 	inline	bool					operator!=(
163 										const BAffineTransform& other) const;
164 
165 	inline	const BAffineTransform&	operator*=(const BAffineTransform& other);
166 	inline	const BAffineTransform&	operator/=(const BAffineTransform& other);
167 
168 	inline	BAffineTransform		operator*(
169 										const BAffineTransform& other) const;
170 	inline	BAffineTransform		operator/(
171 										const BAffineTransform& other) const;
172 
173 	inline	BAffineTransform		operator~() const;
174 
175 	// Utility
176 			bool					IsValid(double epsilon
177 										= kDefaultEpsilon) const;
178 			bool					IsIdentity(double epsilon
179 										= kDefaultEpsilon) const;
180 			bool					IsDilation(double epsilon
181 										= kDefaultEpsilon) const;
182 			bool					IsEqual(const BAffineTransform& other,
183 										double epsilon
184 											= kDefaultEpsilon) const;
185 
186 			const BAffineTransform&	Invert();
187 			const BAffineTransform&	FlipX();
188 			const BAffineTransform&	FlipY();
189 			const BAffineTransform&	Reset();
190 
191 	inline	double					Determinant() const;
192 	inline	double					InverseDeterminant() const;
193 			void					GetTranslation(double* tx,
194 										double* ty) const;
195 			double					Rotation() const;
196 			double					Scale() const;
197 			void					GetScale(double* sx, double* sy) const;
198 			void					GetScaleAbs(double* sx,
199 										double* sy) const;
200 			bool					GetAffineParameters(double* translationX,
201 										double* translationY, double* rotation,
202 										double* scaleX, double* scaleY,
203 										double* shearX, double* shearY) const;
204 
205 public:
206 			double					sx;
207 			double					shy;
208 			double					shx;
209 			double					sy;
210 			double					tx;
211 			double					ty;
212 };
213 
214 
215 extern const BAffineTransform B_AFFINE_IDENTITY_TRANSFORM;
216 
217 
218 // #pragma mark - inline methods
219 
220 
221 inline void
222 BAffineTransform::Apply(double* x, double* y) const
223 {
224 	double tmp = *x;
225 	*x = tmp * sx + *y * shx + tx;
226 	*y = tmp * shy + *y * sy + ty;
227 }
228 
229 
230 inline void
231 BAffineTransform::ApplyInverse(double* x, double* y) const
232 {
233 	double d = InverseDeterminant();
234 	double a = (*x - tx) * d;
235 	double b = (*y - ty) * d;
236 	*x = a * sy - b * shx;
237 	*y = b * sx - a * shy;
238 }
239 
240 
241 // #pragma mark -
242 
243 
244 inline const BAffineTransform&
245 BAffineTransform::TranslateBy(double x, double y)
246 {
247 	tx += x;
248 	ty += y;
249 	return *this;
250 }
251 
252 
253 inline const BAffineTransform&
254 BAffineTransform::PreTranslateBy(double x, double y)
255 {
256 	tx += x * sx + y * shx;
257 	ty += x * shy + y * sy;
258 	return *this;
259 }
260 
261 
262 inline const BAffineTransform&
263 BAffineTransform::RotateBy(double angle)
264 {
265 	double ca = cos(angle);
266 	double sa = sin(angle);
267 	double t0 = sx * ca - shy * sa;
268 	double t2 = shx * ca - sy * sa;
269 	double t4 = tx * ca - ty * sa;
270 	shy = sx * sa + shy * ca;
271 	sy = shx * sa + sy * ca;
272 	ty = tx * sa + ty * ca;
273 	sx = t0;
274 	shx = t2;
275 	tx = t4;
276 	return *this;
277 }
278 
279 
280 inline const BAffineTransform&
281 BAffineTransform::PreRotateBy(double angle)
282 {
283 	double ca = cos(angle);
284 	double sa = sin(angle);
285 	double newSx = sx * ca + shx * sa;
286 	double newSy = -shy * sa + sy * ca;
287 	shy = shy * ca + sy * sa;
288 	shx = -sx * sa + shx * ca;
289 	sx = newSx;
290 	sy = newSy;
291 	return *this;
292 }
293 
294 
295 inline const BAffineTransform&
296 BAffineTransform::ScaleBy(double x, double y)
297 {
298 	double mm0 = x;
299 		// Possible hint for the optimizer
300 	double mm3 = y;
301 	sx *= mm0;
302 	shx *= mm0;
303 	tx *= mm0;
304 	shy *= mm3;
305 	sy *= mm3;
306 	ty *= mm3;
307 	return *this;
308 }
309 
310 
311 inline const BAffineTransform&
312 BAffineTransform::ScaleBy(double s)
313 {
314 	double m = s;
315 		// Possible hint for the optimizer
316 	sx *= m;
317 	shx *= m;
318 	tx *= m;
319 	shy *= m;
320 	sy *= m;
321 	ty *= m;
322 	return *this;
323 }
324 
325 
326 inline const BAffineTransform&
327 BAffineTransform::PreScaleBy(double x, double y)
328 {
329 	sx *= x;
330 	shx *= y;
331 	shy *= x;
332 	sy *= y;
333 	return *this;
334 }
335 
336 
337 inline const BAffineTransform&
338 BAffineTransform::ShearBy(double x, double y)
339 {
340 	BAffineTransform shearTransform = AffineShearing(x, y);
341 	return PreMultiply(shearTransform);
342 }
343 
344 
345 // #pragma mark -
346 
347 
348 inline const BAffineTransform&
349 BAffineTransform::Multiply(const BAffineTransform& other)
350 {
351 	BAffineTransform t(other);
352 	return *this = t.PreMultiply(*this);
353 }
354 
355 
356 inline const BAffineTransform&
357 BAffineTransform::MultiplyInverse(const BAffineTransform& other)
358 {
359 	BAffineTransform t(other);
360 	t.Invert();
361 	return Multiply(t);
362 }
363 
364 
365 inline const BAffineTransform&
366 BAffineTransform::PreMultiplyInverse(const BAffineTransform& other)
367 {
368 	BAffineTransform t(other);
369 	t.Invert();
370 	return *this = t.Multiply(*this);
371 }
372 
373 
374 // #pragma mark -
375 
376 
377 inline BAffineTransform&
378 BAffineTransform::operator=(const BAffineTransform& other)
379 {
380 	sx = other.sx;
381 	shy = other.shy;
382 	shx = other.shx;
383 	sy = other.sy;
384 	tx = other.tx;
385 	ty = other.ty;
386 	return *this;
387 }
388 
389 inline bool
390 BAffineTransform::operator==(const BAffineTransform& other) const
391 {
392 	return IsEqual(other);
393 }
394 
395 inline bool
396 BAffineTransform::operator!=(const BAffineTransform& other) const
397 {
398 	return !IsEqual(other);
399 }
400 
401 
402 inline const BAffineTransform&
403 BAffineTransform::operator*=(const BAffineTransform& other)
404 {
405 	return Multiply(other);
406 }
407 
408 
409 inline const BAffineTransform&
410 BAffineTransform::operator/=(const BAffineTransform& other)
411 {
412 	return MultiplyInverse(other);
413 }
414 
415 
416 inline BAffineTransform
417 BAffineTransform::operator*(const BAffineTransform& other) const
418 {
419 	return BAffineTransform(*this).Multiply(other);
420 }
421 
422 
423 inline BAffineTransform
424 BAffineTransform::operator/(const BAffineTransform& other) const
425 {
426 	return BAffineTransform(*this).MultiplyInverse(other);
427 }
428 
429 
430 inline BAffineTransform
431 BAffineTransform::operator~() const
432 {
433 	BAffineTransform result(*this);
434 	return result.Invert();
435 }
436 
437 
438 // #pragma mark -
439 
440 
441 inline double
442 BAffineTransform::Determinant() const
443 {
444 	return sx * sy - shy * shx;
445 }
446 
447 
448 inline double
449 BAffineTransform::InverseDeterminant() const
450 {
451 	return 1.0 / (sx * sy - shy * shx);
452 }
453 
454 
455 #endif // _AFFINE_TRANSFORM_H
456