diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /include/basegfx/matrix | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/basegfx/matrix')
-rw-r--r-- | include/basegfx/matrix/b2dhommatrix.hxx | 158 | ||||
-rw-r--r-- | include/basegfx/matrix/b2dhommatrixtools.hxx | 218 | ||||
-rw-r--r-- | include/basegfx/matrix/b3dhommatrix.hxx | 127 | ||||
-rw-r--r-- | include/basegfx/matrix/b3dhommatrixtools.hxx | 44 | ||||
-rw-r--r-- | include/basegfx/matrix/hommatrixtemplate.hxx | 427 |
5 files changed, 974 insertions, 0 deletions
diff --git a/include/basegfx/matrix/b2dhommatrix.hxx b/include/basegfx/matrix/b2dhommatrix.hxx new file mode 100644 index 0000000000..8067b8e1c6 --- /dev/null +++ b/include/basegfx/matrix/b2dhommatrix.hxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <ostream> + +#include <sal/types.h> +#include <basegfx/basegfxdllapi.h> +#include <array> + +namespace basegfx +{ + class B2DTuple; + + class SAL_WARN_UNUSED BASEGFX_DLLPUBLIC B2DHomMatrix + { + private: + // Since this is a graphics matrix, the last row is always 0 0 1, so we don't bother to store it. + std::array<std::array<double, 3>, 2> mfValues { + std::array<double, 3>{ 1.0, 0.0, 0.0 }, + std::array<double, 3>{ 0.0, 1.0, 0.0 } }; + + public: + constexpr B2DHomMatrix() = default; + + /** constructor to allow setting all needed values for a 3x2 matrix at once. The + parameter f_0x1 e.g. is the same as using set(0, 1, f) + */ + constexpr B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2) + { + mfValues[0][0] = f_0x0; + mfValues[0][1] = f_0x1; + mfValues[0][2] = f_0x2; + mfValues[1][0] = f_1x0; + mfValues[1][1] = f_1x1; + mfValues[1][2] = f_1x2; + } + + /** Convenience creator for declaration of the matrix that is commonly + used by web standards (SVG, CSS, HTML). + + Values a,b,c,d,e,f represent the following values in the matrix: + [a,c,e] [a,c,e] + [b,d,f] or [b,d,f] + [0,0,1] + + */ + static B2DHomMatrix abcdef(double da, double db, double dc, double dd, double de, double df) + { + return B2DHomMatrix(da, dc, de, db, dd, df); + } + + // Convenience accessor for value at 0,0 position in the matrix + double a() const { return get(0,0); } + // Convenience accessor for value at 1,0 position in the matrix + double b() const { return get(1,0); } + // Convenience accessor for value at 0,1 position in the matrix + double c() const { return get(0,1); } + // Convenience accessor for value at 1,1 position in the matrix + double d() const { return get(1,1); } + // Convenience accessor for value at 0,2 position in the matrix + double e() const { return get(0,2); } + // Convenience accessor for value at 1,2 position in the matrix + double f() const { return get(1,2); } + + double get(sal_uInt16 nRow, sal_uInt16 nColumn) const + { + return mfValues[nRow][nColumn]; + } + + void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue) + { + mfValues[nRow][nColumn] = fValue; + } + + /** allow setting all needed values for a 3x2 matrix in one call. The + parameter f_0x1 e.g. is the same as using set(0, 1, f) + */ + void set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2); + + // reset to a standard matrix + bool isIdentity() const; + void identity(); + + bool isInvertible() const; + bool invert(); + + void rotate(double fRadiant); + + void translate(double fX, double fY); + void translate(const B2DTuple& rTuple); + + void scale(double fX, double fY); + void scale(const B2DTuple& rTuple); + + // Shearing-Matrices + void shearX(double fSx); + void shearY(double fSy); + + bool operator==(const B2DHomMatrix& rMat) const; + bool operator!=(const B2DHomMatrix& rMat) const; + + // matrix multiplication from the left to the local + B2DHomMatrix& operator*=(const B2DHomMatrix& rMat); + + /** + * Help routine to decompose given homogen 3x3 matrix to components. A correction of the + * components is done to avoid inaccuracies. + * + * See basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix() for the opposite, to + * compose a homogen 3x3 matrix from components. + */ + bool decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const; + + private: + void computeAdjoint(double (&dst)[6]) const; + double computeDeterminant(double (&dst)[6]) const; + void doMulMatrix(const B2DHomMatrix& rMat); + }; + + inline B2DHomMatrix operator*(const B2DHomMatrix& rMatA, const B2DHomMatrix& rMatB) + { + B2DHomMatrix aMul(rMatB); + aMul *= rMatA; + return aMul; + } + + template<typename charT, typename traits> + std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, B2DHomMatrix const & matrix) + { + return stream + << '[' << matrix.get(0, 0) << ' ' << matrix.get(0, 1) << ' ' + << matrix.get(0, 2) << "; " << matrix.get(1, 0) << ' ' + << matrix.get(1, 1) << ' ' << matrix.get(1, 2) << ']'; + } +} // end of namespace basegfx + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/matrix/b2dhommatrixtools.hxx b/include/basegfx/matrix/b2dhommatrixtools.hxx new file mode 100644 index 0000000000..9b81f33d2a --- /dev/null +++ b/include/basegfx/matrix/b2dhommatrixtools.hxx @@ -0,0 +1,218 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/types.h> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/tuple/b2dtuple.hxx> +#include <utility> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx { class B2DRange; } + +namespace basegfx::utils +{ + /** If the rotation angle is an approximate multiple of pi/2, + 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) + */ + void createSinCosOrthogonal(double& o_rSin, double& rCos, double fRadiant); + + /** Tooling methods for on-the-fly matrix generation e.g. for inline + multiplications + */ + BASEGFX_DLLPUBLIC B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY); + BASEGFX_DLLPUBLIC B2DHomMatrix createShearXB2DHomMatrix(double fShearX); + BASEGFX_DLLPUBLIC B2DHomMatrix createShearYB2DHomMatrix(double fShearY); + BASEGFX_DLLPUBLIC B2DHomMatrix createRotateB2DHomMatrix(double fRadiant); + BASEGFX_DLLPUBLIC B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY); + + /// inline versions for parameters as tuples + inline B2DHomMatrix createScaleB2DHomMatrix(const B2DTuple& rScale) + { + return createScaleB2DHomMatrix(rScale.getX(), rScale.getY()); + } + + inline B2DHomMatrix createTranslateB2DHomMatrix(const B2DTuple& rTranslate) + { + return createTranslateB2DHomMatrix(rTranslate.getX(), rTranslate.getY()); + } + + /** Tooling methods for faster completely combined matrix creation + when scale, shearX, rotation and translation needs to be done in + exactly that order. It's faster since it directly calculates + each matrix value based on a symbolic calculation of the three + matrix multiplications. + Inline versions for parameters as tuples added, too. + */ + BASEGFX_DLLPUBLIC B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix( + double fScaleX, double fScaleY, + double fShearX, + double fRadiant, + double fTranslateX, double fTranslateY); + inline B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix( + const B2DTuple& rScale, + double fShearX, + double fRadiant, + const B2DTuple& rTranslate) + { + return createScaleShearXRotateTranslateB2DHomMatrix( + rScale.getX(), rScale.getY(), + fShearX, + fRadiant, + rTranslate.getX(), rTranslate.getY()); + } + + BASEGFX_DLLPUBLIC B2DHomMatrix createShearXRotateTranslateB2DHomMatrix( + double fShearX, + double fRadiant, + double fTranslateX, double fTranslateY); + inline B2DHomMatrix createShearXRotateTranslateB2DHomMatrix( + double fShearX, + double fRadiant, + const B2DTuple& rTranslate) + { + return createShearXRotateTranslateB2DHomMatrix( + fShearX, + fRadiant, + rTranslate.getX(), rTranslate.getY()); + } + + BASEGFX_DLLPUBLIC B2DHomMatrix createScaleTranslateB2DHomMatrix( + double fScaleX, double fScaleY, + double fTranslateX, double fTranslateY); + inline B2DHomMatrix createScaleTranslateB2DHomMatrix( + const B2DTuple& rScale, + const B2DTuple& rTranslate) + { + return createScaleTranslateB2DHomMatrix( + rScale.getX(), rScale.getY(), + rTranslate.getX(), rTranslate.getY()); + } + + /// special for the often used case of rotation around a point + BASEGFX_DLLPUBLIC B2DHomMatrix createRotateAroundPoint( + double fPointX, double fPointY, + double fRadiant); + inline B2DHomMatrix createRotateAroundPoint( + const B2DTuple& rPoint, + double fRadiant) + { + return createRotateAroundPoint( + rPoint.getX(), rPoint.getY(), + fRadiant); + } + + /// special for creating a mapping for a Range rotated around it's center + /// while keeping AspectRatio unchanged and staying inside the given Range + /// by optimally using the available space (no overlap or outside allowed) + B2DHomMatrix createRotateAroundCenterKeepAspectRatioStayInsideRange( + const basegfx::B2DRange& rTargetRange, + double fRotate); + + /// special for the case to map from source range to target range + BASEGFX_DLLPUBLIC B2DHomMatrix createSourceRangeTargetRangeTransform( + const B2DRange& rSourceRange, + const B2DRange& rTargetRange); + + /// create based on given CoordinateSystem which is defined by origin and x/yaxis + BASEGFX_DLLPUBLIC B2DHomMatrix createCoordinateSystemTransform( + const B2DPoint& rOrigin, + const B2DVector& rX, + const B2DVector& rY); + + /// get column vector from B2dHomMatrix, e.g. to extract coordinate system origin and x/yaxis + BASEGFX_DLLPUBLIC B2DTuple getColumn(const B2DHomMatrix& rMatrix, sal_uInt16 nCol); + + + class BASEGFX_DLLPUBLIC B2DHomMatrixBufferedDecompose + { + private: + B2DVector maScale; + B2DVector maTranslate; + double mfRotate; + double mfShearX; + + public: + B2DHomMatrixBufferedDecompose(const B2DHomMatrix& rB2DHomMatrix = B2DHomMatrix()) + : mfRotate(0.0), + mfShearX(0.0) + { + rB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX); + } + + // data access + B2DHomMatrix getB2DHomMatrix() const + { + return createScaleShearXRotateTranslateB2DHomMatrix( + maScale, mfShearX, mfRotate, maTranslate); + } + + const B2DVector& getScale() const { return maScale; } + const B2DVector& getTranslate() const { return maTranslate; } + double getRotate() const { return mfRotate; } + double getShearX() const { return mfShearX; } + }; + + class BASEGFX_DLLPUBLIC B2DHomMatrixBufferedOnDemandDecompose + { + private: + B2DHomMatrix maB2DHomMatrix; + B2DVector maScale; + B2DVector maTranslate; + double mfRotate; + double mfShearX; + + bool mbDecomposed : 1; + + void impCheckDecompose() + { + if(!mbDecomposed) + { + maB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX); + mbDecomposed = true; + } + } + + public: + B2DHomMatrixBufferedOnDemandDecompose(B2DHomMatrix aB2DHomMatrix = B2DHomMatrix()) + : maB2DHomMatrix(std::move(aB2DHomMatrix)), + mfRotate(0.0), + mfShearX(0.0), + mbDecomposed(false) + { + } + + // data access + const B2DHomMatrix& getB2DHomMatrix() const { return maB2DHomMatrix; } + const B2DVector& getScale() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maScale; } + const B2DVector& getTranslate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maTranslate; } + double getRotate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfRotate; } + double getShearX() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfShearX; } + }; +} // end of namespace basegfx::utils + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/matrix/b3dhommatrix.hxx b/include/basegfx/matrix/b3dhommatrix.hxx new file mode 100644 index 0000000000..29603f88eb --- /dev/null +++ b/include/basegfx/matrix/b3dhommatrix.hxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/types.h> +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/vector/b3dvector.hxx> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + class B3DTuple; + class Impl3DHomMatrix; + + class BASEGFX_DLLPUBLIC B3DHomMatrix + { + public: + typedef o3tl::cow_wrapper< Impl3DHomMatrix, o3tl::ThreadSafeRefCountingPolicy > ImplType; + + private: + ImplType mpImpl; + + public: + B3DHomMatrix(); + B3DHomMatrix(const B3DHomMatrix& rMat); + B3DHomMatrix(B3DHomMatrix&& rMat); + ~B3DHomMatrix(); + + double get(sal_uInt16 nRow, sal_uInt16 nColumn) const; + void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue); + + // test if last line is default to see if last line needs to be + // involved in calculations + bool isLastLineDefault() const; + + bool isIdentity() const; + /// Reset to the identity matrix + void identity(); + + /// Invert the matrix (if possible) + void invert(); + + /// Calc the matrix determinant + double determinant() const; + + /// Rotation + void rotate(double fAngleX,double fAngleY,double fAngleZ); + void rotate(const B3DTuple& rRotation); + + /// Translation + void translate(double fX, double fY, double fZ); + void translate(const B3DTuple& rTranslation); + + /// Scaling + void scale(double fX, double fY, double fZ); + void scale(const B3DTuple& rScale); + + // Shearing-Matrices + void shearXY(double fSx, double fSy); + void shearXZ(double fSx, double fSz); + + // Projection matrices, used for converting between eye and + // clip coordinates + void frustum(double fLeft = -1.0, double fRight = 1.0, + double fBottom = -1.0, double fTop = 1.0, + double fNear = 0.001, double fFar = 1.0); + + void ortho(double fLeft = -1.0, double fRight = 1.0, + double fBottom = -1.0, double fTop = 1.0, + double fNear = 0.0, double fFar = 1.0); + + // build orientation matrix + void orientation( + const B3DPoint& rVRP = B3DPoint(0.0,0.0,1.0), + B3DVector aVPN = B3DVector(0.0,0.0,1.0), + B3DVector aVUV = B3DVector(0.0,1.0,0.0)); + + // addition, subtraction + B3DHomMatrix& operator+=(const B3DHomMatrix& rMat); + B3DHomMatrix& operator-=(const B3DHomMatrix& rMat); + + // comparison + bool operator==(const B3DHomMatrix& rMat) const; + bool operator!=(const B3DHomMatrix& rMat) const; + + // multiplication, division by constant value + B3DHomMatrix& operator*=(double fValue); + B3DHomMatrix& operator/=(double fValue); + + // matrix multiplication (from the left) + B3DHomMatrix& operator*=(const B3DHomMatrix& rMat); + + // assignment operator + B3DHomMatrix& operator=(const B3DHomMatrix& rMat); + B3DHomMatrix& operator=(B3DHomMatrix&& rMat); + + // decomposition + void decompose(B3DTuple& rScale, B3DTuple& rTranslate, B3DTuple& rRotate, B3DTuple& rShear) const; + }; + + inline B3DHomMatrix operator*(const B3DHomMatrix& rMatA, const B3DHomMatrix& rMatB) + { + B3DHomMatrix aMul(rMatB); + aMul *= rMatA; + return aMul; + } +} // end of namespace basegfx + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/matrix/b3dhommatrixtools.hxx b/include/basegfx/matrix/b3dhommatrixtools.hxx new file mode 100644 index 0000000000..6b65d24603 --- /dev/null +++ b/include/basegfx/matrix/b3dhommatrixtools.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <basegfx/basegfxdllapi.h> +#include <basegfx/matrix/b3dhommatrix.hxx> + +namespace com::sun::star::drawing +{ +struct HomogenMatrix; +} + +namespace basegfx::utils +{ +/* tooling methods for converting API matrices (drawing::HomogenMatrix) to + B3DHomMatrix. drawing::HomogenMatrix4 is not used by OOo + */ +BASEGFX_DLLPUBLIC B3DHomMatrix +UnoHomogenMatrixToB3DHomMatrix(const com::sun::star::drawing::HomogenMatrix& rMatrixIn); + +BASEGFX_DLLPUBLIC void +B3DHomMatrixToUnoHomogenMatrix(const B3DHomMatrix& rMatrixIn, + com::sun::star::drawing::HomogenMatrix& rMatrixOut); + +} // end of namespace basegfx::tools + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/matrix/hommatrixtemplate.hxx b/include/basegfx/matrix/hommatrixtemplate.hxx new file mode 100644 index 0000000000..4f1300f533 --- /dev/null +++ b/include/basegfx/matrix/hommatrixtemplate.hxx @@ -0,0 +1,427 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/types.h> +#include <basegfx/numeric/ftools.hxx> +#include <cmath> + +namespace basegfx::internal + { + + inline constexpr double implGetDefaultValue(sal_uInt16 nRow, sal_uInt16 nColumn) + { + if(nRow == nColumn) + return 1.0; + return 0.0; + } + + template < sal_uInt16 RowSize > class ImplMatLine + { + double mfValue[RowSize]; + + public: + ImplMatLine() = default; + + explicit ImplMatLine(sal_uInt16 nRow) + { + for(sal_uInt16 a(0); a < RowSize; a++) + { + mfValue[a] = implGetDefaultValue(nRow, a); + } + } + + double get(sal_uInt16 nColumn) const + { + return mfValue[nColumn]; + } + + void set(sal_uInt16 nColumn, const double& rValue) + { + mfValue[nColumn] = rValue; + } + }; + + template < sal_uInt16 RowSize > class ImplHomMatrixTemplate + { + ImplMatLine< RowSize > maLine[RowSize]; + + public: + // Is last line used? + bool isLastLineDefault() const + { + for(sal_uInt16 a(0); a < RowSize; a++) + { + const double fDefault(implGetDefaultValue((RowSize - 1), a)); + const double fLineValue(maLine[RowSize-1].get(a)); + + if(fDefault != fLineValue) + { + return false; + } + } + return true; + } + + ImplHomMatrixTemplate() + { + // complete initialization with identity matrix, all lines + // were initialized with a trailing 1 followed by 0's. + for(sal_uInt16 a(0); a < RowSize; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + maLine[a].set(b, implGetDefaultValue(a, b) ); + } + } + + ImplHomMatrixTemplate(const ImplHomMatrixTemplate& rToBeCopied) + { + operator=(rToBeCopied); + } + + ImplHomMatrixTemplate& operator=(const ImplHomMatrixTemplate& rToBeCopied) + { + if (this != &rToBeCopied) + { + // complete initialization using copy + for(sal_uInt16 a(0); a < RowSize; a++) + { + maLine[a] = rToBeCopied.maLine[a]; + } + } + return *this; + } + + static sal_uInt16 getEdgeLength() { return RowSize; } + + double get(sal_uInt16 nRow, sal_uInt16 nColumn) const + { + return maLine[nRow].get(nColumn); + } + + void set(sal_uInt16 nRow, sal_uInt16 nColumn, const double& rValue) + { + maLine[nRow].set(nColumn, rValue); + } + + // Left-upper decomposition + bool ludcmp(sal_uInt16 nIndex[], sal_Int16& nParity) + { + double fBig, fSum, fDum; + double fStorage[RowSize]; + sal_uInt16 a, b, c; + + // #i30874# Initialize nAMax (compiler warns) + sal_uInt16 nAMax = 0; + + nParity = 1; + + // Calc the max of each line. If a line is empty, + // stop immediately since matrix is not invertible then. + for(a = 0; a < RowSize; a++) + { + fBig = 0.0; + + for(b = 0; b < RowSize; b++) + { + double fTemp(fabs(get(a, b))); + + if(::basegfx::fTools::more(fTemp, fBig)) + { + fBig = fTemp; + } + } + + if(::basegfx::fTools::equalZero(fBig)) + { + return false; + } + + fStorage[a] = 1.0 / fBig; + } + + // start normalizing + for(b = 0; b < RowSize; b++) + { + for(a = 0; a < b; a++) + { + fSum = get(a, b); + + for(c = 0; c < a; c++) + { + fSum -= get(a, c) * get(c, b); + } + + set(a, b, fSum); + } + + fBig = 0.0; + + for(a = b; a < RowSize; a++) + { + fSum = get(a, b); + + for(c = 0; c < b; c++) + { + fSum -= get(a, c) * get(c, b); + } + + set(a, b, fSum); + fDum = fStorage[a] * fabs(fSum); + + if(::basegfx::fTools::moreOrEqual(fDum, fBig)) + { + fBig = fDum; + nAMax = a; + } + } + + if(b != nAMax) + { + for(c = 0; c < RowSize; c++) + { + fDum = get(nAMax, c); + set(nAMax, c, get(b, c)); + set(b, c, fDum); + } + + nParity = -nParity; + fStorage[nAMax] = fStorage[b]; + } + + nIndex[b] = nAMax; + + // here the failure of precision occurs + const double fValBB(fabs(get(b, b))); + + if(::basegfx::fTools::equalZero(fValBB)) + { + return false; + } + + if(b != (RowSize - 1)) + { + fDum = 1.0 / get(b, b); + + for(a = b + 1; a < RowSize; a++) + { + set(a, b, get(a, b) * fDum); + } + } + } + + return true; + } + + void lubksb(const sal_uInt16 nIndex[], double fRow[]) const + { + sal_uInt16 b, ip; + sal_Int16 a, a2 = -1; + double fSum; + + for(a = 0; a < RowSize; a++) + { + ip = nIndex[a]; + fSum = fRow[ip]; + fRow[ip] = fRow[a]; + + if(a2 >= 0) + { + for(b = a2; b < a; b++) + { + fSum -= get(a, b) * fRow[b]; + } + } + else if(!::basegfx::fTools::equalZero(fSum)) + { + a2 = a; + } + + fRow[a] = fSum; + } + + for(a = (RowSize - 1); a >= 0; a--) + { + fSum = fRow[a]; + + for(b = a + 1; b < RowSize; b++) + { + fSum -= get(a, b) * fRow[b]; + } + + const double fValueAA(get(a, a)); + + if(!::basegfx::fTools::equalZero(fValueAA)) + { + fRow[a] = fSum / get(a, a); + } + } + } + + bool isIdentity() const + { + for(sal_uInt16 a(0); a < RowSize; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + { + const double fDefault(implGetDefaultValue(a, b)); + const double fValueAB(get(a, b)); + + if(!::basegfx::fTools::equal(fDefault, fValueAB)) + { + return false; + } + } + } + + return true; + } + + bool isInvertible() const + { + ImplHomMatrixTemplate aWork(*this); + sal_uInt16 nIndex[RowSize]; + sal_Int16 nParity; + + return aWork.ludcmp(nIndex, nParity); + } + + void doInvert(const ImplHomMatrixTemplate& rWork, const sal_uInt16 nIndex[]) + { + double fArray[RowSize]; + + for(sal_uInt16 a(0); a < RowSize; a++) + { + // prepare line + sal_uInt16 b; + for( b = 0; b < RowSize; b++) + { + fArray[b] = implGetDefaultValue(a, b); + } + + // expand line + rWork.lubksb(nIndex, fArray); + + // copy line transposed to this matrix + for( b = 0; b < RowSize; b++) + { + set(b, a, fArray[b]); + } + } + } + + double doDeterminant() const + { + ImplHomMatrixTemplate aWork(*this); + sal_uInt16 nIndex[RowSize]; + sal_Int16 nParity; + double fRetval(0.0); + + if(aWork.ludcmp(nIndex, nParity)) + { + fRetval = static_cast<double>(nParity); + for(sal_uInt16 a(0); a < RowSize; a++) + { + fRetval *= aWork.get(a, a); + } + } + + return fRetval; + } + + void doAddMatrix(const ImplHomMatrixTemplate& rMat) + { + for(sal_uInt16 a(0); a < RowSize; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + { + set(a, b, get(a, b) + rMat.get(a, b)); + } + } + } + + void doSubMatrix(const ImplHomMatrixTemplate& rMat) + { + for(sal_uInt16 a(0); a < RowSize; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + { + set(a, b, get(a, b) - rMat.get(a, b)); + } + } + } + + void doMulMatrix(const double& rfValue) + { + for(sal_uInt16 a(0); a < RowSize; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + { + set(a, b, get(a, b) * rfValue); + } + } + } + + void doMulMatrix(const ImplHomMatrixTemplate& rMat) + { + // create a copy as source for the original values + const ImplHomMatrixTemplate aCopy(*this); + + // TODO: maybe optimize cases where last line is [0 0 1]. + + double fValue(0.0); + + for(sal_uInt16 a(0); a < RowSize; ++a) + { + for(sal_uInt16 b(0); b < RowSize; ++b) + { + fValue = 0.0; + + for(sal_uInt16 c(0); c < RowSize; ++c) + fValue += aCopy.get(c, b) * rMat.get(a, c); + + set(a, b, fValue); + } + } + } + + bool isEqual(const ImplHomMatrixTemplate& rMat) const + { + for(sal_uInt16 a(0); a < RowSize; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + { + const double fValueA(get(a, b)); + const double fValueB(rMat.get(a, b)); + + if(!::basegfx::fTools::equal(fValueA, fValueB)) + { + return false; + } + } + } + + return true; + } + }; + +} // namespace basegfx::internal + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |