* Copyright 2006-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "ChannelTransform.h"
#include <math.h>
#include <stdio.h>
ChannelTransform::ChannelTransform()
:
Transformable(),
fPivot(0.0, 0.0),
fTranslation(0.0, 0.0),
fRotation(0.0),
fXScale(1.0),
fYScale(1.0)
{
}
ChannelTransform::ChannelTransform(const ChannelTransform& other)
:
Transformable(other),
fPivot(other.fPivot),
fTranslation(other.fTranslation),
fRotation(other.fRotation),
fXScale(other.fXScale),
fYScale(other.fYScale)
{
}
ChannelTransform::~ChannelTransform()
{
}
void
ChannelTransform::SetTransformation(const Transformable& other)
{
double tx;
double ty;
other.translation(&tx, &ty);
double rotation = agg::rad2deg(other.rotation());
double scaleX;
double scaleY;
other.scaling(&scaleX, &scaleY);
if (isnanf(tx) || isnanf(ty) || isnanf(scaleX) || isnanf(scaleY))
return;
SetTransformation(B_ORIGIN, BPoint(tx, ty), rotation, scaleX, scaleY);
}
void
ChannelTransform::SetTransformation(BPoint pivot, BPoint translation,
double rotation, double xScale, double yScale)
{
if (fTranslation != translation ||
fPivot != pivot ||
fRotation != rotation ||
fXScale != xScale ||
fYScale != yScale) {
fPivot = pivot;
fTranslation = translation;
fRotation = rotation;
fXScale = xScale;
fYScale = yScale;
_UpdateMatrix();
}
}
void
ChannelTransform::SetPivot(BPoint pivot)
{
if (pivot == fPivot)
return;
fPivot = pivot;
_UpdateMatrix();
}
void
ChannelTransform::TranslateBy(BPoint offset)
{
if (offset.x == 0.0 && offset.y == 0.0)
return;
fTranslation += offset;
_UpdateMatrix();
}
a combined local rotation and a translation.
*/
void
ChannelTransform::RotateBy(BPoint origin, double degrees)
{
if (degrees == 0.0)
return;
origin -= fPivot;
fRotation += degrees;
double xOffset = fTranslation.x - origin.x;
double yOffset = fTranslation.y - origin.y;
agg::trans_affine_rotation m(degrees * M_PI / 180.0);
m.transform(&xOffset, &yOffset);
fTranslation.x = origin.x + xOffset;
fTranslation.y = origin.y + yOffset;
_UpdateMatrix();
}
void
ChannelTransform::RotateBy(double degrees)
{
if (degrees == 0.0)
return;
fRotation += degrees;
_UpdateMatrix();
}
void
ChannelTransform::ScaleBy(BPoint origin, double xScale, double yScale)
{
if (xScale == 1.0 && yScale == 1.0)
return;
fXScale *= xScale;
fYScale *= yScale;
double xOffset = fTranslation.x - origin.x;
double yOffset = fTranslation.y - origin.y;
fTranslation.x = origin.x + (xOffset * xScale);
fTranslation.y = origin.y + (yOffset * yScale);
_UpdateMatrix();
}
void
ChannelTransform::ScaleBy(double xScale, double yScale)
{
if (xScale == 1.0 && yScale == 1.0)
return;
fXScale *= xScale;
fYScale *= yScale;
_UpdateMatrix();
}
void
ChannelTransform::SetTranslationAndScale(BPoint offset, double xScale,
double yScale)
{
if (fTranslation == offset && fXScale == xScale && fYScale == yScale)
return;
fTranslation = offset;
fXScale = xScale;
fYScale = yScale;
_UpdateMatrix();
}
void
ChannelTransform::Reset()
{
SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0);
}
ChannelTransform&
ChannelTransform::operator=(const ChannelTransform& other)
{
fTranslation = other.fTranslation;
fRotation = other.fRotation;
fXScale = other.fXScale;
fYScale = other.fYScale;
Transformable::operator=(other);
return *this;
}
void
ChannelTransform::_UpdateMatrix()
{
double xScale = fXScale;
if (xScale == 0.0)
xScale = 0.000001;
double yScale = fYScale;
if (yScale == 0.0)
yScale = 0.000001;
reset();
multiply(agg::trans_affine_translation(-fPivot.x, -fPivot.y));
multiply(agg::trans_affine_scaling(xScale, yScale));
multiply(agg::trans_affine_rotation(fRotation * M_PI / 180.0));
multiply(agg::trans_affine_translation(fPivot.x + fTranslation.x,
fPivot.y + fTranslation.y));
Update();
}