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 33class BAffineTransform : public BFlattenable { 34public: 35 36#if __cplusplus < 201103L 37 static const double kDefaultEpsilon = 1e-14; 38#else 39 static constexpr double kDefaultEpsilon = 1e-14; 40#endif 41 42public: 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 205public: 206 double sx; 207 double shy; 208 double shx; 209 double sy; 210 double tx; 211 double ty; 212}; 213 214 215extern const BAffineTransform B_AFFINE_IDENTITY_TRANSFORM; 216 217 218// #pragma mark - inline methods 219 220 221inline void 222BAffineTransform::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 230inline void 231BAffineTransform::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 244inline const BAffineTransform& 245BAffineTransform::TranslateBy(double x, double y) 246{ 247 tx += x; 248 ty += y; 249 return *this; 250} 251 252 253inline const BAffineTransform& 254BAffineTransform::PreTranslateBy(double x, double y) 255{ 256 tx += x * sx + y * shx; 257 ty += x * shy + y * sy; 258 return *this; 259} 260 261 262inline const BAffineTransform& 263BAffineTransform::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 280inline const BAffineTransform& 281BAffineTransform::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 295inline const BAffineTransform& 296BAffineTransform::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 311inline const BAffineTransform& 312BAffineTransform::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 326inline const BAffineTransform& 327BAffineTransform::PreScaleBy(double x, double y) 328{ 329 sx *= x; 330 shx *= y; 331 shy *= x; 332 sy *= y; 333 return *this; 334} 335 336 337inline const BAffineTransform& 338BAffineTransform::ShearBy(double x, double y) 339{ 340 BAffineTransform shearTransform = AffineShearing(x, y); 341 return PreMultiply(shearTransform); 342} 343 344 345// #pragma mark - 346 347 348inline const BAffineTransform& 349BAffineTransform::Multiply(const BAffineTransform& other) 350{ 351 BAffineTransform t(other); 352 return *this = t.PreMultiply(*this); 353} 354 355 356inline const BAffineTransform& 357BAffineTransform::MultiplyInverse(const BAffineTransform& other) 358{ 359 BAffineTransform t(other); 360 t.Invert(); 361 return Multiply(t); 362} 363 364 365inline const BAffineTransform& 366BAffineTransform::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 377inline BAffineTransform& 378BAffineTransform::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 389inline bool 390BAffineTransform::operator==(const BAffineTransform& other) const 391{ 392 return IsEqual(other); 393} 394 395inline bool 396BAffineTransform::operator!=(const BAffineTransform& other) const 397{ 398 return !IsEqual(other); 399} 400 401 402inline const BAffineTransform& 403BAffineTransform::operator*=(const BAffineTransform& other) 404{ 405 return Multiply(other); 406} 407 408 409inline const BAffineTransform& 410BAffineTransform::operator/=(const BAffineTransform& other) 411{ 412 return MultiplyInverse(other); 413} 414 415 416inline BAffineTransform 417BAffineTransform::operator*(const BAffineTransform& other) const 418{ 419 return BAffineTransform(*this).Multiply(other); 420} 421 422 423inline BAffineTransform 424BAffineTransform::operator/(const BAffineTransform& other) const 425{ 426 return BAffineTransform(*this).MultiplyInverse(other); 427} 428 429 430inline BAffineTransform 431BAffineTransform::operator~() const 432{ 433 BAffineTransform result(*this); 434 return result.Invert(); 435} 436 437 438// #pragma mark - 439 440 441inline double 442BAffineTransform::Determinant() const 443{ 444 return sx * sy - shy * shx; 445} 446 447 448inline double 449BAffineTransform::InverseDeterminant() const 450{ 451 return 1.0 / (sx * sy - shy * shx); 452} 453 454 455#endif // _AFFINE_TRANSFORM_H 456