initial check in
This commit is contained in:
845
testTransform/transform2.cpp
Normal file
845
testTransform/transform2.cpp
Normal file
@@ -0,0 +1,845 @@
|
||||
/*
|
||||
* 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
|
||||
Reference in New Issue
Block a user