/* * SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of Synopsys, * Inc., and is fully protected under copyright and trade secret laws. You may * not view, use, disclose, copy, or distribute this file or any information * contained herein except pursuant to a valid written license from Synopsys. */ #include "base/type-traits2.h" #include "ssetypes.h" #include "transform2.h" #include "base/constants.h" namespace base2 { #if 0 const stdOrientEnum inverseStdOrient[stdOrientMAX] = { R0, R270, R180, R90, XFlipR0, XFlipR90, XFlipR180, XFlipR270 }; /* In Aix64 platform char is by default unsigned this causes difference in values, ensuring signed char array */ const signed char stdOrientCoeffMatrix[stdOrientMAX][2][2] = { // /// R0: 0 degree rotation with no flip. /// Coefficients = | 1 0| /// | 0 1| // {{1, 0}, {0, 1}}, // /// R90: 90 degree rotation with no flip. /// Coefficients = | 0 1| /// |-1 0| // {{0, 1}, {-1, 0}}, // /// R180: 180 degree rotation with no flip. /// Coefficients = |-1 0| /// | 0 -1| // {{-1, 0}, {0, -1}}, // /// R270: 270 degree rotation with no flip. /// Coefficients = | 0 -1| /// | 1 0| // {{0, -1}, {1, 0}}, // /// XFlipR0: X flip followed by 0 degree rotation. /// Coefficients = | 1 0| /// | 0 -1| // {{1, 0}, {0, -1}}, // /// X flip followed by 90 degree rotation. /// Coefficients = | 0 1| /// | 1 0| // {{0, 1}, {1, 0}}, // /// X flip followed by 180 degree rotation. /// Coefficients = |-1 0| /// | 0 1| // {{-1, 0}, {0, 1}}, // /// X flip followed by 270 degree rotation. /// Coefficients = | 0 -1| /// |-1 0| // {{0, -1}, {-1, 0}} }; // /// Matrix for multiplying standard orientations. // const stdOrientEnum multStdOrientMatrix[stdOrientMAX][stdOrientMAX] = { // R0, R90, R180, R270, XFlipR0, XFlipR90, XFlipR180, XFlipR270 /* R0 */ { R0, R90, R180, R270, XFlipR0, XFlipR90, XFlipR180, XFlipR270}, /* R90 */ { R90, R180, R270, R0, XFlipR270, XFlipR0, XFlipR90, XFlipR180}, /* R180 */ { R180, R270, R0, R90, XFlipR180, XFlipR270, XFlipR0, XFlipR90}, /* R270 */ { R270, R0, R90, R180, XFlipR90, XFlipR180, XFlipR270, XFlipR0}, /* XFlipR0 */ { XFlipR0, XFlipR90, XFlipR180, XFlipR270, R0, R90, R180, R270}, /* XFlipR90 */ { XFlipR90, XFlipR180, XFlipR270, XFlipR0, R270, R0, R90, R180}, /* XFlipR180 */ { XFlipR180, XFlipR270, XFlipR0, XFlipR90, R180, R270, R0, R90}, /* XFlipR270 */ { XFlipR270, XFlipR0, XFlipR90, XFlipR180, R90, R180, R270, R0} } #endif // /// Initialize the function tables. // void transform::initFnTables() { } // Value of standard orientation const struct { bool xflip; double angle;} stdOrientXFlipAngValues[stdOrientMAX]= { {false, 0. }, // RO {false, 90. }, // R90 {false, 180. }, // R180 {false, 270. }, // R270 {true, 0. }, // XFlipR0 {true, 90. }, //XFlipR90 {true, 180. }, //XFlipR180 {true, 270. } //XFlipR270 }; const void transform::getAngleFlipMag( double& angle, bool& isXFlip, double& mag) const { #if 0 if( type!=GeneralTransformType) { // // standard orientation. Use table // int idx= (int) getOrient().getOri(); isXFlip= stdOrientXFlipAngValues[idx].xflip; angle = stdOrientXFlipAngValues[idx].angle; mag = a11; } else #endif { // From constructor // double multiplier = 1.0; // if (inXFlip == true) // multiplier = -1.0; // register double newAngle = degreesToRadians(normalizeAngle(inAngle)); // register double cosine = cos(newAngle); // register double sine = sin(newAngle); // a11 = inMag * cosine; // a12 = inMag * sine; // a21 = -inMag * multiplier * sine; // a22 = inMag * multiplier * cosine; // // How to get angle, inMage and inXFlip from a11, a12, a21, and a22 // Let sumProd = a11* a22 - a12*a21 // = (inMag*consine)(inMag * multiplier * cosine) - (inMag * sine)(-inMag * multiplier * sine) // = inMag*inMag*multiplier*consine*consine + inMag*inMag*multiplier*sine*sine // = inMag*inMag*multiplier(consine* consine + sine*sine) // = inMag*inMag*multiplier // // if( sumProd) < 0 ==> inXFlip=true // inMag= SquareRoot( Abs(sumPro)); // Angle= ArcCosine(a11/inMag) double sumProd= a11()*a22() - a12()*a21(); //get inXFlip. // sumProd= imMag*imMag*multiplier isXFlip= sumProd < 0; // get abs(imMag*imMag) if(sumProd<0) sumProd= -sumProd; // get mag mag= sqrt(sumProd); // get angle if(mag> 0) { double angleR= acos(a11()/mag); angle=radiansToDegrees(angleR); // aCos funciton range is 0 to 180. // We need to decide if angle is between 180 to 360 // // How to solve it // Let (Xt, Yt) is the point by applying (1,0) with transformation without xFlip, // if Yt > 0, then angle is located between 180 and 360 // // i.e. // | a11 a12 | x | 1 | = [a11 a21p ] = (Xt, Yt) // | a21p a22 | | 0 | // a21= multiplier * a21p = xFlip + angle // if a21p > 0 angle is located between 180 and 360 // double a21p= isXFlip? -a21(): a21(); if( a21p> 0 ) angle= 360. - angle; } else angle=0; }// end else } #if 0 transform transform::getInverseScaleOffset(const transform & T) { return transform( -T.offset.X()/T.a11, -T.offset.Y()/T.a22, 1.0/T.a11, 1.0/T.a22); } // /// Get the inverse of a general transform. // transform transform::getInverseGeneral(const transform & T ) { // // compute the determinant // double det = T.a11*T.a22 - T.a12*T.a21; return transform( (T.offset.Y()*T.a21 - T.offset.X()*T.a22)/det, (T.offset.X()*T.a12 - T.offset.Y()*T.a11)/det, T.a22/det, -T.a12/det, -T.a21/det, T.a11/det); } // /// Get the inverse of a standard transform. // transform transform::getInverseStd(const transform & T) { // // Transform the offset. // pod::point off = - T.offset * stdOrient(inverseStdOrient[T.orient.getOri()]); // // Return the inverted standard transform. // return transform (off.X(), off.Y(), inverseStdOrient[T.orient.getOri()]); } // /// Get the inverse of a standard transform with mag. // transform transform::getInverseStdWithMag(const transform & T) { register double oneOverMag = 1.0/T.a11; register stdOrientEnum e = inverseStdOrient[T.orient.getOri()]; // // Transform the offset. // pod::point off = - (T.offset * stdOrient(e)) * oneOverMag; return transform( off.X(), off.Y(), e, oneOverMag ); } // /// Get the inverse of a scale transform. // transform transform::getInverseScale(const transform & T) { return transform( 0.0, 0.0, 1.0/T.a11, 1.0/T.a22); } // // Get the inverse of a resolution transform. // transform transform::getInverseResolution(const transform & T) { if (T.next) { transform T1(T.a11, T.a22, false); transform T2; T1.mult(*(T.next), T2); return T2.getInverse(); } else { return transform(1.0/T.a11, 1.0/T.a22, false); } } #endif #if 0 // /// Multiply two scale transforms. // void transform::multScaleXScale(const transform &T1, const transform &T2, transform &outT) { outT.type = ScaleTransformType; outT.a11 = T1.a11*T2.a11; outT.a22 = T1.a22*T2.a22; outT.offset = pod::point(0.0, 0.0); } // /// Multiply a scale transform with a resolution transform. // void transform::multScaleXResolution(const transform &T1, const transform &T2, transform &outT) { outT.type = ResolutionTransformType; outT.a11 = T2.a11; outT.a12 = T2.a12; outT.a21 = T2.a21; outT.a22 = T2.a22; if (T2.next) { if (!outT.next) outT.next = new transform; transform tmp(T1.a11, T1.a22, false); tmp.mult(*(T2.next), *(outT.next)); } else { if (outT.next) { outT.next->type = ScaleTransformType; outT.next->a11 = T1.a11; outT.next->a12 = T1.a12; outT.next->a21 = T1.a21; outT.next->a22 = T1.a22; outT.next->offset.setX(0.0); outT.next->offset.setY(0.0); } else { outT.next = new transform(T1.a11, T1.a22, false); } } } // // /// Multiply two scale offset transforms. // void transform::multScaleOffsetXScaleOffset(const transform &T1, const transform &T2, transform &outT) { outT.type = ScaleOffsetTransformType; outT.a11 = T1.a11*T2.a11; outT.a22 = T1.a22*T2.a22; outT.offset = pod::point( T2.a11*T1.offset.X() + T2.offset.X(), T2.a22*T1.offset.Y() + T2.offset.Y()); } // /// Multiply a scale offset transform with a general transform. // void transform::multScaleOffsetXGeneral(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = T1.a11*T2.a11; outT.a12 = T1.a11*T2.a12; outT.a21 = T1.a22*T2.a21; outT.a22 = T1.a22*T2.a22; outT.offset = pod::point( T1.offset.X()*T2.a11 + T1.offset.Y()*T2.a21 + T2.offset.X(), T1.offset.X()*T2.a12 + T1.offset.Y()*T2.a22 + T2.offset.Y()); } // /// Multiply a scale offset transform with a standard transform. // void transform::multScaleOffsetXStd( const transform &T1, const transform &T2, transform &outT) { // // If we have uniform magnification, then we do not have to go to // a general transform. // if ( T1.a11 == T1.a22 ) { outT.type = StdTransformWithMagType; outT.orient = T2.orient; outT.a11 = T1.a11*T2.a11; } else { outT.type = GeneralTransformType; outT.a11 = T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][0]; outT.a12 = T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][1]; outT.a21 = T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]; outT.a22 = T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]; } outT.offset = pod::point( T1.offset.X()*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] + T1.offset.Y()*stdOrientCoeffMatrix[T2.orient.getOri()][1][0], T1.offset.X()*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] + T1.offset.Y()*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]) + T2.offset; } // /// Multiply a scale offset transform with a standard transform /// with magnification. // void transform::multScaleOffsetXStdWithMag( const transform &T1, const transform &T2, transform &outT) { // // If we have uniform magnification, then we do not have to go to // a general transform. // if ( T1.a11 == T1.a22 ) { outT.type = StdTransformWithMagType; outT.orient = T2.orient; outT.a11 = T1.a11*T2.a11; } else { outT.type = GeneralTransformType; outT.a11 = T1.a11*T2.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][0]; outT.a12 = T1.a11*T2.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][1]; outT.a21 = T1.a22*T2.a11*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]; outT.a22 = T1.a22*T2.a11*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]; } outT.offset = pod::point( T2.a11*(T1.offset.X()*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] + T1.offset.Y()*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]), T2.a11*(T1.offset.X()*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] + T1.offset.Y()*stdOrientCoeffMatrix[T2.orient.getOri()][1][1])) + T2.offset; } // /// Multiply a scale offset transform with a resolution transform. // void transform::multScaleOffsetXResolution(const transform &T1, const transform &T2, transform &outT) { outT.type = ResolutionTransformType; outT.a11 = T2.a11; outT.a12 = T2.a12; outT.a21 = T2.a21; outT.a22 = T2.a22; if (T2.next) { if (!outT.next) outT.next = new transform; transform tmp( T1.offset.getX()*T2.a11, T1.offset.getY()*T2.a22, T1.a11, T1.a22); tmp.mult(*(T2.next), *(outT.next)); } else { if (outT.next) { outT.next->type = ScaleOffsetTransformType; outT.next->a11 = T1.a11; outT.next->a12 = 0.0; outT.next->a21 = 0.0; outT.next->a22 = T1.a22; outT.next->offset.setX(T1.offset.getX()*T2.a11); outT.next->offset.setY(T1.offset.getY()*T2.a22); } else { outT.next = new transform( T1.offset.getX()*T2.a11, T1.offset.getY()*T2.a22, T1.a11, T1.a22); } } } // /// Multiply a general transform with a scale offset transform. // void transform::multGeneralXScaleOffset(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = T1.a11*T2.a11; outT.a12 = T1.a12*T2.a22; outT.a21 = T1.a21*T2.a11; outT.a22 = T1.a22*T2.a22; outT.offset = pod::point( T1.offset.X()*T2.a11, T1.offset.Y()*T2.a22) + T2.offset; } // /// Multiply two general transforms. // void transform::multGeneralXGeneral(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = T1.a11*T2.a11 + T1.a12*T2.a21; outT.a12 = T1.a11*T2.a12 + T1.a12*T2.a22; outT.a21 = T1.a21*T2.a11 + T1.a22*T2.a21; outT.a22 = T1.a21*T2.a12 + T1.a22*T2.a22; outT.offset = pod::point( T1.offset.X()*T2.a11 + T1.offset.Y()*T2.a21, T1.offset.X()*T2.a12 + T1.offset.Y()*T2.a22) + T2.offset; } // /// Multiply a general transform with a standard transform. // void transform::multGeneralXStd(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] + T1.a12*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]; outT.a12 = T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] + T1.a12*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]; outT.a21 = T1.a21*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] + T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]; outT.a22 = T1.a21*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] + T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]; // // Transform the offset. // outT.offset = T1.offset * T2.orient + T2.offset; } // /// Multiply a general transform with a standard transform /// with magnification. // void transform::multGeneralXStdWithMag(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = T2.a11*(T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] + T1.a12*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]); outT.a12 = T2.a11*(T1.a11*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] + T1.a12*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]); outT.a21 = T2.a11*(T1.a21*stdOrientCoeffMatrix[T2.orient.getOri()][0][0] + T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][0]); outT.a22 = T2.a11*(T1.a21*stdOrientCoeffMatrix[T2.orient.getOri()][0][1] + T1.a22*stdOrientCoeffMatrix[T2.orient.getOri()][1][1]); // // Transform the offset. // outT.offset = (T1.offset * T2.orient) * T2.a11 + T2.offset; } // /// Multiply a general transform with a resolution transform. // void transform::multGeneralXResolution(const transform &T1, const transform &T2, transform &outT) { outT.type = ResolutionTransformType; outT.a11 = T2.a11; outT.a12 = T2.a12; outT.a21 = T2.a21; outT.a22 = T2.a22; if (T2.next) { if (!outT.next) outT.next = new transform; transform tmp( T1.offset.getX()*T2.a11, T1.offset.getY()*T2.a22, T1.a11, T1.a12, T1.a21, T1.a22); tmp.mult(*(T2.next), *(outT.next)); } else { if (outT.next) { outT.next->type = GeneralTransformType; outT.next->a11 = T1.a11; outT.next->a22 = T1.a22; outT.next->a12 = T1.a12; outT.next->a21 = T1.a21; outT.next->offset.setX(T1.offset.getX()*T2.a11); outT.next->offset.setY(T1.offset.getY()*T2.a22); } else { outT.next = new transform( T1.offset.getX()*T2.a11, T1.offset.getY()*T2.a22, T1.a11, T1.a12, T1.a21, T1.a22); } } } // /// Multiply a standard transform with a scale and offset transform. // void transform::multStdXScaleOffset(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a11; outT.a12 = stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a22; outT.a21 = stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a11; outT.a22 = stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a22; // // Transform the offset. // outT.offset = pod::point( T1.offset.X()*T2.a11, T1.offset.Y()*T2.a22) + T2.offset; } // /// Multiply a standard transform with a general transform. // void transform::multStdXGeneral(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a11 + stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a21; outT.a12 = stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a12 + stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a22; outT.a21 = stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a11 + stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a21; outT.a22 = stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a12 + stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a22; // // Transform the offset. // outT.offset = pod::point( T1.offset.X()*T2.a11 + T1.offset.Y()*T2.a21, T1.offset.X()*T2.a12 + T1.offset.Y()*T2.a22) + T2.offset; } // /// Multiply two standard transforms. // void transform::multStdXStd(const transform &T1, const transform &T2, transform &outT) { outT.type = StdTransformType; outT.orient = multStdOrientMatrix[T1.orient.getOri()][T2.orient.getOri()]; // // Transform the offset. // outT.offset = T1.offset * T2.orient + T2.offset; } // /// Multiply a standard transform with a standard transform /// with magnification. // void transform::multStdXStdWithMag(const transform &T1, const transform &T2, transform &outT) { outT.type = StdTransformWithMagType; outT.orient = stdOrient(multStdOrientMatrix[T1.orient.getOri()][T2.orient.getOri()]); outT.a11 = T2.a11; // // Transform the offset. // outT.offset = T1.offset * T2.orient * T2.a11 + T2.offset; } // /// Multiply a standard transform with a resolution transform. // void transform::multStdXResolution(const transform &T1, const transform &T2, transform &outT) { outT.type = ResolutionTransformType; outT.a11 = T2.a11; outT.a12 = T2.a12; outT.a21 = T2.a21; outT.a22 = T2.a22; if (T2.next) { if (!outT.next) outT.next = new transform; transform tmp( T1.offset.getX()*T2.a11, T1.offset.getY()*T2.a22, T1.orient.getOri()); tmp.mult(*(T2.next), *(outT.next)); } else if (outT.next) { outT.next->type = StdTransformType; outT.next->a11 = T1.a11; outT.next->a12 = T1.a12; outT.next->a21 = T1.a21; outT.next->a22 = T1.a22; outT.next->offset.setX(T1.offset.getX()*T2.a11); outT.next->offset.setY(T1.offset.getY()*T2.a22); outT.next->orient = T1.orient; } else { outT.next = new transform( T1.offset.getX()*T2.a11, T1.offset.getY()*T2.a22, T1.orient.getOri()); } } // /// Multiply a standard transform with magnification with a /// scale and offset transform. // void transform::multStdWithMagXScaleOffset(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = T1.a11*stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a11; outT.a12 = T1.a11*stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a22; outT.a21 = T1.a11*stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a11; outT.a22 = T1.a11*stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a22; // // Transform the offset. // outT.offset = pod::point( T1.offset.X()*T2.a11, T1.offset.Y()*T2.a22) + T2.offset; } // /// Multiply a standard transform with magnification with /// a general transform. // void transform::multStdWithMagXGeneral(const transform &T1, const transform &T2, transform &outT) { outT.type = GeneralTransformType; outT.a11 = T1.a11*( stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a11 + stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a21); outT.a12 = T1.a11*( stdOrientCoeffMatrix[T1.orient.getOri()][0][0]*T2.a12 + stdOrientCoeffMatrix[T1.orient.getOri()][0][1]*T2.a22); outT.a21 = T1.a11*( stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a11 + stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a21); outT.a22 = T1.a11*( stdOrientCoeffMatrix[T1.orient.getOri()][1][0]*T2.a12 + stdOrientCoeffMatrix[T1.orient.getOri()][1][1]*T2.a22); // // Transfomr the offset. // outT.offset = pod::point( T1.offset.X()*T2.a11 + T1.offset.Y()*T2.a21, T1.offset.X()*T2.a12 + T1.offset.Y()*T2.a22) + T2.offset; } // /// Multiply a standard transform with magnification with /// a standard transform. // void transform::multStdWithMagXStd(const transform &T1, const transform &T2, transform &outT) { outT.type = StdTransformWithMagType; outT.orient = stdOrient(multStdOrientMatrix[T1.orient.getOri()][T2.orient.getOri()]); outT.a11 = T1.a11; // // Transform the offset. // outT.offset = T1.offset * T2.orient + T2.offset; } // /// Multiply two standard transforms with magnification. // void transform::multStdWithMagXStdWithMag(const transform &T1, const transform &T2, transform &outT) { outT.type = StdTransformWithMagType; outT.orient = stdOrient(multStdOrientMatrix[T1.orient.getOri()][T2.orient.getOri()]); outT.a11 = T1.a11*T2.a11; // // Transform the offset. // outT.offset = T1.offset * T2.orient * T2.a11 + T2.offset; } // /// Multiply a standard transform with magnification with a /// resolution transform. // void transform::multStdWithMagXResolution(const transform &T1, const transform &T2, transform &outT) { outT.type = ResolutionTransformType; outT.a11 = T2.a11; outT.a12 = T2.a12; outT.a21 = T2.a21; outT.a22 = T2.a22; if (T2.next) { if (!outT.next) outT.next = new transform; transform tmp( T1.offset.getX()*T2.a11, T1.offset.getY()*T2.a22, T1.orient.getOri(), T1.a11); tmp.mult(*(T2.next), *(outT.next)); } else { if (outT.next) { outT.next->type = StdTransformWithMagType; outT.next->a11 = T1.a11; outT.next->a12 = T1.a12; outT.next->a21 = T1.a21; outT.next->a22 = T1.a22; outT.next->offset.setX(T1.offset.getX()*T2.a11); outT.next->offset.setY(T1.offset.getY()*T2.a22); outT.next->orient = T1.orient; } else { outT.next = new transform( T1.offset.getX()*T2.a11, T1.offset.getY()*T2.a22, T1.orient.getOri(), T1.a11); } } } // /// Multiply a resolution transform with any transform. // void transform::multResolutionXAny(const transform &T1, const transform &T2, transform &outT) { outT.type = ResolutionTransformType; outT.a11 = T1.a11; outT.a12 = T1.a12; outT.a21 = T1.a21; outT.a22 = T1.a22; if(T1.next) { if (!(outT.next)) outT.next = new transform; T1.next->mult(T2, *(outT.next)); } else { outT.next = new transform(T2); } } #endif // /// Print a transform, mainly for debug purpose. // void transform::print(FILE *outStream, const char *linePrefix) const { fprintf(outStream, "%sa11 = %f.\n", linePrefix, a11() ); fprintf(outStream, "%sa12 = %f.\n", linePrefix, a12() ); fprintf(outStream, "%sa21 = %f.\n", linePrefix, a21() ); fprintf(outStream, "%sa22 = %f.\n", linePrefix, a22() ); fprintf(outStream, "%stx = %f.\n", linePrefix, offset_x() ); fprintf(outStream, "%sty = %f.\n", linePrefix, offset_y() ); } std::ostream & operator << (std::ostream & os, const transform & t) { os << "" << std::endl; os << "" << std::endl; os << t.getRow1(); os << t.getRow2(); os << "" << std::endl; os << "" << std::endl; os << t.getOffset(); os << "" << std::endl; os << "" << std::endl; return os; } }; // namespace base