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