summaryrefslogtreecommitdiff
path: root/basegfx/source/matrix
diff options
context:
space:
mode:
authorthb <thb@openoffice.org>2010-01-18 01:10:42 +0100
committerthb <thb@openoffice.org>2010-01-18 01:10:42 +0100
commitea48c18b848fed4d6504c956adeb3f24f05938ca (patch)
tree1eccf884707ec16e4dd74f8e83c74563e1539b34 /basegfx/source/matrix
parent1737f4d2fdba50a590f76631cd7ca7e762d18c35 (diff)
parent8765a3bf9f2926a50d0f644e4263782269abe023 (diff)
thbfixes10: merge with DEV300 m69
Diffstat (limited to 'basegfx/source/matrix')
-rw-r--r--basegfx/source/matrix/b2dhommatrix.cxx174
-rw-r--r--basegfx/source/matrix/b2dhommatrixtools.cxx333
2 files changed, 360 insertions, 147 deletions
diff --git a/basegfx/source/matrix/b2dhommatrix.cxx b/basegfx/source/matrix/b2dhommatrix.cxx
index 352113fa8ed3..a7777352effb 100644
--- a/basegfx/source/matrix/b2dhommatrix.cxx
+++ b/basegfx/source/matrix/b2dhommatrix.cxx
@@ -36,6 +36,9 @@
#include <hommatrixtemplate.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+///////////////////////////////////////////////////////////////////////////////
namespace basegfx
{
@@ -60,6 +63,17 @@ namespace basegfx
{
}
+ B2DHomMatrix::B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2)
+ : mpImpl( IdentityMatrix::get() ) // use common identity matrix, will be made unique with 1st set-call
+ {
+ mpImpl->set(0, 0, f_0x0);
+ mpImpl->set(0, 1, f_0x1);
+ mpImpl->set(0, 2, f_0x2);
+ mpImpl->set(1, 0, f_1x0);
+ mpImpl->set(1, 1, f_1x1);
+ mpImpl->set(1, 2, f_1x2);
+ }
+
B2DHomMatrix& B2DHomMatrix::operator=(const B2DHomMatrix& rMat)
{
mpImpl = rMat.mpImpl;
@@ -81,6 +95,16 @@ namespace basegfx
mpImpl->set(nRow, nColumn, fValue);
}
+ void B2DHomMatrix::set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2)
+ {
+ mpImpl->set(0, 0, f_0x0);
+ mpImpl->set(0, 1, f_0x1);
+ mpImpl->set(0, 2, f_0x2);
+ mpImpl->set(1, 0, f_1x0);
+ mpImpl->set(1, 1, f_1x1);
+ mpImpl->set(1, 2, f_1x2);
+ }
+
bool B2DHomMatrix::isLastLineDefault() const
{
return mpImpl->isLastLineDefault();
@@ -206,56 +230,9 @@ namespace basegfx
if(!fTools::equalZero(fRadiant))
{
double fSin(0.0);
- double fCos(0.0);
-
- // is the rotation angle an approximate multiple of pi/2?
- // If yes, force fSin/fCos to -1/0/1, to maintain
- // orthogonality (which might also be advantageous for the
- // other cases, but: for multiples of pi/2, the exact
- // values _can_ be attained. It would be largely
- // unintuitive, if a 180 degrees rotation would introduce
- // slight roundoff errors, instead of exactly mirroring
- // the coordinate system).
- if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
- {
- // determine quadrant
- const sal_Int32 nQuad(
- (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
- switch( nQuad )
- {
- case 0: // -2pi,0,2pi
- fSin = 0.0;
- fCos = 1.0;
- break;
-
- case 1: // -3/2pi,1/2pi
- fSin = 1.0;
- fCos = 0.0;
- break;
-
- case 2: // -pi,pi
- fSin = 0.0;
- fCos = -1.0;
- break;
-
- case 3: // -1/2pi,3/2pi
- fSin = -1.0;
- fCos = 0.0;
- break;
-
- default:
- OSL_ENSURE( false,
- "B2DHomMatrix::rotate(): Impossible case reached" );
- }
- }
- else
- {
- // TODO(P1): Maybe use glibc's sincos here (though
- // that's kinda non-portable...)
- fSin = sin(fRadiant);
- fCos = cos(fRadiant);
- }
+ double fCos(1.0);
+ tools::createSinCosOrthogonal(fSin, fCos, fRadiant);
Impl2DHomMatrix aRotMat;
aRotMat.set(0, 0, fCos);
@@ -474,104 +451,7 @@ namespace basegfx
return true;
}
-
-/* Old version: Used 3D decompose when shaer was involved and also a determinant test
- (but only in that case). Keeping as comment since it also worked and to allow a
- fallback in case the new version makes trouble somehow. Definitely missing in the 2nd
- case is the sign correction for Y-Scale, this would need to be added following the above
- pattern
-
- bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const
- {
- // when perspective is used, decompose is not made here
- if(!mpImpl->isLastLineDefault())
- return false;
-
- // test for rotation and shear
- if(fTools::equalZero(get(0, 1))
- && fTools::equalZero(get(1, 0)))
- {
- // no rotation and shear, direct value extraction
- rRotate = rShearX = 0.0;
-
- // copy scale values
- rScale.setX(get(0, 0));
- rScale.setY(get(1, 1));
-
- // copy translation values
- rTranslate.setX(get(0, 2));
- rTranslate.setY(get(1, 2));
-
- return true;
- }
- else
- {
- // test if shear is zero. That's the case, if the unit vectors in the matrix
- // are perpendicular -> scalar is zero
- const ::basegfx::B2DVector aUnitVecX(get(0, 0), get(1, 0));
- const ::basegfx::B2DVector aUnitVecY(get(0, 1), get(1, 1));
-
- if(fTools::equalZero(aUnitVecX.scalar(aUnitVecY)))
- {
- // no shear, direct value extraction
- rShearX = 0.0;
-
- // calculate rotation
- rShearX = 0.0;
- rRotate = atan2(aUnitVecX.getY(), aUnitVecX.getX());
-
- // calculate scale values
- rScale.setX(aUnitVecX.getLength());
- rScale.setY(aUnitVecY.getLength());
-
- // copy translation values
- rTranslate.setX(get(0, 2));
- rTranslate.setY(get(1, 2));
-
- return true;
- }
- else
- {
- // If determinant is zero, decomposition is not possible
- if(0.0 == determinant())
- return false;
-
- // copy 2x2 matrix and translate vector to 3x3 matrix
- ::basegfx::B3DHomMatrix a3DHomMat;
-
- a3DHomMat.set(0, 0, get(0, 0));
- a3DHomMat.set(0, 1, get(0, 1));
- a3DHomMat.set(1, 0, get(1, 0));
- a3DHomMat.set(1, 1, get(1, 1));
- a3DHomMat.set(0, 3, get(0, 2));
- a3DHomMat.set(1, 3, get(1, 2));
-
- ::basegfx::B3DTuple r3DScale, r3DTranslate, r3DRotate, r3DShear;
-
- if(a3DHomMat.decompose(r3DScale, r3DTranslate, r3DRotate, r3DShear))
- {
- // copy scale values
- rScale.setX(r3DScale.getX());
- rScale.setY(r3DScale.getY());
-
- // copy shear
- rShearX = r3DShear.getX();
-
- // copy rotate
- rRotate = r3DRotate.getZ();
-
- // copy translate
- rTranslate.setX(r3DTranslate.getX());
- rTranslate.setY(r3DTranslate.getY());
-
- return true;
- }
- }
- }
-
- return false;
- } */
-
} // end of namespace basegfx
+///////////////////////////////////////////////////////////////////////////////
// eof
diff --git a/basegfx/source/matrix/b2dhommatrixtools.cxx b/basegfx/source/matrix/b2dhommatrixtools.cxx
index 366a08a1d202..f3d483c976e5 100644
--- a/basegfx/source/matrix/b2dhommatrixtools.cxx
+++ b/basegfx/source/matrix/b2dhommatrixtools.cxx
@@ -66,6 +66,339 @@ namespace basegfx
return aStrBuf.makeStringAndClear();
}
+ namespace tools
+ {
+ void createSinCosOrthogonal(double& o_rSin, double& o_rCos, double fRadiant)
+ {
+ if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
+ {
+ // determine quadrant
+ const sal_Int32 nQuad(
+ (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
+ switch( nQuad )
+ {
+ case 0: // -2pi,0,2pi
+ o_rSin = 0.0;
+ o_rCos = 1.0;
+ break;
+
+ case 1: // -3/2pi,1/2pi
+ o_rSin = 1.0;
+ o_rCos = 0.0;
+ break;
+
+ case 2: // -pi,pi
+ o_rSin = 0.0;
+ o_rCos = -1.0;
+ break;
+
+ case 3: // -1/2pi,3/2pi
+ o_rSin = -1.0;
+ o_rCos = 0.0;
+ break;
+
+ default:
+ OSL_ENSURE( false, "createSinCos: Impossible case reached" );
+ }
+ }
+ else
+ {
+ // TODO(P1): Maybe use glibc's sincos here (though
+ // that's kinda non-portable...)
+ o_rSin = sin(fRadiant);
+ o_rCos = cos(fRadiant);
+ }
+ }
+
+ B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY)
+ {
+ B2DHomMatrix aRetval;
+ const double fOne(1.0);
+
+ if(!fTools::equal(fScaleX, fOne))
+ {
+ aRetval.set(0, 0, fScaleX);
+ }
+
+ if(!fTools::equal(fScaleY, fOne))
+ {
+ aRetval.set(1, 1, fScaleY);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createShearXB2DHomMatrix(double fShearX)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!fTools::equalZero(fShearX))
+ {
+ aRetval.set(0, 1, fShearX);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createShearYB2DHomMatrix(double fShearY)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!fTools::equalZero(fShearY))
+ {
+ aRetval.set(1, 0, fShearY);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createRotateB2DHomMatrix(double fRadiant)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!fTools::equalZero(fRadiant))
+ {
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+ aRetval.set(0, 0, fCos);
+ aRetval.set(1, 1, fCos);
+ aRetval.set(1, 0, fSin);
+ aRetval.set(0, 1, -fSin);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY)))
+ {
+ aRetval.set(0, 2, fTranslateX);
+ aRetval.set(1, 2, fTranslateY);
+ }
+
+ return aRetval;
+ }
+
+ B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(
+ double fScaleX, double fScaleY,
+ double fShearX,
+ double fRadiant,
+ double fTranslateX, double fTranslateY)
+ {
+ const double fOne(1.0);
+
+ if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne))
+ {
+ /// no scale, take shortcut
+ return createShearXRotateTranslateB2DHomMatrix(fShearX, fRadiant, fTranslateX, fTranslateY);
+ }
+ else
+ {
+ /// scale used
+ if(fTools::equalZero(fShearX))
+ {
+ /// no shear
+ if(fTools::equalZero(fRadiant))
+ {
+ /// no rotate, take shortcut
+ return createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, fTranslateX, fTranslateY);
+ }
+ else
+ {
+ /// rotate and scale used, no shear
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fCos * fScaleX,
+ /* Row 0, Column 1 */ fScaleY * -fSin,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ fSin * fScaleX,
+ /* Row 1, Column 1 */ fScaleY * fCos,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ else
+ {
+ /// scale and shear used
+ if(fTools::equalZero(fRadiant))
+ {
+ /// scale and shear, but no rotate
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fScaleX,
+ /* Row 0, Column 1 */ fScaleY * fShearX,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ 0.0,
+ /* Row 1, Column 1 */ fScaleY,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ else
+ {
+ /// scale, shear and rotate used
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fCos * fScaleX,
+ /* Row 0, Column 1 */ fScaleY * ((fCos * fShearX) - fSin),
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ fSin * fScaleX,
+ /* Row 1, Column 1 */ fScaleY * ((fSin * fShearX) + fCos),
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ }
+ }
+
+ B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(
+ double fShearX,
+ double fRadiant,
+ double fTranslateX, double fTranslateY)
+ {
+ if(fTools::equalZero(fShearX))
+ {
+ /// no shear
+ if(fTools::equalZero(fRadiant))
+ {
+ /// no shear, no rotate, take shortcut
+ return createTranslateB2DHomMatrix(fTranslateX, fTranslateY);
+ }
+ else
+ {
+ /// no shear, but rotate used
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fCos,
+ /* Row 0, Column 1 */ -fSin,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ fSin,
+ /* Row 1, Column 1 */ fCos,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ else
+ {
+ /// shear used
+ if(fTools::equalZero(fRadiant))
+ {
+ /// no rotate, but shear used
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ 1.0,
+ /* Row 0, Column 1 */ fShearX,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ 0.0,
+ /* Row 1, Column 1 */ 1.0,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ else
+ {
+ /// shear and rotate used
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fCos,
+ /* Row 0, Column 1 */ (fCos * fShearX) - fSin,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ fSin,
+ /* Row 1, Column 1 */ (fSin * fShearX) + fCos,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ }
+
+ B2DHomMatrix createScaleTranslateB2DHomMatrix(
+ double fScaleX, double fScaleY,
+ double fTranslateX, double fTranslateY)
+ {
+ const double fOne(1.0);
+
+ if(fTools::equal(fScaleX, fOne) && fTools::equal(fScaleY, fOne))
+ {
+ /// no scale, take shortcut
+ return createTranslateB2DHomMatrix(fTranslateX, fTranslateY);
+ }
+ else
+ {
+ /// scale used
+ if(fTools::equalZero(fTranslateX) && fTools::equalZero(fTranslateY))
+ {
+ /// no translate, but scale.
+ B2DHomMatrix aRetval;
+
+ aRetval.set(0, 0, fScaleX);
+ aRetval.set(1, 1, fScaleY);
+
+ return aRetval;
+ }
+ else
+ {
+ /// translate and scale
+ B2DHomMatrix aRetval(
+ /* Row 0, Column 0 */ fScaleX,
+ /* Row 0, Column 1 */ 0.0,
+ /* Row 0, Column 2 */ fTranslateX,
+ /* Row 1, Column 0 */ 0.0,
+ /* Row 1, Column 1 */ fScaleY,
+ /* Row 1, Column 2 */ fTranslateY);
+
+ return aRetval;
+ }
+ }
+ }
+
+ B2DHomMatrix createRotateAroundPoint(
+ double fPointX, double fPointY,
+ double fRadiant)
+ {
+ B2DHomMatrix aRetval;
+
+ if(!fTools::equalZero(fRadiant))
+ {
+ double fSin(0.0);
+ double fCos(1.0);
+
+ createSinCosOrthogonal(fSin, fCos, fRadiant);
+
+ aRetval.set3x2(
+ /* Row 0, Column 0 */ fCos,
+ /* Row 0, Column 1 */ -fSin,
+ /* Row 0, Column 2 */ (fPointX * (1.0 - fCos)) + (fSin * fPointY),
+ /* Row 1, Column 0 */ fSin,
+ /* Row 1, Column 1 */ fCos,
+ /* Row 1, Column 2 */ (fPointY * (1.0 - fCos)) - (fSin * fPointX));
+ }
+
+ return aRetval;
+ }
+ } // end of namespace tools
} // end of namespace basegfx
///////////////////////////////////////////////////////////////////////////////