xref: /haiku/headers/os/interface/AffineTransform.h (revision 22440f4105cafc95cc1d49f9bc65bb395c527d86)
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 			BAffineTransform		TranslateByCopy(double x, double y) const;
86 			BAffineTransform		TranslateByCopy(const BPoint& delta) const;
87 
88 //			const BAffineTransform&	SetTranslation(double x, double y);
89 
90 	// Rotation
91 	inline	const BAffineTransform&	RotateBy(double angle);
92 			const BAffineTransform&	RotateBy(const BPoint& center,
93 										double angle);
94 
95 			BAffineTransform		RotateByCopy(double angle) const;
96 			BAffineTransform		RotateByCopy(const BPoint& center,
97 										double angle) const;
98 
99 //			const BAffineTransform&	SetRotation(double angle);
100 
101 	// Scaling
102 	inline	const BAffineTransform&	ScaleBy(double scale);
103 			const BAffineTransform&	ScaleBy(const BPoint& center,
104 										double scale);
105 	inline	const BAffineTransform&	ScaleBy(double x, double y);
106 			const BAffineTransform&	ScaleBy(const BPoint& center, double x,
107 										double y);
108 			const BAffineTransform&	ScaleBy(const BPoint& scale);
109 			const BAffineTransform&	ScaleBy(const BPoint& center,
110 										const BPoint& scale);
111 
112 			BAffineTransform		ScaleByCopy(double scale) const;
113 			BAffineTransform		ScaleByCopy(const BPoint& center,
114 										double scale) const;
115 			BAffineTransform		ScaleByCopy(double x, double y) const;
116 			BAffineTransform		ScaleByCopy(const BPoint& center,
117 										double x, double y) const;
118 			BAffineTransform		ScaleByCopy(const BPoint& scale) const;
119 			BAffineTransform		ScaleByCopy(const BPoint& center,
120 										const BPoint& scale) const;
121 
122 			const BAffineTransform&	SetScale(double scale);
123 			const BAffineTransform&	SetScale(double x, double y);
124 
125 	// Shearing
126 	inline	const BAffineTransform&	ShearBy(double x, double y);
127 			const BAffineTransform&	ShearBy(const BPoint& center, double x,
128 										double y);
129 			const BAffineTransform&	ShearBy(const BPoint& shear);
130 			const BAffineTransform&	ShearBy(const BPoint& center,
131 										const BPoint& shear);
132 
133 			BAffineTransform		ShearByCopy(double x, double y) const;
134 			BAffineTransform		ShearByCopy(const BPoint& center,
135 										double x, double y) const;
136 			BAffineTransform		ShearByCopy(const BPoint& shear) const;
137 			BAffineTransform		ShearByCopy(const BPoint& center,
138 										const BPoint& shear) const;
139 
140 //			const BAffineTransform&	SetShear(double x, double y);
141 
142 	// Multiplication
143 	inline	const BAffineTransform&	Multiply(const BAffineTransform& other);
144 			const BAffineTransform&	PreMultiply(const BAffineTransform& other);
145 	inline	const BAffineTransform&	MultiplyInverse(
146 										const BAffineTransform& other);
147 	inline	const BAffineTransform&	PreMultiplyInverse(
148 										const BAffineTransform& other);
149 
150 	// Operators
151 	inline	BAffineTransform&		operator=(
152 										const BAffineTransform& copyFrom);
153 
154 	inline	bool					operator==(
155 										const BAffineTransform& other) const;
156 	inline	bool					operator!=(
157 										const BAffineTransform& other) const;
158 
159 	inline	const BAffineTransform&	operator*=(const BAffineTransform& other);
160 	inline	const BAffineTransform&	operator/=(const BAffineTransform& other);
161 
162 	inline	BAffineTransform		operator*(
163 										const BAffineTransform& other) const;
164 	inline	BAffineTransform		operator/(
165 										const BAffineTransform& other) const;
166 
167 	inline	BAffineTransform		operator~() const;
168 
169 	// Utility
170 			bool					IsValid(double epsilon
171 										= kDefaultEpsilon) const;
172 			bool					IsIdentity(double epsilon
173 										= kDefaultEpsilon) const;
174 			bool					IsEqual(const BAffineTransform& other,
175 										double epsilon
176 											= kDefaultEpsilon) const;
177 
178 			const BAffineTransform&	Invert();
179 			const BAffineTransform&	FlipX();
180 			const BAffineTransform&	FlipY();
181 			const BAffineTransform&	Reset();
182 
183 	inline	double					Determinant() const;
184 	inline	double					InverseDeterminant() const;
185 			void					GetTranslation(double* tx,
186 										double* ty) const;
187 			double					Rotation() const;
188 			double					Scale() const;
189 			void					GetScale(double* sx, double* sy) const;
190 			void					GetScaleAbs(double* sx,
191 										double* sy) const;
192 			bool					GetAffineParameters(double* translationX,
193 										double* translationY, double* rotation,
194 										double* scaleX, double* scaleY,
195 										double* shearX, double* shearY) const;
196 
197 public:
198 			double					sx;
199 			double					shy;
200 			double					shx;
201 			double					sy;
202 			double					tx;
203 			double					ty;
204 };
205 
206 
207 extern const BAffineTransform B_AFFINE_IDENTITY_TRANSFORM;
208 
209 
210 // #pragma mark - inline methods
211 
212 
213 inline void
214 BAffineTransform::Apply(double* x, double* y) const
215 {
216 	register double tmp = *x;
217 	*x = tmp * sx + *y * shx + tx;
218 	*y = tmp * shy + *y * sy + ty;
219 }
220 
221 
222 inline void
223 BAffineTransform::ApplyInverse(double* x, double* y) const
224 {
225 	register double d = InverseDeterminant();
226 	register double a = (*x - tx) * d;
227 	register double b = (*y - ty) * d;
228 	*x = a * sy - b * shx;
229 	*y = b * sx - a * shy;
230 }
231 
232 
233 // #pragma mark -
234 
235 
236 inline const BAffineTransform&
237 BAffineTransform::TranslateBy(double x, double y)
238 {
239 	tx += x;
240 	ty += y;
241 	return *this;
242 }
243 
244 
245 inline const BAffineTransform&
246 BAffineTransform::RotateBy(double angle)
247 {
248 	double ca = cos(angle);
249 	double sa = sin(angle);
250 	double t0 = sx * ca - shy * sa;
251 	double t2 = shx * ca - sy * sa;
252 	double t4 = tx * ca - ty * sa;
253 	shy = sx * sa + shy * ca;
254 	sy = shx * sa + sy * ca;
255 	ty = tx * sa + ty * ca;
256 	sx = t0;
257 	shx = t2;
258 	tx = t4;
259 	return *this;
260 }
261 
262 
263 inline const BAffineTransform&
264 BAffineTransform::ScaleBy(double x, double y)
265 {
266 	double mm0 = x;
267 		// Possible hint for the optimizer
268 	double mm3 = y;
269 	sx *= mm0;
270 	shx *= mm0;
271 	tx *= mm0;
272 	shy *= mm3;
273 	sy *= mm3;
274 	ty *= mm3;
275 	return *this;
276 }
277 
278 
279 inline const BAffineTransform&
280 BAffineTransform::ScaleBy(double s)
281 {
282 	double m = s;
283 		// Possible hint for the optimizer
284 	sx *= m;
285 	shx *= m;
286 	tx *= m;
287 	shy *= m;
288 	sy *= m;
289 	ty *= m;
290 	return *this;
291 }
292 
293 
294 inline const BAffineTransform&
295 BAffineTransform::ShearBy(double x, double y)
296 {
297 	BAffineTransform shearTransform = AffineShearing(x, y);
298 	return PreMultiply(shearTransform);
299 }
300 
301 
302 // #pragma mark -
303 
304 
305 inline const BAffineTransform&
306 BAffineTransform::Multiply(const BAffineTransform& other)
307 {
308 	BAffineTransform t(other);
309 	return *this = t.PreMultiply(*this);
310 }
311 
312 
313 inline const BAffineTransform&
314 BAffineTransform::MultiplyInverse(const BAffineTransform& other)
315 {
316 	BAffineTransform t(other);
317 	t.Invert();
318 	return Multiply(t);
319 }
320 
321 
322 inline const BAffineTransform&
323 BAffineTransform::PreMultiplyInverse(const BAffineTransform& other)
324 {
325 	BAffineTransform t(other);
326 	t.Invert();
327 	return *this = t.Multiply(*this);
328 }
329 
330 
331 // #pragma mark -
332 
333 
334 inline BAffineTransform&
335 BAffineTransform::operator=(const BAffineTransform& other)
336 {
337 	sx = other.sx;
338 	shy = other.shy;
339 	shx = other.shx;
340 	sy = other.sy;
341 	tx = other.tx;
342 	ty = other.ty;
343 	return *this;
344 }
345 
346 inline bool
347 BAffineTransform::operator==(const BAffineTransform& other) const
348 {
349 	return IsEqual(other);
350 }
351 
352 inline bool
353 BAffineTransform::operator!=(const BAffineTransform& other) const
354 {
355 	return !IsEqual(other);
356 }
357 
358 
359 inline const BAffineTransform&
360 BAffineTransform::operator*=(const BAffineTransform& other)
361 {
362 	return Multiply(other);
363 }
364 
365 
366 inline const BAffineTransform&
367 BAffineTransform::operator/=(const BAffineTransform& other)
368 {
369 	return MultiplyInverse(other);
370 }
371 
372 
373 inline BAffineTransform
374 BAffineTransform::operator*(const BAffineTransform& other) const
375 {
376 	return BAffineTransform(*this).Multiply(other);
377 }
378 
379 
380 inline BAffineTransform
381 BAffineTransform::operator/(const BAffineTransform& other) const
382 {
383 	return BAffineTransform(*this).MultiplyInverse(other);
384 }
385 
386 
387 inline BAffineTransform
388 BAffineTransform::operator~() const
389 {
390 	BAffineTransform result(*this);
391 	return result.Invert();
392 }
393 
394 
395 // #pragma mark -
396 
397 
398 inline double
399 BAffineTransform::Determinant() const
400 {
401 	return sx * sy - shy * shx;
402 }
403 
404 
405 inline double
406 BAffineTransform::InverseDeterminant() const
407 {
408 	return 1.0 / (sx * sy - shy * shx);
409 }
410 
411 
412 #endif // _AFFINE_TRANSFORM_H
413