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