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 static const double kDefaultEpsilon = 1e-14; 37 38public: 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 193public: 194 double sx; 195 double shy; 196 double shx; 197 double sy; 198 double tx; 199 double ty; 200}; 201 202 203extern const BAffineTransform B_AFFINE_IDENTITY_TRANSFORM; 204 205 206// #pragma mark - inline methods 207 208 209inline void 210BAffineTransform::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 218inline void 219BAffineTransform::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 232inline const BAffineTransform& 233BAffineTransform::TranslateBy(double x, double y) 234{ 235 tx += x; 236 ty += y; 237 return *this; 238} 239 240 241inline const BAffineTransform& 242BAffineTransform::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 259inline const BAffineTransform& 260BAffineTransform::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 275inline const BAffineTransform& 276BAffineTransform::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 290inline const BAffineTransform& 291BAffineTransform::ShearBy(double x, double y) 292{ 293 BAffineTransform shearTransform = AffineShearing(x, y); 294 return PreMultiply(shearTransform); 295} 296 297 298// #pragma mark - 299 300 301inline const BAffineTransform& 302BAffineTransform::Multiply(const BAffineTransform& other) 303{ 304 BAffineTransform t(other); 305 return *this = t.PreMultiply(*this); 306} 307 308 309inline const BAffineTransform& 310BAffineTransform::MultiplyInverse(const BAffineTransform& other) 311{ 312 BAffineTransform t(other); 313 t.Invert(); 314 return Multiply(t); 315} 316 317 318inline const BAffineTransform& 319BAffineTransform::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 330inline BAffineTransform& 331BAffineTransform::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 342inline bool 343BAffineTransform::operator==(const BAffineTransform& other) const 344{ 345 return IsEqual(other); 346} 347 348inline bool 349BAffineTransform::operator!=(const BAffineTransform& other) const 350{ 351 return !IsEqual(other); 352} 353 354 355inline const BAffineTransform& 356BAffineTransform::operator*=(const BAffineTransform& other) 357{ 358 return Multiply(other); 359} 360 361 362inline const BAffineTransform& 363BAffineTransform::operator/=(const BAffineTransform& other) 364{ 365 return MultiplyInverse(other); 366} 367 368 369inline BAffineTransform 370BAffineTransform::operator*(const BAffineTransform& other) const 371{ 372 return BAffineTransform(*this).Multiply(other); 373} 374 375 376inline BAffineTransform 377BAffineTransform::operator/(const BAffineTransform& other) const 378{ 379 return BAffineTransform(*this).MultiplyInverse(other); 380} 381 382 383inline BAffineTransform 384BAffineTransform::operator~() const 385{ 386 BAffineTransform result(*this); 387 return result.Invert(); 388} 389 390 391// #pragma mark - 392 393 394inline double 395BAffineTransform::Determinant() const 396{ 397 return sx * sy - shy * shx; 398} 399 400 401inline double 402BAffineTransform::InverseDeterminant() const 403{ 404 return 1.0 / (sx * sy - shy * shx); 405} 406 407 408#endif // _AFFINE_TRANSFORM_H 409