xref: /haiku/src/apps/icon-o-matic/transformable/ChannelTransform.cpp (revision 14d604ddfa3cc7dc7a5a5c92e03e17956239f06b)
10e684ccfSStephan Aßmus /*
27f5bbbdcSAxel Dörfler  * Copyright 2006-2009, Haiku.
30e684ccfSStephan Aßmus  * Distributed under the terms of the MIT License.
40e684ccfSStephan Aßmus  *
50e684ccfSStephan Aßmus  * Authors:
60e684ccfSStephan Aßmus  *		Stephan Aßmus <superstippi@gmx.de>
70e684ccfSStephan Aßmus  */
80e684ccfSStephan Aßmus 
90e684ccfSStephan Aßmus #include "ChannelTransform.h"
100e684ccfSStephan Aßmus 
110e1ba39fSStephan Aßmus #include <math.h>
120e684ccfSStephan Aßmus #include <stdio.h>
130e684ccfSStephan Aßmus 
147f5bbbdcSAxel Dörfler 
150e684ccfSStephan Aßmus // constructor
ChannelTransform()160e684ccfSStephan Aßmus ChannelTransform::ChannelTransform()
177f5bbbdcSAxel Dörfler 	:
187f5bbbdcSAxel Dörfler 	Transformable(),
190e684ccfSStephan Aßmus 	fPivot(0.0, 0.0),
200e684ccfSStephan Aßmus 	fTranslation(0.0, 0.0),
210e684ccfSStephan Aßmus 	fRotation(0.0),
220e684ccfSStephan Aßmus 	fXScale(1.0),
230e684ccfSStephan Aßmus 	fYScale(1.0)
240e684ccfSStephan Aßmus {
250e684ccfSStephan Aßmus }
260e684ccfSStephan Aßmus 
270e684ccfSStephan Aßmus // copy constructor
ChannelTransform(const ChannelTransform & other)280e684ccfSStephan Aßmus ChannelTransform::ChannelTransform(const ChannelTransform& other)
297f5bbbdcSAxel Dörfler 	:
307f5bbbdcSAxel Dörfler 	Transformable(other),
310e684ccfSStephan Aßmus 	fPivot(other.fPivot),
320e684ccfSStephan Aßmus 	fTranslation(other.fTranslation),
330e684ccfSStephan Aßmus 	fRotation(other.fRotation),
340e684ccfSStephan Aßmus 	fXScale(other.fXScale),
350e684ccfSStephan Aßmus 	fYScale(other.fYScale)
360e684ccfSStephan Aßmus {
370e684ccfSStephan Aßmus }
380e684ccfSStephan Aßmus 
397f5bbbdcSAxel Dörfler 
400e684ccfSStephan Aßmus // destructor
~ChannelTransform()410e684ccfSStephan Aßmus ChannelTransform::~ChannelTransform()
420e684ccfSStephan Aßmus {
430e684ccfSStephan Aßmus }
440e684ccfSStephan Aßmus 
457f5bbbdcSAxel Dörfler 
460e684ccfSStephan Aßmus // SetTransformation
470e684ccfSStephan Aßmus void
SetTransformation(const Transformable & other)480e1ba39fSStephan Aßmus ChannelTransform::SetTransformation(const Transformable& other)
490e1ba39fSStephan Aßmus {
500e1ba39fSStephan Aßmus 	// calc affine parameters
510e1ba39fSStephan Aßmus 
520e1ba39fSStephan Aßmus 	// translation
530e1ba39fSStephan Aßmus 	double tx;
540e1ba39fSStephan Aßmus 	double ty;
550e1ba39fSStephan Aßmus 	other.translation(&tx, &ty);
560e1ba39fSStephan Aßmus 
570e1ba39fSStephan Aßmus 	// rotation
580e1ba39fSStephan Aßmus 	double rotation = agg::rad2deg(other.rotation());
590e1ba39fSStephan Aßmus 
600e1ba39fSStephan Aßmus 	// scale
610e1ba39fSStephan Aßmus 	double scaleX;
620e1ba39fSStephan Aßmus 	double scaleY;
630e1ba39fSStephan Aßmus 	other.scaling(&scaleX, &scaleY);
640e1ba39fSStephan Aßmus 
650e1ba39fSStephan Aßmus 	if (isnanf(tx) || isnanf(ty) || isnanf(scaleX) || isnanf(scaleY))
660e1ba39fSStephan Aßmus 		return;
670e1ba39fSStephan Aßmus 
680e1ba39fSStephan Aßmus 	SetTransformation(B_ORIGIN, BPoint(tx, ty), rotation, scaleX, scaleY);
690e1ba39fSStephan Aßmus }
700e1ba39fSStephan Aßmus 
717f5bbbdcSAxel Dörfler 
720e1ba39fSStephan Aßmus // SetTransformation
730e1ba39fSStephan Aßmus void
SetTransformation(BPoint pivot,BPoint translation,double rotation,double xScale,double yScale)747f5bbbdcSAxel Dörfler ChannelTransform::SetTransformation(BPoint pivot, BPoint translation,
757f5bbbdcSAxel Dörfler 	double rotation, double xScale, double yScale)
760e684ccfSStephan Aßmus {
770e1ba39fSStephan Aßmus //printf("SetTransformation(BPoint(%.1f, %.1f), BPoint(%.1f, %.1f), "
780e1ba39fSStephan Aßmus //"%.2f, %.2f, %.2f)\n", pivot.x, pivot.y, translation.x, translation.y,
790e1ba39fSStephan Aßmus //rotation, xScale, yScale);
800e1ba39fSStephan Aßmus 
810e684ccfSStephan Aßmus 	if (fTranslation != translation ||
820e684ccfSStephan Aßmus 		fPivot != pivot ||
830e684ccfSStephan Aßmus 		fRotation != rotation ||
840e684ccfSStephan Aßmus 		fXScale != xScale ||
850e684ccfSStephan Aßmus 		fYScale != yScale) {
860e684ccfSStephan Aßmus 
870e684ccfSStephan Aßmus 		fPivot = pivot;
880e684ccfSStephan Aßmus 		fTranslation = translation;
890e684ccfSStephan Aßmus 		fRotation = rotation;
900e684ccfSStephan Aßmus 		fXScale = xScale;
910e684ccfSStephan Aßmus 		fYScale = yScale;
920e684ccfSStephan Aßmus 
930e684ccfSStephan Aßmus 		_UpdateMatrix();
940e684ccfSStephan Aßmus 	}
950e684ccfSStephan Aßmus }
960e684ccfSStephan Aßmus 
977f5bbbdcSAxel Dörfler 
980e684ccfSStephan Aßmus // SetPivot
990e684ccfSStephan Aßmus void
SetPivot(BPoint pivot)1000e684ccfSStephan Aßmus ChannelTransform::SetPivot(BPoint pivot)
1010e684ccfSStephan Aßmus {
1020e684ccfSStephan Aßmus 	if (pivot == fPivot)
1030e684ccfSStephan Aßmus 		return;
1040e684ccfSStephan Aßmus 
1050e684ccfSStephan Aßmus 	fPivot = pivot;
1060e684ccfSStephan Aßmus 
1070e684ccfSStephan Aßmus 	_UpdateMatrix();
1080e684ccfSStephan Aßmus }
1090e684ccfSStephan Aßmus 
1107f5bbbdcSAxel Dörfler 
1110e684ccfSStephan Aßmus // TranslateBy
1120e684ccfSStephan Aßmus void
TranslateBy(BPoint offset)1130e684ccfSStephan Aßmus ChannelTransform::TranslateBy(BPoint offset)
1140e684ccfSStephan Aßmus {
1150e684ccfSStephan Aßmus 	if (offset.x == 0.0 && offset.y == 0.0)
1160e684ccfSStephan Aßmus 		return;
1170e684ccfSStephan Aßmus 
1180e684ccfSStephan Aßmus 	fTranslation += offset;
1190e684ccfSStephan Aßmus 
1200e684ccfSStephan Aßmus 	_UpdateMatrix();
1210e684ccfSStephan Aßmus }
1220e684ccfSStephan Aßmus 
1237f5bbbdcSAxel Dörfler 
1240e684ccfSStephan Aßmus // RotateBy
1257f5bbbdcSAxel Dörfler /*!	Converts a rotation in world coordinates into
1267f5bbbdcSAxel Dörfler 	a combined local rotation and a translation.
1277f5bbbdcSAxel Dörfler */
1280e684ccfSStephan Aßmus void
RotateBy(BPoint origin,double degrees)1290e684ccfSStephan Aßmus ChannelTransform::RotateBy(BPoint origin, double degrees)
1300e684ccfSStephan Aßmus {
1310e684ccfSStephan Aßmus 	if (degrees == 0.0)
1320e684ccfSStephan Aßmus 		return;
1330e684ccfSStephan Aßmus 
1340e684ccfSStephan Aßmus 	origin -= fPivot;
1350e684ccfSStephan Aßmus 
1360e684ccfSStephan Aßmus 	fRotation += degrees;
1370e684ccfSStephan Aßmus 
1380e684ccfSStephan Aßmus 	// rotate fTranslation
1390e684ccfSStephan Aßmus 	double xOffset = fTranslation.x - origin.x;
1400e684ccfSStephan Aßmus 	double yOffset = fTranslation.y - origin.y;
1410e684ccfSStephan Aßmus 
1427f5bbbdcSAxel Dörfler 	agg::trans_affine_rotation m(degrees * M_PI / 180.0);
1430e684ccfSStephan Aßmus 	m.transform(&xOffset, &yOffset);
1440e684ccfSStephan Aßmus 
1450e684ccfSStephan Aßmus 	fTranslation.x = origin.x + xOffset;
1460e684ccfSStephan Aßmus 	fTranslation.y = origin.y + yOffset;
1470e684ccfSStephan Aßmus 
1480e684ccfSStephan Aßmus 	_UpdateMatrix();
1490e684ccfSStephan Aßmus }
1500e684ccfSStephan Aßmus 
1510e684ccfSStephan Aßmus 
1520e684ccfSStephan Aßmus // RotateBy
1530e684ccfSStephan Aßmus void
RotateBy(double degrees)1540e684ccfSStephan Aßmus ChannelTransform::RotateBy(double degrees)
1550e684ccfSStephan Aßmus {
1560e684ccfSStephan Aßmus 	if (degrees == 0.0)
1570e684ccfSStephan Aßmus 		return;
1580e684ccfSStephan Aßmus 
1590e684ccfSStephan Aßmus 	fRotation += degrees;
1600e684ccfSStephan Aßmus 
1610e684ccfSStephan Aßmus 	_UpdateMatrix();
1620e684ccfSStephan Aßmus }
1630e684ccfSStephan Aßmus 
1647f5bbbdcSAxel Dörfler 
165*14d604ddSStephan Aßmus // ScaleBy
1660e684ccfSStephan Aßmus //
167*14d604ddSStephan Aßmus // converts a scalation in world coordinates into
168*14d604ddSStephan Aßmus // a combined local scalation and a translation
169*14d604ddSStephan Aßmus void
ScaleBy(BPoint origin,double xScale,double yScale)170*14d604ddSStephan Aßmus ChannelTransform::ScaleBy(BPoint origin, double xScale, double yScale)
171*14d604ddSStephan Aßmus {
172*14d604ddSStephan Aßmus 	// TODO: Untested?
173*14d604ddSStephan Aßmus 	if (xScale == 1.0 && yScale == 1.0)
174*14d604ddSStephan Aßmus 		return;
175*14d604ddSStephan Aßmus 
176*14d604ddSStephan Aßmus 	fXScale *= xScale;
177*14d604ddSStephan Aßmus 	fYScale *= yScale;
178*14d604ddSStephan Aßmus 
179*14d604ddSStephan Aßmus 	// scale fTranslation
180*14d604ddSStephan Aßmus 	double xOffset = fTranslation.x - origin.x;
181*14d604ddSStephan Aßmus 	double yOffset = fTranslation.y - origin.y;
182*14d604ddSStephan Aßmus 
183*14d604ddSStephan Aßmus 	fTranslation.x = origin.x + (xOffset * xScale);
184*14d604ddSStephan Aßmus 	fTranslation.y = origin.y + (yOffset * yScale);
185*14d604ddSStephan Aßmus 
186*14d604ddSStephan Aßmus 	_UpdateMatrix();
187*14d604ddSStephan Aßmus }
1880e684ccfSStephan Aßmus 
1890e684ccfSStephan Aßmus // ScaleBy
1900e684ccfSStephan Aßmus void
ScaleBy(double xScale,double yScale)1910e684ccfSStephan Aßmus ChannelTransform::ScaleBy(double xScale, double yScale)
1920e684ccfSStephan Aßmus {
1930e684ccfSStephan Aßmus 	if (xScale == 1.0 && yScale == 1.0)
1940e684ccfSStephan Aßmus 		return;
1950e684ccfSStephan Aßmus 
1960e684ccfSStephan Aßmus 	fXScale *= xScale;
1970e684ccfSStephan Aßmus 	fYScale *= yScale;
1980e684ccfSStephan Aßmus 
1990e684ccfSStephan Aßmus 	_UpdateMatrix();
2000e684ccfSStephan Aßmus }
2010e684ccfSStephan Aßmus 
2027f5bbbdcSAxel Dörfler 
2030e684ccfSStephan Aßmus // SetTranslationAndScale
2040e684ccfSStephan Aßmus void
SetTranslationAndScale(BPoint offset,double xScale,double yScale)2057f5bbbdcSAxel Dörfler ChannelTransform::SetTranslationAndScale(BPoint offset, double xScale,
2067f5bbbdcSAxel Dörfler 	double yScale)
2070e684ccfSStephan Aßmus {
2080e684ccfSStephan Aßmus 	if (fTranslation == offset && fXScale == xScale && fYScale == yScale)
2090e684ccfSStephan Aßmus 		return;
2100e684ccfSStephan Aßmus 
2110e684ccfSStephan Aßmus 	fTranslation = offset;
2120e684ccfSStephan Aßmus 
2130e684ccfSStephan Aßmus 	fXScale = xScale;
2140e684ccfSStephan Aßmus 	fYScale = yScale;
2150e684ccfSStephan Aßmus 
2160e684ccfSStephan Aßmus 	_UpdateMatrix();
2170e684ccfSStephan Aßmus }
2180e684ccfSStephan Aßmus 
2197f5bbbdcSAxel Dörfler 
2200e684ccfSStephan Aßmus // Reset
2210e684ccfSStephan Aßmus void
Reset()2220e684ccfSStephan Aßmus ChannelTransform::Reset()
2230e684ccfSStephan Aßmus {
2240e684ccfSStephan Aßmus 	SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0);
2250e684ccfSStephan Aßmus }
2260e684ccfSStephan Aßmus 
2277f5bbbdcSAxel Dörfler 
2280e684ccfSStephan Aßmus // =
2290e684ccfSStephan Aßmus ChannelTransform&
operator =(const ChannelTransform & other)2300e684ccfSStephan Aßmus ChannelTransform::operator=(const ChannelTransform& other)
2310e684ccfSStephan Aßmus {
2320e684ccfSStephan Aßmus 	fTranslation = other.fTranslation;
2330e684ccfSStephan Aßmus 	fRotation = other.fRotation;
2340e684ccfSStephan Aßmus 	fXScale = other.fXScale;
2350e684ccfSStephan Aßmus 	fYScale = other.fYScale;
2360e684ccfSStephan Aßmus 
2370e684ccfSStephan Aßmus 	Transformable::operator=(other);
2380e684ccfSStephan Aßmus 
2390e684ccfSStephan Aßmus 	return *this;
2400e684ccfSStephan Aßmus }
2410e684ccfSStephan Aßmus 
2427f5bbbdcSAxel Dörfler 
2430e684ccfSStephan Aßmus // _UpdateMatrix
2440e684ccfSStephan Aßmus void
_UpdateMatrix()2450e684ccfSStephan Aßmus ChannelTransform::_UpdateMatrix()
2460e684ccfSStephan Aßmus {
2470e684ccfSStephan Aßmus 	// fix up scales in case any is zero
2480e684ccfSStephan Aßmus 	double xScale = fXScale;
2490e684ccfSStephan Aßmus 	if (xScale == 0.0)
2500e684ccfSStephan Aßmus 		xScale = 0.000001;
2510e684ccfSStephan Aßmus 	double yScale = fYScale;
2520e684ccfSStephan Aßmus 	if (yScale == 0.0)
2530e684ccfSStephan Aßmus 		yScale = 0.000001;
2540e684ccfSStephan Aßmus 
2550e684ccfSStephan Aßmus 	// start clean
2560e684ccfSStephan Aßmus 	reset();
2570e684ccfSStephan Aßmus 	// the "pivot" is like the offset from world to local
2580e684ccfSStephan Aßmus 	// coordinate system and is the center for rotation and scale
2590e684ccfSStephan Aßmus 	multiply(agg::trans_affine_translation(-fPivot.x, -fPivot.y));
2600e684ccfSStephan Aßmus 	multiply(agg::trans_affine_scaling(xScale, yScale));
2617f5bbbdcSAxel Dörfler 	multiply(agg::trans_affine_rotation(fRotation * M_PI / 180.0));
2620e684ccfSStephan Aßmus 
2630e684ccfSStephan Aßmus 	multiply(agg::trans_affine_translation(fPivot.x + fTranslation.x,
2640e684ccfSStephan Aßmus 		fPivot.y + fTranslation.y));
2650e684ccfSStephan Aßmus 
2660e684ccfSStephan Aßmus 	// call hook function
2670e684ccfSStephan Aßmus 	Update();
2680e684ccfSStephan Aßmus }
2690e684ccfSStephan Aßmus 
270