d7fcb36f2b
* Added commented versions for translation, rotation and shear, which would work similar. * Added B_AFFINE_IDENTITY_TRANSFORM constant similar to B_ORIGIN. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36401 a95241bf-73f2-0310-859d-f6bbb57e9c96
409 lines
10 KiB
C++
409 lines
10 KiB
C++
/*
|
|
* Copyright 2008-2010, Haiku, Inc. All Rights Reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Stephen Deken, stephen.deken@gmail.com
|
|
* Stephan Aßmus <superstippi@gmx.de>
|
|
*/
|
|
//----------------------------------------------------------------------------
|
|
// Anti-Grain Geometry - Version 2.4
|
|
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
|
//
|
|
// Permission to copy, use, modify, sell and distribute this software
|
|
// is granted provided this copyright notice appears in all copies.
|
|
// This software is provided "as is" without express or implied
|
|
// warranty, and with no claim as to its suitability for any purpose.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
// Contact: mcseem@antigrain.com
|
|
// mcseemagg@yahoo.com
|
|
// http://www.antigrain.com
|
|
//----------------------------------------------------------------------------
|
|
#ifndef _AFFINE_TRANSFORM_H
|
|
#define _AFFINE_TRANSFORM_H
|
|
|
|
|
|
#include <Flattenable.h>
|
|
#include <Point.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
class BAffineTransform : public BFlattenable {
|
|
public:
|
|
|
|
static const double kDefaultEpsilon = 1e-14;
|
|
|
|
public:
|
|
BAffineTransform();
|
|
BAffineTransform(double sx, double shy,
|
|
double shx, double sy, double tx,
|
|
double ty);
|
|
BAffineTransform(
|
|
const BAffineTransform& copyFrom);
|
|
virtual ~BAffineTransform();
|
|
|
|
// BFlattenable interface
|
|
virtual bool IsFixedSize() const;
|
|
virtual type_code TypeCode() const;
|
|
virtual ssize_t FlattenedSize() const;
|
|
virtual status_t Flatten(void* buffer,
|
|
ssize_t size) const;
|
|
virtual status_t Unflatten(type_code code,
|
|
const void* buffer, ssize_t size);
|
|
|
|
// Construction
|
|
static BAffineTransform AffineTranslation(double x, double y);
|
|
static BAffineTransform AffineRotation(double angle);
|
|
static BAffineTransform AffineScaling(double x, double y);
|
|
static BAffineTransform AffineScaling(double scale);
|
|
static BAffineTransform AffineShearing(double x, double y);
|
|
|
|
// Application
|
|
inline void Apply(double* x, double* y) const;
|
|
inline void ApplyInverse(double* x, double* y) const;
|
|
|
|
BPoint Apply(const BPoint& point) const;
|
|
BPoint ApplyInverse(const BPoint& point) const;
|
|
|
|
void Apply(BPoint* point) const;
|
|
void ApplyInverse(BPoint* point) const;
|
|
|
|
void Apply(BPoint* points, uint32 count) const;
|
|
void ApplyInverse(BPoint* points,
|
|
uint32 count) const;
|
|
|
|
// Translation
|
|
inline const BAffineTransform& TranslateBy(double x, double y);
|
|
const BAffineTransform& TranslateBy(const BPoint& delta);
|
|
|
|
BAffineTransform TranslateByCopy(double x, double y) const;
|
|
BAffineTransform TranslateByCopy(const BPoint& delta) const;
|
|
|
|
// const BAffineTransform& SetTranslation(double x, double y);
|
|
|
|
// Rotation
|
|
inline const BAffineTransform& RotateBy(double angle);
|
|
const BAffineTransform& RotateBy(const BPoint& center,
|
|
double angle);
|
|
|
|
BAffineTransform RotateByCopy(double angle) const;
|
|
BAffineTransform RotateByCopy(const BPoint& center,
|
|
double angle) const;
|
|
|
|
// const BAffineTransform& SetRotation(double angle);
|
|
|
|
// Scaling
|
|
inline const BAffineTransform& ScaleBy(double scale);
|
|
const BAffineTransform& ScaleBy(const BPoint& center,
|
|
double scale);
|
|
inline const BAffineTransform& ScaleBy(double x, double y);
|
|
const BAffineTransform& ScaleBy(const BPoint& center, double x,
|
|
double y);
|
|
const BAffineTransform& ScaleBy(const BPoint& scale);
|
|
const BAffineTransform& ScaleBy(const BPoint& center,
|
|
const BPoint& scale);
|
|
|
|
BAffineTransform ScaleByCopy(double scale) const;
|
|
BAffineTransform ScaleByCopy(const BPoint& center,
|
|
double scale) const;
|
|
BAffineTransform ScaleByCopy(double x, double y) const;
|
|
BAffineTransform ScaleByCopy(const BPoint& center,
|
|
double x, double y) const;
|
|
BAffineTransform ScaleByCopy(const BPoint& scale) const;
|
|
BAffineTransform ScaleByCopy(const BPoint& center,
|
|
const BPoint& scale) const;
|
|
|
|
const BAffineTransform& SetScale(double scale);
|
|
const BAffineTransform& SetScale(double x, double y);
|
|
|
|
// Shearing
|
|
inline const BAffineTransform& ShearBy(double x, double y);
|
|
const BAffineTransform& ShearBy(const BPoint& center, double x,
|
|
double y);
|
|
const BAffineTransform& ShearBy(const BPoint& shear);
|
|
const BAffineTransform& ShearBy(const BPoint& center,
|
|
const BPoint& shear);
|
|
|
|
BAffineTransform ShearByCopy(double x, double y) const;
|
|
BAffineTransform ShearByCopy(const BPoint& center,
|
|
double x, double y) const;
|
|
BAffineTransform ShearByCopy(const BPoint& shear) const;
|
|
BAffineTransform ShearByCopy(const BPoint& center,
|
|
const BPoint& shear) const;
|
|
|
|
// const BAffineTransform& SetShear(double x, double y);
|
|
|
|
// Multiplication
|
|
inline const BAffineTransform& Multiply(const BAffineTransform& other);
|
|
const BAffineTransform& PreMultiply(const BAffineTransform& other);
|
|
inline const BAffineTransform& MultiplyInverse(
|
|
const BAffineTransform& other);
|
|
inline const BAffineTransform& PreMultiplyInverse(
|
|
const BAffineTransform& other);
|
|
|
|
// Operators
|
|
inline BAffineTransform& operator=(
|
|
const BAffineTransform& copyFrom);
|
|
|
|
inline bool operator==(
|
|
const BAffineTransform& other) const;
|
|
inline bool operator!=(
|
|
const BAffineTransform& other) const;
|
|
|
|
inline const BAffineTransform& operator*=(const BAffineTransform& other);
|
|
inline const BAffineTransform& operator/=(const BAffineTransform& other);
|
|
|
|
inline BAffineTransform operator*(
|
|
const BAffineTransform& other) const;
|
|
inline BAffineTransform operator/(
|
|
const BAffineTransform& other) const;
|
|
|
|
inline BAffineTransform operator~() const;
|
|
|
|
// Utility
|
|
bool IsValid(double epsilon
|
|
= kDefaultEpsilon) const;
|
|
bool IsIdentity(double epsilon
|
|
= kDefaultEpsilon) const;
|
|
bool IsEqual(const BAffineTransform& other,
|
|
double epsilon
|
|
= kDefaultEpsilon) const;
|
|
|
|
const BAffineTransform& Invert();
|
|
const BAffineTransform& FlipX();
|
|
const BAffineTransform& FlipY();
|
|
const BAffineTransform& Reset();
|
|
|
|
inline double Determinant() const;
|
|
inline double InverseDeterminant() const;
|
|
void GetTranslation(double* tx,
|
|
double* ty) const;
|
|
double Rotation() const;
|
|
double Scale() const;
|
|
void GetScale(double* sx, double* sy) const;
|
|
void GetScaleAbs(double* sx,
|
|
double* sy) const;
|
|
bool GetAffineParameters(double* translationX,
|
|
double* translationY, double* rotation,
|
|
double* scaleX, double* scaleY,
|
|
double* shearX, double* shearY) const;
|
|
|
|
public:
|
|
double sx;
|
|
double shy;
|
|
double shx;
|
|
double sy;
|
|
double tx;
|
|
double ty;
|
|
};
|
|
|
|
|
|
extern const BAffineTransform B_AFFINE_IDENTITY_TRANSFORM;
|
|
|
|
|
|
// #pragma mark - inline methods
|
|
|
|
|
|
inline void
|
|
BAffineTransform::Apply(double* x, double* y) const
|
|
{
|
|
register double tmp = *x;
|
|
*x = tmp * sx + *y * shx + tx;
|
|
*y = tmp * shy + *y * sy + ty;
|
|
}
|
|
|
|
|
|
inline void
|
|
BAffineTransform::ApplyInverse(double* x, double* y) const
|
|
{
|
|
register double d = InverseDeterminant();
|
|
register double a = (*x - tx) * d;
|
|
register double b = (*y - ty) * d;
|
|
*x = a * sy - b * shx;
|
|
*y = b * sx - a * shy;
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::TranslateBy(double x, double y)
|
|
{
|
|
tx += x;
|
|
ty += y;
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::RotateBy(double angle)
|
|
{
|
|
double ca = cos(angle);
|
|
double sa = sin(angle);
|
|
double t0 = sx * ca - shy * sa;
|
|
double t2 = shx * ca - sy * sa;
|
|
double t4 = tx * ca - ty * sa;
|
|
shy = sx * sa + shy * ca;
|
|
sy = shx * sa + sy * ca;
|
|
ty = tx * sa + ty * ca;
|
|
sx = t0;
|
|
shx = t2;
|
|
tx = t4;
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::ScaleBy(double x, double y)
|
|
{
|
|
double mm0 = x;
|
|
// Possible hint for the optimizer
|
|
double mm3 = y;
|
|
sx *= mm0;
|
|
shx *= mm0;
|
|
tx *= mm0;
|
|
shy *= mm3;
|
|
sy *= mm3;
|
|
ty *= mm3;
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::ScaleBy(double s)
|
|
{
|
|
double m = s;
|
|
// Possible hint for the optimizer
|
|
sx *= m;
|
|
shx *= m;
|
|
tx *= m;
|
|
shy *= m;
|
|
sy *= m;
|
|
ty *= m;
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::ShearBy(double x, double y)
|
|
{
|
|
BAffineTransform shearTransform = AffineShearing(x, y);
|
|
return PreMultiply(shearTransform);
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::Multiply(const BAffineTransform& other)
|
|
{
|
|
BAffineTransform t(other);
|
|
return *this = t.PreMultiply(*this);
|
|
}
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::MultiplyInverse(const BAffineTransform& other)
|
|
{
|
|
BAffineTransform t(other);
|
|
t.Invert();
|
|
return Multiply(t);
|
|
}
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::PreMultiplyInverse(const BAffineTransform& other)
|
|
{
|
|
BAffineTransform t(other);
|
|
t.Invert();
|
|
return *this = t.Multiply(*this);
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
inline BAffineTransform&
|
|
BAffineTransform::operator=(const BAffineTransform& other)
|
|
{
|
|
sx = other.sx;
|
|
shy = other.shy;
|
|
shx = other.shx;
|
|
sy = other.sy;
|
|
tx = other.tx;
|
|
ty = other.ty;
|
|
return *this;
|
|
}
|
|
|
|
inline bool
|
|
BAffineTransform::operator==(const BAffineTransform& other) const
|
|
{
|
|
return IsEqual(other);
|
|
}
|
|
|
|
inline bool
|
|
BAffineTransform::operator!=(const BAffineTransform& other) const
|
|
{
|
|
return !IsEqual(other);
|
|
}
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::operator*=(const BAffineTransform& other)
|
|
{
|
|
return Multiply(other);
|
|
}
|
|
|
|
|
|
inline const BAffineTransform&
|
|
BAffineTransform::operator/=(const BAffineTransform& other)
|
|
{
|
|
return MultiplyInverse(other);
|
|
}
|
|
|
|
|
|
inline BAffineTransform
|
|
BAffineTransform::operator*(const BAffineTransform& other) const
|
|
{
|
|
return BAffineTransform(*this).Multiply(other);
|
|
}
|
|
|
|
|
|
inline BAffineTransform
|
|
BAffineTransform::operator/(const BAffineTransform& other) const
|
|
{
|
|
return BAffineTransform(*this).MultiplyInverse(other);
|
|
}
|
|
|
|
|
|
inline BAffineTransform
|
|
BAffineTransform::operator~() const
|
|
{
|
|
BAffineTransform result(*this);
|
|
return result.Invert();
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
inline double
|
|
BAffineTransform::Determinant() const
|
|
{
|
|
return sx * sy - shy * shx;
|
|
}
|
|
|
|
|
|
inline double
|
|
BAffineTransform::InverseDeterminant() const
|
|
{
|
|
return 1.0 / (sx * sy - shy * shx);
|
|
}
|
|
|
|
|
|
#endif // _AFFINE_TRANSFORM_H
|