Files
test/testTransform/transform2.cpp
2012-12-06 21:43:03 +04:00

846 lines
24 KiB
C++

/*
* 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<double> 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<double> 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<double>(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<double>(
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<double>( 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<double>(
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<double>(
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<double>( 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<double>( 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<double>( 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<double>( 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<double>( 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<double>( 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 << "<transform ";
os << ">" << std::endl;
os << "<matrix>" << std::endl;
os << t.getRow1();
os << t.getRow2();
os << "</matrix>" << std::endl;
os << "<offset>" << std::endl;
os << t.getOffset();
os << "</offset>" << std::endl;
os << "</transform>" << std::endl;
return os;
}
}; // namespace base