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