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