1583 lines
52 KiB
C++
1583 lines
52 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 "transform.h"
|
|
#include "base/constants.h"
|
|
|
|
namespace base
|
|
{
|
|
|
|
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}
|
|
};
|
|
|
|
|
|
pModifyFunDblToShort modifyDblToShortFunTbl[transformTypeMAX];
|
|
pModifyFunLongToShort modifyLongToShortFunTbl[transformTypeMAX];
|
|
pModifyFunIntToShort modifyIntToShortFunTbl[transformTypeMAX];
|
|
pModifyFunDblToInt modifyDblToIntFunTbl[transformTypeMAX];
|
|
pModifyFunDblToDbl modifyDblToDblFunTbl[transformTypeMAX];
|
|
pModifyFunLongToInt modifyLongToIntFunTbl[transformTypeMAX];
|
|
pModifyFunIntToInt modifyIntToIntFunTbl[transformTypeMAX];
|
|
pModifyFunLongToLong modifyLongToLongFunTbl[transformTypeMAX];
|
|
pModifyRectFunLongToLong modifyRectLongToLongFunTbl[transformTypeMAX];
|
|
pModifyRectFunDblToDbl modifyRectDblToDblFunTbl[transformTypeMAX];
|
|
pModifyRectFunIntToInt modifyRectIntToIntFunTbl[transformTypeMAX];
|
|
|
|
//
|
|
/// Table of inverse determining functions by transform type.
|
|
//
|
|
pGetInverseFun getInverseFnTbl[transformTypeMAX];
|
|
|
|
//
|
|
/// Table of multiplication determining functions by transform type.
|
|
//
|
|
pMultFun multFnTbl[transformTypeMAX*transformTypeMAX];
|
|
|
|
//
|
|
/// Modify a point using scale transform.
|
|
//
|
|
template <class iC,class oC>
|
|
pod::point<oC> GXX_HIDDEN modifyScale(
|
|
const transform & T, pod::point<iC> xy)
|
|
{
|
|
pod::point<double> tmp = xy % T.getDiagonal();
|
|
return std::tr1::is_floating_point<oC>::value ?
|
|
pod::point<oC>((oC)tmp.X(),(oC)tmp.Y())
|
|
:
|
|
pod::point<oC>((oC)base::round(tmp.X()),(oC)base::round(tmp.Y()));
|
|
}
|
|
//
|
|
/// Modify a point using scale and offset transform.
|
|
//
|
|
template <class iC,class oC>
|
|
pod::point<oC> GXX_HIDDEN modifyScaleOffset(
|
|
const transform & T, pod::point<iC> xy)
|
|
{
|
|
pod::point<double> tmp = xy % T.getDiagonal() + T.getOffset();
|
|
return std::tr1::is_floating_point<oC>::value ?
|
|
pod::point<oC>((oC)tmp.X(),(oC)tmp.Y())
|
|
:
|
|
pod::point<oC>((oC)base::round(tmp.X()),(oC)base::round(tmp.Y()));
|
|
}
|
|
//
|
|
/// Modify a point using a general transform.
|
|
//
|
|
template <class iC, class oC>
|
|
pod::point<oC> GXX_HIDDEN modifyGeneral( const transform & T, pod::point<iC> xy )
|
|
{
|
|
pod::point<double> tmp(T.getCol1()*pod::point<double>(xy),T.getCol2()*pod::point<double>(xy));
|
|
tmp += T.getOffset();
|
|
return std::tr1::is_floating_point<oC>::value ?
|
|
pod::point<oC>((oC)tmp.X(),(oC)tmp.Y())
|
|
:
|
|
pod::point<oC>((oC)base::round(tmp.X()),(oC)base::round(tmp.Y()));
|
|
}
|
|
|
|
template <class iC,class oC>
|
|
pod::point<oC> GXX_HIDDEN modifyStd ( const transform & T, pod::point<iC> xy )
|
|
{
|
|
//
|
|
// Transform the point.
|
|
//
|
|
pod::point<double> d = xy * T.getOrient() + T.getOffset();
|
|
//
|
|
// Convert to target coordinate type.
|
|
//
|
|
return std::tr1::is_floating_point<oC>::value ?
|
|
pod::point<oC>( (oC)(d.getX()), (oC)(d.getY()))
|
|
:
|
|
pod::point<oC>( (oC)base::round(d.getX()), (oC)base::round(d.getY()));
|
|
}
|
|
//
|
|
/// Modify a point using standard transform with magnification
|
|
//
|
|
template <class iC, class oC>
|
|
pod::point<oC> GXX_HIDDEN modifyStdMag( const transform &T, pod::point<iC> xy )
|
|
{
|
|
//
|
|
// Transform the point.
|
|
//
|
|
pod::point<double> d = xy * T.getOrient() * T.get11() + T.getOffset();
|
|
//
|
|
// Convert to target coordinate type.
|
|
//
|
|
return std::tr1::is_floating_point<oC>::value ?
|
|
pod::point<oC>( (oC)(d.getX()), (oC)(d.getY()))
|
|
:
|
|
pod::point<oC>( (oC)base::round(d.getX()), (oC)base::round(d.getY()));
|
|
}
|
|
//
|
|
/// Modify a point using resolution transform.
|
|
//
|
|
template <class iC, class oC>
|
|
pod::point<oC> GXX_HIDDEN modifyResolution( const transform &T, pod::point<iC> xy )
|
|
{
|
|
pod::point<double> tmp = xy % T.getDiagonal();
|
|
if (T.getNext()) {
|
|
if (std::tr1::is_double<oC>::value) {
|
|
pod::point<double> tmp2 = pod::point<double>((double)tmp.X(),
|
|
(double)tmp.Y());
|
|
return T.getNext()->modifyDblToDbl(tmp2);
|
|
} else if (std::tr1::is_long<oC>::value) {
|
|
pod::point<long> tmp2 = pod::point<long>((long)base::round(tmp.X()),
|
|
(long)base::round(tmp.Y()));
|
|
return T.getNext()->modifyLongToLong(tmp2);
|
|
} else if (std::tr1::is_int<oC>::value) {
|
|
pod::point<long> tmp2 = pod::point<long>((long)base::round(tmp.X()),
|
|
(long)base::round(tmp.Y()));
|
|
return T.getNext()->modifyLongToInt(tmp2);
|
|
} else if (std::tr1::is_short<oC>::value) {
|
|
pod::point<long> tmp2 = pod::point<long>((long)base::round(tmp.X()),
|
|
(long)base::round(tmp.Y()));
|
|
return T.getNext()->modifyLongToShort(tmp2);
|
|
}
|
|
} else
|
|
return std::tr1::is_floating_point<oC>::value ?
|
|
pod::point<oC>((oC)tmp.X(),(oC)tmp.Y()) :
|
|
pod::point<oC>((oC)base::round(tmp.X()),
|
|
(oC)base::round(tmp.Y()));
|
|
// Should not get here or something is missing.
|
|
throw except::programError();
|
|
return pod::point<oC>((oC)0, (oC)0);
|
|
}
|
|
//
|
|
// Modify a rectangle using scale transform.
|
|
//
|
|
template <class iC,class oC>
|
|
pod::rectangle<oC> GXX_HIDDEN modifyScaleRect(
|
|
const transform & T,
|
|
const pod::rectangle<iC> & r)
|
|
{
|
|
pod::rectangle<oC> rect(modifyScale<iC,oC>(T,r.getLowerLeft()),
|
|
modifyScale<iC,oC>(T,r.getUpperRight()));
|
|
rect.makeValid();
|
|
return rect;
|
|
}
|
|
//
|
|
// Modify a rectangle using scale and offset transform.
|
|
//
|
|
template <class iC,class oC>
|
|
pod::rectangle<oC> GXX_HIDDEN modifyScaleOffsetRect(
|
|
const transform & T,
|
|
const pod::rectangle<iC> & r)
|
|
{
|
|
pod::rectangle<oC> rect(modifyScaleOffset<iC,oC>(T,r.getLowerLeft()),
|
|
modifyScaleOffset<iC,oC>(T,r.getUpperRight()));
|
|
rect.makeValid();
|
|
return rect;
|
|
}
|
|
//
|
|
// Modify a rectangle using a general transform.
|
|
//
|
|
template <class iC, class oC>
|
|
pod::rectangle<oC> GXX_HIDDEN modifyGeneralRect(
|
|
const transform & T,
|
|
const pod::rectangle<iC> & r )
|
|
{
|
|
//
|
|
// We have to transform all four corner points when using a
|
|
// general transform in order to figure out what the new corner
|
|
// points will be.
|
|
//
|
|
pod::point<oC> p0 = modifyGeneral<iC,oC>(T,r.getLowerLeft());
|
|
pod::point<oC> p1 = modifyGeneral<iC,oC>(T,r.getLowerRight());
|
|
pod::point<oC> p2 = modifyGeneral<iC,oC>(T,r.getUpperRight());
|
|
pod::point<oC> p3 = modifyGeneral<iC,oC>(T,r.getUpperLeft());
|
|
pod::rectangle<oC> rect;
|
|
rect.merge(p0);
|
|
rect.merge(p1);
|
|
rect.merge(p2);
|
|
rect.merge(p3);
|
|
return rect;
|
|
}
|
|
|
|
template <class iC,class oC>
|
|
pod::rectangle<oC> GXX_HIDDEN modifyStdRect (
|
|
const transform & T,
|
|
const pod::rectangle<iC> & r )
|
|
{
|
|
pod::rectangle<oC> rect(modifyStd<iC,oC>(T,r.getLowerLeft()),
|
|
modifyStd<iC,oC>(T,r.getUpperRight()));
|
|
rect.makeValid();
|
|
return rect;
|
|
}
|
|
//
|
|
// Modify a rectangle using standard transform with magnification.
|
|
//
|
|
template <class iC, class oC>
|
|
pod::rectangle<oC> GXX_HIDDEN modifyStdMagRect(
|
|
const transform &T,
|
|
const pod::rectangle<iC> & r )
|
|
{
|
|
pod::rectangle<oC> rect(modifyStdMag<iC,oC>(T,r.getLowerLeft()),
|
|
modifyStdMag<iC,oC>(T,r.getUpperRight()));
|
|
rect.makeValid();
|
|
return rect;
|
|
}
|
|
//
|
|
// Modify a rectangle using resolution transform.
|
|
//
|
|
template <class iC,class oC>
|
|
pod::rectangle<oC> GXX_HIDDEN modifyResolutionRect(
|
|
const transform & T,
|
|
const pod::rectangle<iC> & r)
|
|
{
|
|
pod::rectangle<oC> rect(modifyResolution<iC,oC>(T,r.getLowerLeft()),
|
|
modifyResolution<iC,oC>(T,r.getUpperRight()));
|
|
rect.makeValid();
|
|
return rect;
|
|
}
|
|
|
|
//
|
|
/// Initialize the function tables.
|
|
//
|
|
void transform::initFnTables()
|
|
{
|
|
//
|
|
// double to short
|
|
//
|
|
modifyDblToShortFunTbl[ScaleOffsetTransformType] = &modifyScaleOffset<double,short>;
|
|
modifyDblToShortFunTbl[GeneralTransformType] = &modifyGeneral<double,short>;
|
|
modifyDblToShortFunTbl[StdTransformType] = &modifyStd<double,short>;
|
|
modifyDblToShortFunTbl[StdTransformWithMagType] = &modifyStdMag<double,short>;
|
|
modifyDblToShortFunTbl[ScaleTransformType] = &modifyScale<double,short>;
|
|
modifyDblToShortFunTbl[ResolutionTransformType] = &modifyResolution<double,short>;
|
|
//
|
|
// long to short
|
|
//
|
|
modifyLongToShortFunTbl[ScaleOffsetTransformType] = &modifyScaleOffset<long,short>;
|
|
modifyLongToShortFunTbl[GeneralTransformType] = &modifyGeneral<long,short>;
|
|
modifyLongToShortFunTbl[StdTransformType] = &modifyStd<long,short>;
|
|
modifyLongToShortFunTbl[StdTransformWithMagType] = &modifyStdMag<long,short>;
|
|
modifyLongToShortFunTbl[ScaleTransformType] = &modifyScale<long,short>;
|
|
modifyLongToShortFunTbl[ResolutionTransformType] = &modifyResolution<long,short>;
|
|
//
|
|
// int to short
|
|
//
|
|
modifyIntToShortFunTbl[ScaleOffsetTransformType] = &modifyScaleOffset<int,short>;
|
|
modifyIntToShortFunTbl[GeneralTransformType] = &modifyGeneral<int,short>;
|
|
modifyIntToShortFunTbl[StdTransformType] = &modifyStd<int,short>;
|
|
modifyIntToShortFunTbl[StdTransformWithMagType] = &modifyStdMag<int,short>;
|
|
modifyIntToShortFunTbl[ScaleTransformType] = &modifyScale<int,short>;
|
|
modifyIntToShortFunTbl[ResolutionTransformType] = &modifyResolution<int,short>;
|
|
//
|
|
// double to int
|
|
//
|
|
modifyDblToIntFunTbl[ScaleOffsetTransformType] = &modifyScaleOffset<double,int>;
|
|
modifyDblToIntFunTbl[GeneralTransformType] = &modifyGeneral<double,int>;
|
|
modifyDblToIntFunTbl[StdTransformType] = &modifyStd<double,int>;
|
|
modifyDblToIntFunTbl[StdTransformWithMagType] = &modifyStdMag<double,int>;
|
|
modifyDblToIntFunTbl[ScaleTransformType] = &modifyScale<double,int>;
|
|
modifyDblToIntFunTbl[ResolutionTransformType] = &modifyResolution<double,int>;
|
|
//
|
|
// double to double
|
|
//
|
|
modifyDblToDblFunTbl[ScaleOffsetTransformType] = &modifyScaleOffset<double,double>;
|
|
modifyDblToDblFunTbl[GeneralTransformType] = &modifyGeneral<double,double>;
|
|
modifyDblToDblFunTbl[StdTransformType] = &modifyStd<double,double>;
|
|
modifyDblToDblFunTbl[StdTransformWithMagType] = &modifyStdMag<double,double>;
|
|
modifyDblToDblFunTbl[ScaleTransformType] = &modifyScale<double,double>;
|
|
modifyDblToDblFunTbl[ResolutionTransformType] = &modifyResolution<double,double>;
|
|
//
|
|
// long to int
|
|
//
|
|
modifyLongToIntFunTbl[ScaleOffsetTransformType] = &modifyScaleOffset<long,int>;
|
|
modifyLongToIntFunTbl[GeneralTransformType] = &modifyGeneral<long,int>;
|
|
modifyLongToIntFunTbl[StdTransformType] = &modifyStd<long,int>;
|
|
modifyLongToIntFunTbl[StdTransformWithMagType] = &modifyStdMag<long,int>;
|
|
modifyLongToIntFunTbl[ScaleTransformType] = &modifyScale<long,int>;
|
|
modifyLongToIntFunTbl[ResolutionTransformType] = &modifyResolution<long,int>;
|
|
//
|
|
// int to int
|
|
//
|
|
modifyIntToIntFunTbl[ScaleOffsetTransformType] = &modifyScaleOffset<int,int>;
|
|
modifyIntToIntFunTbl[GeneralTransformType] = &modifyGeneral<int,int>;
|
|
modifyIntToIntFunTbl[StdTransformType] = &modifyStd<int,int>;
|
|
modifyIntToIntFunTbl[StdTransformWithMagType] = &modifyStdMag<int,int>;
|
|
modifyIntToIntFunTbl[ScaleTransformType] = &modifyScale<int,int>;
|
|
modifyIntToIntFunTbl[ResolutionTransformType] = &modifyResolution<int,int>;
|
|
//
|
|
// long to long
|
|
//
|
|
modifyLongToLongFunTbl[ScaleOffsetTransformType] = &modifyScaleOffset<long,long>;
|
|
modifyLongToLongFunTbl[GeneralTransformType] = &modifyGeneral<long,long>;
|
|
modifyLongToLongFunTbl[StdTransformType] = &modifyStd<long,long>;
|
|
modifyLongToLongFunTbl[StdTransformWithMagType] = &modifyStdMag<long,long>;
|
|
modifyLongToLongFunTbl[ScaleTransformType] = &modifyScale<long,long>;
|
|
modifyLongToLongFunTbl[ResolutionTransformType] = &modifyResolution<long,long>;
|
|
//
|
|
/// Init get inverse func table.
|
|
//
|
|
getInverseFnTbl[ScaleOffsetTransformType] = &getInverseScaleOffset;
|
|
getInverseFnTbl[GeneralTransformType] = &getInverseGeneral;
|
|
getInverseFnTbl[StdTransformType] = &getInverseStd;
|
|
getInverseFnTbl[StdTransformWithMagType] = &getInverseStdWithMag;
|
|
getInverseFnTbl[ScaleTransformType] = &getInverseScale;
|
|
getInverseFnTbl[ResolutionTransformType] = &getInverseResolution;
|
|
//
|
|
/// Init the multiply func table.
|
|
//
|
|
multFnTbl[0] = &multScaleOffsetXScaleOffset;
|
|
multFnTbl[1] = &multScaleOffsetXGeneral;
|
|
multFnTbl[2] = &multScaleOffsetXStd;
|
|
multFnTbl[3] = &multScaleOffsetXStdWithMag;
|
|
multFnTbl[4] = &multScaleOffsetXScaleOffset;
|
|
multFnTbl[5] = &multScaleOffsetXResolution;
|
|
multFnTbl[6] = &multGeneralXScaleOffset;
|
|
multFnTbl[7] = &multGeneralXGeneral;
|
|
multFnTbl[8] = &multGeneralXStd;
|
|
multFnTbl[9] = &multGeneralXStdWithMag;
|
|
multFnTbl[10] = &multGeneralXScaleOffset;
|
|
multFnTbl[11] = &multGeneralXResolution;
|
|
multFnTbl[12] = &multStdXScaleOffset;
|
|
multFnTbl[13] = &multStdXGeneral;
|
|
multFnTbl[14] = &multStdXStd;
|
|
multFnTbl[15] = &multStdXStdWithMag;
|
|
multFnTbl[16] = &multStdXScaleOffset;
|
|
multFnTbl[17] = &multStdXResolution;
|
|
multFnTbl[18] = &multStdWithMagXScaleOffset;
|
|
multFnTbl[19] = &multStdWithMagXGeneral;
|
|
multFnTbl[20] = &multStdWithMagXStd;
|
|
multFnTbl[21] = &multStdWithMagXStdWithMag;
|
|
multFnTbl[22] = &multStdWithMagXScaleOffset;
|
|
multFnTbl[23] = &multStdWithMagXResolution;
|
|
multFnTbl[24] = &multScaleOffsetXScaleOffset;
|
|
multFnTbl[25] = &multScaleOffsetXGeneral;
|
|
multFnTbl[26] = &multScaleOffsetXStd;
|
|
multFnTbl[27] = &multScaleOffsetXStdWithMag;
|
|
multFnTbl[28] = &multScaleXScale;
|
|
multFnTbl[29] = &multScaleXResolution;
|
|
multFnTbl[30] = &multResolutionXAny;
|
|
multFnTbl[31] = &multResolutionXAny;
|
|
multFnTbl[32] = &multResolutionXAny;
|
|
multFnTbl[33] = &multResolutionXAny;
|
|
multFnTbl[34] = &multResolutionXAny;
|
|
multFnTbl[35] = &multResolutionXAny;
|
|
//
|
|
// Initialize the rectangle modification function tables.
|
|
//
|
|
modifyRectLongToLongFunTbl[ScaleOffsetTransformType] = modifyScaleOffsetRect<long,long>;
|
|
modifyRectLongToLongFunTbl[GeneralTransformType] = modifyGeneralRect<long,long>;
|
|
modifyRectLongToLongFunTbl[StdTransformType] = modifyStdRect<long,long>;
|
|
modifyRectLongToLongFunTbl[StdTransformWithMagType] = modifyStdMagRect<long,long>;
|
|
modifyRectLongToLongFunTbl[ScaleTransformType] = modifyScaleRect<long,long>;
|
|
modifyRectLongToLongFunTbl[ResolutionTransformType] = modifyResolutionRect<long,long>;
|
|
|
|
modifyRectDblToDblFunTbl[ScaleOffsetTransformType] = modifyScaleOffsetRect<double,double>;
|
|
modifyRectDblToDblFunTbl[GeneralTransformType] = modifyGeneralRect<double,double>;
|
|
modifyRectDblToDblFunTbl[StdTransformType] = modifyStdRect<double,double>;
|
|
modifyRectDblToDblFunTbl[StdTransformWithMagType] = modifyStdMagRect<double,double>;
|
|
modifyRectDblToDblFunTbl[ScaleTransformType] = modifyScaleRect<double,double>;
|
|
modifyRectDblToDblFunTbl[ResolutionTransformType] = modifyResolutionRect<double,double>;
|
|
|
|
modifyRectIntToIntFunTbl[ScaleOffsetTransformType] = modifyScaleOffsetRect<int,int>;
|
|
modifyRectIntToIntFunTbl[GeneralTransformType] = modifyGeneralRect<int,int>;
|
|
modifyRectIntToIntFunTbl[StdTransformType] = modifyStdRect<int,int>;
|
|
modifyRectIntToIntFunTbl[StdTransformWithMagType] = modifyStdMagRect<int,int>;
|
|
modifyRectIntToIntFunTbl[ScaleTransformType] = modifyScaleRect<int,int>;
|
|
modifyRectIntToIntFunTbl[ResolutionTransformType] = modifyResolutionRect<int,int>;
|
|
}
|
|
|
|
// 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( type!=GeneralTransformType)
|
|
{
|
|
//
|
|
// standard orientation. Use table
|
|
//
|
|
int idx= (int) getOrient().getOri();
|
|
isXFlip= stdOrientXFlipAngValues[idx].xflip;
|
|
angle = stdOrientXFlipAngValues[idx].angle;
|
|
mag = a11;
|
|
}
|
|
else
|
|
{
|
|
// 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
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
//
|
|
/// 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);
|
|
}
|
|
}
|
|
//
|
|
/// This is a convinient function converting coordinate types without loss of precision.
|
|
//
|
|
/*!
|
|
We try to not loss precision and use available functionality
|
|
provided by transform maximally. This function does what
|
|
all modifyXxxxToYyyyy does and is very helpful in generic programming.
|
|
*/
|
|
template <class iC, class oC>
|
|
void transform::modify( const pod::point<iC>& rSrc, pod::point<oC>& rDest ) const
|
|
{
|
|
switch ( type )
|
|
{
|
|
case ScaleOffsetTransformType:
|
|
rDest = modifyScaleOffset<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case GeneralTransformType:
|
|
rDest = modifyGeneral<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case StdTransformType:
|
|
rDest = modifyStd<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case StdTransformWithMagType:
|
|
rDest = modifyStdMag<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case ScaleTransformType:
|
|
rDest = modifyScale<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case ResolutionTransformType:
|
|
rDest = modifyResolution<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
default:
|
|
throw except::outOfRange("base::modify: Unknown type.");
|
|
} // switch
|
|
}
|
|
|
|
//
|
|
/// This is pod::rectangle version of above function.
|
|
//
|
|
template <class iC, class oC>
|
|
void transform::modify( const pod::rectangle<iC>& rSrc, pod::rectangle<oC>& rDest ) const
|
|
{
|
|
switch ( type )
|
|
{
|
|
case ScaleOffsetTransformType:
|
|
rDest = modifyScaleOffsetRect<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case GeneralTransformType:
|
|
rDest = modifyGeneralRect<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case StdTransformType:
|
|
rDest = modifyStdRect<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case StdTransformWithMagType:
|
|
rDest = modifyStdMagRect<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case ScaleTransformType:
|
|
rDest = modifyScaleRect<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
case ResolutionTransformType:
|
|
rDest = modifyResolutionRect<iC,oC>( *this, rSrc );
|
|
break;
|
|
|
|
default:
|
|
throw except::outOfRange("base::modify: Unknown type.");
|
|
} // switch
|
|
}
|
|
|
|
//
|
|
/// Transform given bbox.
|
|
//
|
|
/*!
|
|
While we transform bbox, the usual approach of transforming
|
|
lower left and upper right is not satisfactory. In case of
|
|
rotations we need to transform and merge all four vertices
|
|
of bbox to get one of bbox rectangles of a shape which bbox we
|
|
want to transform. The bbox transformed this way will not be the
|
|
smallest bbox of the shape, yet at least this will be a bbox.
|
|
While if we use usual approach, then we will get (in case of rotation)
|
|
a rectangle that is not nessecarily a bbox of original shape.
|
|
|
|
The function also optimizes cases when transform has
|
|
only orthogonal transforms.
|
|
*/
|
|
template <class iC, class oC>
|
|
void transform::modifyBBox( const pod::rectangle<iC>& rSrc, pod::rectangle<oC>& rDest ) const
|
|
{
|
|
//
|
|
// If we have orthogonal transform?
|
|
// First check get12 since most of transform will
|
|
// have no rotation factor.
|
|
//
|
|
if ( !next && (get12() == 0 || get11() == 0))
|
|
modify( rSrc, rDest );
|
|
//
|
|
// General case.
|
|
//
|
|
else
|
|
{
|
|
rDest.makeInvalid();
|
|
pod::point<oC> tmp;
|
|
|
|
modify( rSrc.getLowerLeft(), tmp );
|
|
rDest.merge( tmp );
|
|
|
|
modify( rSrc.getLowerRight(), tmp );
|
|
rDest.merge( tmp );
|
|
|
|
modify( rSrc.getUpperLeft(), tmp );
|
|
rDest.merge( tmp );
|
|
|
|
modify( rSrc.getUpperRight(), tmp );
|
|
rDest.merge( tmp );
|
|
}
|
|
}
|
|
|
|
//
|
|
/// Print a transform, mainly for debug purpose.
|
|
//
|
|
void transform::print(FILE *outStream, const char *linePrefix) const
|
|
{
|
|
std::string str = (std::string)(*this);
|
|
fprintf(outStream, "%stype = %s.\n", linePrefix,
|
|
str.c_str());
|
|
if (getType() != ResolutionTransformType &&
|
|
getType() != ScaleTransformType) {
|
|
fprintf(outStream, "%stx = %f.\n", linePrefix, offset.X());
|
|
fprintf(outStream, "%sty = %f.\n", linePrefix, offset.Y());
|
|
}
|
|
switch(type) {
|
|
case ScaleOffsetTransformType:
|
|
case ScaleTransformType:
|
|
fprintf(outStream, "%sscaleX = %f.\n", linePrefix, a11);
|
|
fprintf(outStream, "%sscaleY = %f.\n", linePrefix, a22);
|
|
break;
|
|
|
|
case GeneralTransformType:
|
|
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);
|
|
break;
|
|
|
|
case StdTransformType:
|
|
str = (std::string)orient;
|
|
fprintf(outStream, "%sorient = %s.\n", linePrefix, str.c_str());
|
|
break;
|
|
|
|
case StdTransformWithMagType:
|
|
str = (std::string)orient;
|
|
fprintf(outStream, "%sorient = %s.\n", linePrefix, str.c_str());
|
|
fprintf(outStream, "%smag = %f.\n", linePrefix, a11);
|
|
break;
|
|
|
|
case ResolutionTransformType:
|
|
fprintf(outStream, "%sscale = %f.\n", linePrefix, a11);
|
|
if (next) {
|
|
std::string bfr(linePrefix);
|
|
bfr += " ";
|
|
next->print(outStream, bfr.c_str());
|
|
}
|
|
break;
|
|
|
|
default:
|
|
throw except::outOfRange("base::transform:print: Unknown type.");
|
|
} // switch
|
|
}
|
|
|
|
//
|
|
/// Convert a transform type to a string.
|
|
//
|
|
transform::operator std::string() const
|
|
{
|
|
switch(type) {
|
|
case ScaleOffsetTransformType:
|
|
return std::string("ScaleOffsetTransform");
|
|
break;
|
|
case GeneralTransformType:
|
|
return std::string("GeneralTransform");
|
|
break;
|
|
case StdTransformType:
|
|
return std::string("StdTransform");
|
|
break;
|
|
case StdTransformWithMagType:
|
|
return std::string("StdTransformWithMag");
|
|
break;
|
|
case ScaleTransformType:
|
|
return std::string("ScaleTransform");
|
|
break;
|
|
case ResolutionTransformType:
|
|
return std::string("ResolutionTransform");
|
|
break;
|
|
default:
|
|
throw except::outOfRange("base::transformTypeToString: Unknown type.");
|
|
} // switch
|
|
}
|
|
|
|
std::ostream & operator << (std::ostream & os, const transform & t)
|
|
{
|
|
os << "<transform ";
|
|
os << "type=\"" << (std::string)t << "\"";
|
|
if ( t.type == StdTransformType || t.type == StdTransformWithMagType )
|
|
os << " orientation=\"" << (std::string)t.getOrient() << "\"";
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* Instantiate template with some arguments.
|
|
*/
|
|
template void transform::modify<int,short>( const pod::point<int>&, pod::point<short>& ) const;
|
|
template void transform::modify<long,short>( const pod::point<long>&, pod::point<short>& ) const;
|
|
template void transform::modify<double,short>( const pod::point<double>&, pod::point<short>& ) const;
|
|
|
|
template void transform::modify<int,int>( const pod::point<int>&, pod::point<int>& ) const;
|
|
template void transform::modify<long,int>( const pod::point<long>&, pod::point<int>& ) const;
|
|
template void transform::modify<double,int>( const pod::point<double>&, pod::point<int>& ) const;
|
|
|
|
template void transform::modify<int,long>( const pod::point<int>&, pod::point<long>& ) const;
|
|
template void transform::modify<long,long>( const pod::point<long>&, pod::point<long>& ) const;
|
|
template void transform::modify<double,long>( const pod::point<double>&, pod::point<long>& ) const;
|
|
|
|
template void transform::modify<int,double>( const pod::point<int>&, pod::point<double>& ) const;
|
|
template void transform::modify<long,double>( const pod::point<long>&, pod::point<double>& ) const;
|
|
template void transform::modify<double,double>( const pod::point<double>&, pod::point<double>& ) const;
|
|
|
|
template void transform::modify<int,short>( const pod::rectangle<int>&, pod::rectangle<short>& ) const;
|
|
template void transform::modify<long,short>( const pod::rectangle<long>&, pod::rectangle<short>& ) const;
|
|
template void transform::modify<double,short>( const pod::rectangle<double>&, pod::rectangle<short>& ) const;
|
|
|
|
template void transform::modify<int,int>( const pod::rectangle<int>&, pod::rectangle<int>& ) const;
|
|
template void transform::modify<long,int>( const pod::rectangle<long>&, pod::rectangle<int>& ) const;
|
|
template void transform::modify<double,int>( const pod::rectangle<double>&, pod::rectangle<int>& ) const;
|
|
|
|
template void transform::modify<int,long>( const pod::rectangle<int>&, pod::rectangle<long>& ) const;
|
|
template void transform::modify<long,long>( const pod::rectangle<long>&, pod::rectangle<long>& ) const;
|
|
template void transform::modify<double,long>( const pod::rectangle<double>&, pod::rectangle<long>& ) const;
|
|
|
|
template void transform::modify<int,double>( const pod::rectangle<int>&, pod::rectangle<double>& ) const;
|
|
template void transform::modify<long,double>( const pod::rectangle<long>&, pod::rectangle<double>& ) const;
|
|
template void transform::modify<double,double>( const pod::rectangle<double>&, pod::rectangle<double>& ) const;
|
|
|
|
template void transform::modifyBBox<int,short>( const pod::rectangle<int>&, pod::rectangle<short>& ) const;
|
|
template void transform::modifyBBox<long,short>( const pod::rectangle<long>&, pod::rectangle<short>& ) const;
|
|
template void transform::modifyBBox<double,short>( const pod::rectangle<double>&, pod::rectangle<short>& ) const;
|
|
|
|
template void transform::modifyBBox<int,int>( const pod::rectangle<int>&, pod::rectangle<int>& ) const;
|
|
template void transform::modifyBBox<long,int>( const pod::rectangle<long>&, pod::rectangle<int>& ) const;
|
|
template void transform::modifyBBox<double,int>( const pod::rectangle<double>&, pod::rectangle<int>& ) const;
|
|
|
|
template void transform::modifyBBox<int,long>( const pod::rectangle<int>&, pod::rectangle<long>& ) const;
|
|
template void transform::modifyBBox<long,long>( const pod::rectangle<long>&, pod::rectangle<long>& ) const;
|
|
template void transform::modifyBBox<double,long>( const pod::rectangle<double>&, pod::rectangle<long>& ) const;
|
|
|
|
template void transform::modifyBBox<int,double>( const pod::rectangle<int>&, pod::rectangle<double>& ) const;
|
|
template void transform::modifyBBox<long,double>( const pod::rectangle<long>&, pod::rectangle<double>& ) const;
|
|
template void transform::modifyBBox<double,double>( const pod::rectangle<double>&, pod::rectangle<double>& ) const;
|
|
|
|
#if defined( _MSC_VER )
|
|
template void transform::modify<int64,short>( const pod::point<int64>&, pod::point<short>& ) const;
|
|
template void transform::modify<int64,int>( const pod::point<int64>&, pod::point<int>& ) const;
|
|
template void transform::modify<int64,long>( const pod::point<int64>&, pod::point<long>& ) const;
|
|
template void transform::modify<int64,double>( const pod::point<int64>&, pod::point<double>& ) const;
|
|
template void transform::modify<int,int64>( const pod::point<int>&, pod::point<int64>& ) const;
|
|
template void transform::modify<long,int64>( const pod::point<long>&, pod::point<int64>& ) const;
|
|
template void transform::modify<double,int64>( const pod::point<double>&, pod::point<int64>& ) const;
|
|
template void transform::modify<int64,int64>( const pod::point<int64>&, pod::point<int64>& ) const;
|
|
|
|
template void transform::modify<int64,short>( const pod::rectangle<int64>&, pod::rectangle<short>& ) const;
|
|
template void transform::modify<int64,int>( const pod::rectangle<int64>&, pod::rectangle<int>& ) const;
|
|
template void transform::modify<int64,long>( const pod::rectangle<int64>&, pod::rectangle<long>& ) const;
|
|
template void transform::modify<int64,double>( const pod::rectangle<int64>&, pod::rectangle<double>& ) const;
|
|
template void transform::modify<int,int64>( const pod::rectangle<int>&, pod::rectangle<int64>& ) const;
|
|
template void transform::modify<long,int64>( const pod::rectangle<long>&, pod::rectangle<int64>& ) const;
|
|
template void transform::modify<double,int64>( const pod::rectangle<double>&, pod::rectangle<int64>& ) const;
|
|
template void transform::modify<int64,int64>( const pod::rectangle<int64>&, pod::rectangle<int64>& ) const;
|
|
|
|
template void transform::modifyBBox<int64,short>( const pod::rectangle<int64>&, pod::rectangle<short>& ) const;
|
|
template void transform::modifyBBox<int64,int>( const pod::rectangle<int64>&, pod::rectangle<int>& ) const;
|
|
template void transform::modifyBBox<int64,long>( const pod::rectangle<int64>&, pod::rectangle<long>& ) const;
|
|
template void transform::modifyBBox<int64,double>( const pod::rectangle<int64>&, pod::rectangle<double>& ) const;
|
|
template void transform::modifyBBox<int,int64>( const pod::rectangle<int>&, pod::rectangle<int64>& ) const;
|
|
template void transform::modifyBBox<long,int64>( const pod::rectangle<long>&, pod::rectangle<int64>& ) const;
|
|
template void transform::modifyBBox<double,int64>( const pod::rectangle<double>&, pod::rectangle<int64>& ) const;
|
|
template void transform::modifyBBox<int64,int64>( const pod::rectangle<int64>&, pod::rectangle<int64>& ) const;
|
|
#endif
|
|
|
|
namespace transformTest
|
|
{
|
|
|
|
|
|
/// called by testGetAngleFlipMag()
|
|
bool testTran_(int idx, const transform& tr, bool xFlip0, double angle0, double mag0)
|
|
{
|
|
// Get angle/xflip/mag from tr
|
|
bool xFlip;
|
|
double angle, mag;
|
|
tr.getAngleFlipMag( angle,xFlip, mag);
|
|
|
|
// Compare
|
|
bool bFlp= xFlip == xFlip0;
|
|
bool bAng=(angle - angle0) < absTolerance &&
|
|
(angle0 -angle) < absTolerance ;
|
|
bool bMag= (mag - mag0) < absTolerance &&
|
|
(mag0 -mag) < absTolerance ;
|
|
|
|
// Print error message if there is different
|
|
if(!bFlp || !bAng || !bMag)
|
|
{
|
|
printf(" %-2d tr(xFlop=%s)",idx, (xFlip0?"T":"F"));
|
|
if(!bFlp)
|
|
printf("!= %s", (xFlip?"T":"F"));
|
|
|
|
printf(" (angle=%10.5f)", angle0) ;
|
|
if(!bAng)
|
|
printf("!= %10.5f", angle);
|
|
|
|
printf(" (mag=%5.3f)",mag0);
|
|
|
|
if(!bMag)
|
|
printf("!= %5.3f", mag);
|
|
printf("\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//
|
|
/// Function test getAngelFlipMag()
|
|
//
|
|
bool testGetAngleFlipMag()
|
|
{
|
|
struct { bool xFlip; double angle; double mag; } testData[]=
|
|
{ // xFlip Angle Max index
|
|
{false, 0, 1}, //0 standard Orientation
|
|
{false, 90, 1.1}, //1
|
|
{false, 180, 1.2}, //2
|
|
{false, 270, 1.3}, //3
|
|
{true, 0, 1.4}, //4
|
|
{true, 90, 1.5}, //5
|
|
{true, 180, 1.6}, //6
|
|
{true, 270, 1.7}, //7
|
|
{false, 23, 1.8}, //8 non-standard Orientation
|
|
{true, 23, 1.9}, //9
|
|
{false, 92, 2.1}, //10
|
|
{true, 92, 2.2}, //11
|
|
{false, 192, 2.3}, //12
|
|
{true, 192, 2.4}, //13
|
|
{false, 272, 2.5}, //14
|
|
{true, 272, 2.6} //15
|
|
};
|
|
const int dataCount=16;
|
|
int failCtr=0;
|
|
int i=0;
|
|
for( ;i < dataCount; i++)
|
|
{
|
|
// Construct transform
|
|
transform tr(0,0,
|
|
testData[i].xFlip,
|
|
testData[i].angle,
|
|
testData[i].mag);
|
|
if(! testTran_(i, tr, testData[i].xFlip, testData[i].angle, testData[i].mag))
|
|
failCtr++;
|
|
}
|
|
|
|
/// set a11, a12, a21, a22 directly
|
|
transform trR0(101,101, 1, 0, 0, 1);
|
|
transform trR90(101,101, 0, 1, -1, 0);
|
|
transform trR180(101,101, -1,0, 0, -1);
|
|
transform trR270(101,101, 0, -1, 1, 0);
|
|
|
|
transform XtrR0(101,101, 1, 0,0, -1);
|
|
transform XtrR90(101,101, 0, 1, 1, 0);
|
|
transform XtrR180(101,101, -1,0, 0, 1);
|
|
transform XtrR270(101,101, 0, -1, -1, 0);
|
|
|
|
if(!testTran_(i++, trR0, false, 0, 1)) failCtr++;
|
|
if(!testTran_(i++, trR90, false, 90, 1)) failCtr++;
|
|
if(!testTran_(i++, trR180, false, 180, 1)) failCtr++;
|
|
if(!testTran_(i++, trR270, false, 270, 1)) failCtr++;
|
|
if(!testTran_(i++, XtrR0, true, 0, 1)) failCtr++;
|
|
if(!testTran_(i++, XtrR90, true, 90, 1)) failCtr++;
|
|
if(!testTran_(i++, XtrR180,true, 180, 1)) failCtr++;
|
|
if(!testTran_(i++, XtrR270,true, 270, 1)) failCtr++;
|
|
|
|
|
|
// Print summary
|
|
printf("transformation::testGetAngleFlipMag() test:%s\n",
|
|
(failCtr >0 ? " failed":" passed"));
|
|
|
|
return failCtr==0;
|
|
}
|
|
|
|
|
|
};
|
|
|
|
}; // namespace base
|