xref: /haiku/src/apps/icon-o-matic/transformable/ChannelTransform.cpp (revision 0e684ccfed8462d5e8647473765eafcf970899f6)
1*0e684ccfSStephan Aßmus /*
2*0e684ccfSStephan Aßmus  * Copyright 2006, Haiku.
3*0e684ccfSStephan Aßmus  * Distributed under the terms of the MIT License.
4*0e684ccfSStephan Aßmus  *
5*0e684ccfSStephan Aßmus  * Authors:
6*0e684ccfSStephan Aßmus  *		Stephan Aßmus <superstippi@gmx.de>
7*0e684ccfSStephan Aßmus  */
8*0e684ccfSStephan Aßmus 
9*0e684ccfSStephan Aßmus #include "ChannelTransform.h"
10*0e684ccfSStephan Aßmus 
11*0e684ccfSStephan Aßmus #include <stdio.h>
12*0e684ccfSStephan Aßmus 
13*0e684ccfSStephan Aßmus // constructor
14*0e684ccfSStephan Aßmus ChannelTransform::ChannelTransform()
15*0e684ccfSStephan Aßmus 	: Transformable(),
16*0e684ccfSStephan Aßmus 	  fPivot(0.0, 0.0),
17*0e684ccfSStephan Aßmus 	  fTranslation(0.0, 0.0),
18*0e684ccfSStephan Aßmus 	  fRotation(0.0),
19*0e684ccfSStephan Aßmus 	  fXScale(1.0),
20*0e684ccfSStephan Aßmus 	  fYScale(1.0)
21*0e684ccfSStephan Aßmus {
22*0e684ccfSStephan Aßmus }
23*0e684ccfSStephan Aßmus 
24*0e684ccfSStephan Aßmus // copy constructor
25*0e684ccfSStephan Aßmus ChannelTransform::ChannelTransform(const ChannelTransform& other)
26*0e684ccfSStephan Aßmus 	: Transformable(other),
27*0e684ccfSStephan Aßmus 	  fPivot(other.fPivot),
28*0e684ccfSStephan Aßmus 	  fTranslation(other.fTranslation),
29*0e684ccfSStephan Aßmus 	  fRotation(other.fRotation),
30*0e684ccfSStephan Aßmus 	  fXScale(other.fXScale),
31*0e684ccfSStephan Aßmus 	  fYScale(other.fYScale)
32*0e684ccfSStephan Aßmus {
33*0e684ccfSStephan Aßmus }
34*0e684ccfSStephan Aßmus 
35*0e684ccfSStephan Aßmus // destructor
36*0e684ccfSStephan Aßmus ChannelTransform::~ChannelTransform()
37*0e684ccfSStephan Aßmus {
38*0e684ccfSStephan Aßmus }
39*0e684ccfSStephan Aßmus 
40*0e684ccfSStephan Aßmus // SetTransformation
41*0e684ccfSStephan Aßmus void
42*0e684ccfSStephan Aßmus ChannelTransform::SetTransformation(BPoint pivot,
43*0e684ccfSStephan Aßmus 									 BPoint translation,
44*0e684ccfSStephan Aßmus 									 double rotation,
45*0e684ccfSStephan Aßmus 									 double xScale,
46*0e684ccfSStephan Aßmus 									 double yScale)
47*0e684ccfSStephan Aßmus {
48*0e684ccfSStephan Aßmus 	if (fTranslation != translation ||
49*0e684ccfSStephan Aßmus 		fPivot != pivot ||
50*0e684ccfSStephan Aßmus 		fRotation != rotation ||
51*0e684ccfSStephan Aßmus 		fXScale != xScale ||
52*0e684ccfSStephan Aßmus 		fYScale != yScale) {
53*0e684ccfSStephan Aßmus 
54*0e684ccfSStephan Aßmus 		fPivot = pivot;
55*0e684ccfSStephan Aßmus 		fTranslation = translation;
56*0e684ccfSStephan Aßmus 		fRotation = rotation;
57*0e684ccfSStephan Aßmus 		fXScale = xScale;
58*0e684ccfSStephan Aßmus 		fYScale = yScale;
59*0e684ccfSStephan Aßmus 
60*0e684ccfSStephan Aßmus 		_UpdateMatrix();
61*0e684ccfSStephan Aßmus 	}
62*0e684ccfSStephan Aßmus }
63*0e684ccfSStephan Aßmus 
64*0e684ccfSStephan Aßmus // SetPivot
65*0e684ccfSStephan Aßmus void
66*0e684ccfSStephan Aßmus ChannelTransform::SetPivot(BPoint pivot)
67*0e684ccfSStephan Aßmus {
68*0e684ccfSStephan Aßmus 	if (pivot == fPivot)
69*0e684ccfSStephan Aßmus 		return;
70*0e684ccfSStephan Aßmus 
71*0e684ccfSStephan Aßmus 	fPivot = pivot;
72*0e684ccfSStephan Aßmus 
73*0e684ccfSStephan Aßmus 	_UpdateMatrix();
74*0e684ccfSStephan Aßmus }
75*0e684ccfSStephan Aßmus 
76*0e684ccfSStephan Aßmus // TranslateBy
77*0e684ccfSStephan Aßmus void
78*0e684ccfSStephan Aßmus ChannelTransform::TranslateBy(BPoint offset)
79*0e684ccfSStephan Aßmus {
80*0e684ccfSStephan Aßmus 	if (offset.x == 0.0 && offset.y == 0.0)
81*0e684ccfSStephan Aßmus 		return;
82*0e684ccfSStephan Aßmus 
83*0e684ccfSStephan Aßmus 	fTranslation += offset;
84*0e684ccfSStephan Aßmus 
85*0e684ccfSStephan Aßmus 	_UpdateMatrix();
86*0e684ccfSStephan Aßmus }
87*0e684ccfSStephan Aßmus 
88*0e684ccfSStephan Aßmus // RotateBy
89*0e684ccfSStephan Aßmus //
90*0e684ccfSStephan Aßmus // converts a rotation in world coordinates into
91*0e684ccfSStephan Aßmus // a combined local rotation and a translation
92*0e684ccfSStephan Aßmus void
93*0e684ccfSStephan Aßmus ChannelTransform::RotateBy(BPoint origin, double degrees)
94*0e684ccfSStephan Aßmus {
95*0e684ccfSStephan Aßmus 	if (degrees == 0.0)
96*0e684ccfSStephan Aßmus 		return;
97*0e684ccfSStephan Aßmus 
98*0e684ccfSStephan Aßmus 	origin -= fPivot;
99*0e684ccfSStephan Aßmus 
100*0e684ccfSStephan Aßmus 	fRotation += degrees;
101*0e684ccfSStephan Aßmus 
102*0e684ccfSStephan Aßmus 	// rotate fTranslation
103*0e684ccfSStephan Aßmus 	double xOffset = fTranslation.x - origin.x;
104*0e684ccfSStephan Aßmus 	double yOffset = fTranslation.y - origin.y;
105*0e684ccfSStephan Aßmus 
106*0e684ccfSStephan Aßmus 	agg::trans_affine_rotation m(degrees * PI / 180.0);
107*0e684ccfSStephan Aßmus 	m.transform(&xOffset, &yOffset);
108*0e684ccfSStephan Aßmus 
109*0e684ccfSStephan Aßmus 	fTranslation.x = origin.x + xOffset;
110*0e684ccfSStephan Aßmus 	fTranslation.y = origin.y + yOffset;
111*0e684ccfSStephan Aßmus 
112*0e684ccfSStephan Aßmus 	_UpdateMatrix();
113*0e684ccfSStephan Aßmus }
114*0e684ccfSStephan Aßmus 
115*0e684ccfSStephan Aßmus 
116*0e684ccfSStephan Aßmus // RotateBy
117*0e684ccfSStephan Aßmus void
118*0e684ccfSStephan Aßmus ChannelTransform::RotateBy(double degrees)
119*0e684ccfSStephan Aßmus {
120*0e684ccfSStephan Aßmus 	if (degrees == 0.0)
121*0e684ccfSStephan Aßmus 		return;
122*0e684ccfSStephan Aßmus 
123*0e684ccfSStephan Aßmus 	fRotation += degrees;
124*0e684ccfSStephan Aßmus 
125*0e684ccfSStephan Aßmus 	_UpdateMatrix();
126*0e684ccfSStephan Aßmus }
127*0e684ccfSStephan Aßmus 
128*0e684ccfSStephan Aßmus //// ScaleBy
129*0e684ccfSStephan Aßmus ////
130*0e684ccfSStephan Aßmus //// converts a scalation in world coordinates into
131*0e684ccfSStephan Aßmus //// a combined local scalation and a translation
132*0e684ccfSStephan Aßmus //void
133*0e684ccfSStephan Aßmus //ChannelTransform::ScaleBy(BPoint origin, double xScale, double yScale)
134*0e684ccfSStephan Aßmus //{
135*0e684ccfSStephan Aßmus //	if (xScale == 1.0 && yScale == 1.0)
136*0e684ccfSStephan Aßmus //		return;
137*0e684ccfSStephan Aßmus //
138*0e684ccfSStephan Aßmus //	fXScale *= xScale;
139*0e684ccfSStephan Aßmus //	fYScale *= yScale;
140*0e684ccfSStephan Aßmus //
141*0e684ccfSStephan Aßmus //	// scale fTranslation
142*0e684ccfSStephan Aßmus //	double xOffset = fTranslation.x - origin.x;
143*0e684ccfSStephan Aßmus //	double yOffset = fTranslation.y - origin.y;
144*0e684ccfSStephan Aßmus //
145*0e684ccfSStephan Aßmus //	fTranslation.x = origin.x + (xOffset * xScale);
146*0e684ccfSStephan Aßmus //	fTranslation.y = origin.y + (yOffset * yScale);
147*0e684ccfSStephan Aßmus //
148*0e684ccfSStephan Aßmus //	_UpdateMatrix();
149*0e684ccfSStephan Aßmus //}
150*0e684ccfSStephan Aßmus 
151*0e684ccfSStephan Aßmus // ScaleBy
152*0e684ccfSStephan Aßmus void
153*0e684ccfSStephan Aßmus ChannelTransform::ScaleBy(double xScale, double yScale)
154*0e684ccfSStephan Aßmus {
155*0e684ccfSStephan Aßmus 	if (xScale == 1.0 && yScale == 1.0)
156*0e684ccfSStephan Aßmus 		return;
157*0e684ccfSStephan Aßmus 
158*0e684ccfSStephan Aßmus 	fXScale *= xScale;
159*0e684ccfSStephan Aßmus 	fYScale *= yScale;
160*0e684ccfSStephan Aßmus 
161*0e684ccfSStephan Aßmus 	_UpdateMatrix();
162*0e684ccfSStephan Aßmus }
163*0e684ccfSStephan Aßmus 
164*0e684ccfSStephan Aßmus // SetTranslationAndScale
165*0e684ccfSStephan Aßmus void
166*0e684ccfSStephan Aßmus ChannelTransform::SetTranslationAndScale(BPoint offset,
167*0e684ccfSStephan Aßmus 										  double xScale, double yScale)
168*0e684ccfSStephan Aßmus {
169*0e684ccfSStephan Aßmus 	if (fTranslation == offset && fXScale == xScale && fYScale == yScale)
170*0e684ccfSStephan Aßmus 		return;
171*0e684ccfSStephan Aßmus 
172*0e684ccfSStephan Aßmus 	fTranslation = offset;
173*0e684ccfSStephan Aßmus 
174*0e684ccfSStephan Aßmus 	fXScale = xScale;
175*0e684ccfSStephan Aßmus 	fYScale = yScale;
176*0e684ccfSStephan Aßmus 
177*0e684ccfSStephan Aßmus 	_UpdateMatrix();
178*0e684ccfSStephan Aßmus }
179*0e684ccfSStephan Aßmus 
180*0e684ccfSStephan Aßmus // Reset
181*0e684ccfSStephan Aßmus void
182*0e684ccfSStephan Aßmus ChannelTransform::Reset()
183*0e684ccfSStephan Aßmus {
184*0e684ccfSStephan Aßmus 	SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0);
185*0e684ccfSStephan Aßmus }
186*0e684ccfSStephan Aßmus 
187*0e684ccfSStephan Aßmus // =
188*0e684ccfSStephan Aßmus ChannelTransform&
189*0e684ccfSStephan Aßmus ChannelTransform::operator=(const ChannelTransform& other)
190*0e684ccfSStephan Aßmus {
191*0e684ccfSStephan Aßmus 	fTranslation = other.fTranslation;
192*0e684ccfSStephan Aßmus 	fRotation = other.fRotation;
193*0e684ccfSStephan Aßmus 	fXScale = other.fXScale;
194*0e684ccfSStephan Aßmus 	fYScale = other.fYScale;
195*0e684ccfSStephan Aßmus 
196*0e684ccfSStephan Aßmus 	Transformable::operator=(other);
197*0e684ccfSStephan Aßmus 
198*0e684ccfSStephan Aßmus 	return *this;
199*0e684ccfSStephan Aßmus }
200*0e684ccfSStephan Aßmus 
201*0e684ccfSStephan Aßmus // _UpdateMatrix
202*0e684ccfSStephan Aßmus void
203*0e684ccfSStephan Aßmus ChannelTransform::_UpdateMatrix()
204*0e684ccfSStephan Aßmus {
205*0e684ccfSStephan Aßmus 	// fix up scales in case any is zero
206*0e684ccfSStephan Aßmus 	double xScale = fXScale;
207*0e684ccfSStephan Aßmus 	if (xScale == 0.0)
208*0e684ccfSStephan Aßmus 		xScale = 0.000001;
209*0e684ccfSStephan Aßmus 	double yScale = fYScale;
210*0e684ccfSStephan Aßmus 	if (yScale == 0.0)
211*0e684ccfSStephan Aßmus 		yScale = 0.000001;
212*0e684ccfSStephan Aßmus 
213*0e684ccfSStephan Aßmus 	// start clean
214*0e684ccfSStephan Aßmus 	reset();
215*0e684ccfSStephan Aßmus 	// the "pivot" is like the offset from world to local
216*0e684ccfSStephan Aßmus 	// coordinate system and is the center for rotation and scale
217*0e684ccfSStephan Aßmus 	multiply(agg::trans_affine_translation(-fPivot.x, -fPivot.y));
218*0e684ccfSStephan Aßmus 	multiply(agg::trans_affine_scaling(xScale, yScale));
219*0e684ccfSStephan Aßmus 	multiply(agg::trans_affine_rotation(fRotation * PI / 180.0));
220*0e684ccfSStephan Aßmus 
221*0e684ccfSStephan Aßmus 	multiply(agg::trans_affine_translation(fPivot.x + fTranslation.x,
222*0e684ccfSStephan Aßmus 										   fPivot.y + fTranslation.y));
223*0e684ccfSStephan Aßmus 
224*0e684ccfSStephan Aßmus 	// call hook function
225*0e684ccfSStephan Aßmus 	Update();
226*0e684ccfSStephan Aßmus }
227*0e684ccfSStephan Aßmus 
228