109dbbe93SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 309dbbe93SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 409dbbe93SAndrew Rist * or more contributor license agreements. See the NOTICE file 509dbbe93SAndrew Rist * distributed with this work for additional information 609dbbe93SAndrew Rist * regarding copyright ownership. The ASF licenses this file 709dbbe93SAndrew Rist * to you under the Apache License, Version 2.0 (the 809dbbe93SAndrew Rist * "License"); you may not use this file except in compliance 909dbbe93SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 1109dbbe93SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 1309dbbe93SAndrew Rist * Unless required by applicable law or agreed to in writing, 1409dbbe93SAndrew Rist * software distributed under the License is distributed on an 1509dbbe93SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1609dbbe93SAndrew Rist * KIND, either express or implied. See the License for the 1709dbbe93SAndrew Rist * specific language governing permissions and limitations 1809dbbe93SAndrew Rist * under the License. 19cdf0e10cSrcweir * 2009dbbe93SAndrew Rist *************************************************************/ 2109dbbe93SAndrew Rist 22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 23cdf0e10cSrcweir #include "precompiled_basegfx.hxx" 24cdf0e10cSrcweir 25cdf0e10cSrcweir #include <rtl/instance.hxx> 26cdf0e10cSrcweir #include <basegfx/matrix/b3dhommatrix.hxx> 27cdf0e10cSrcweir #include <hommatrixtemplate.hxx> 28cdf0e10cSrcweir #include <basegfx/vector/b3dvector.hxx> 29cdf0e10cSrcweir 30cdf0e10cSrcweir namespace basegfx 31cdf0e10cSrcweir { 32cdf0e10cSrcweir class Impl3DHomMatrix : public ::basegfx::internal::ImplHomMatrixTemplate< 4 > 33cdf0e10cSrcweir { 34cdf0e10cSrcweir }; 35cdf0e10cSrcweir 36cdf0e10cSrcweir namespace { struct IdentityMatrix : public rtl::Static< B3DHomMatrix::ImplType, 37cdf0e10cSrcweir IdentityMatrix > {}; } 38cdf0e10cSrcweir B3DHomMatrix()39cdf0e10cSrcweir B3DHomMatrix::B3DHomMatrix() : 40cdf0e10cSrcweir mpImpl( IdentityMatrix::get() ) // use common identity matrix 41cdf0e10cSrcweir { 42cdf0e10cSrcweir } 43cdf0e10cSrcweir B3DHomMatrix(const B3DHomMatrix & rMat)44cdf0e10cSrcweir B3DHomMatrix::B3DHomMatrix(const B3DHomMatrix& rMat) : 45cdf0e10cSrcweir mpImpl(rMat.mpImpl) 46cdf0e10cSrcweir { 47cdf0e10cSrcweir } 48cdf0e10cSrcweir ~B3DHomMatrix()49cdf0e10cSrcweir B3DHomMatrix::~B3DHomMatrix() 50cdf0e10cSrcweir { 51cdf0e10cSrcweir } 52cdf0e10cSrcweir operator =(const B3DHomMatrix & rMat)53cdf0e10cSrcweir B3DHomMatrix& B3DHomMatrix::operator=(const B3DHomMatrix& rMat) 54cdf0e10cSrcweir { 55cdf0e10cSrcweir mpImpl = rMat.mpImpl; 56cdf0e10cSrcweir return *this; 57cdf0e10cSrcweir } 58cdf0e10cSrcweir makeUnique()59cdf0e10cSrcweir void B3DHomMatrix::makeUnique() 60cdf0e10cSrcweir { 61cdf0e10cSrcweir mpImpl.make_unique(); 62cdf0e10cSrcweir } 63cdf0e10cSrcweir get(sal_uInt16 nRow,sal_uInt16 nColumn) const64cdf0e10cSrcweir double B3DHomMatrix::get(sal_uInt16 nRow, sal_uInt16 nColumn) const 65cdf0e10cSrcweir { 66cdf0e10cSrcweir return mpImpl->get(nRow, nColumn); 67cdf0e10cSrcweir } 68cdf0e10cSrcweir set(sal_uInt16 nRow,sal_uInt16 nColumn,double fValue)69cdf0e10cSrcweir void B3DHomMatrix::set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue) 70cdf0e10cSrcweir { 71cdf0e10cSrcweir mpImpl->set(nRow, nColumn, fValue); 72cdf0e10cSrcweir } 73cdf0e10cSrcweir isLastLineDefault() const74cdf0e10cSrcweir bool B3DHomMatrix::isLastLineDefault() const 75cdf0e10cSrcweir { 76cdf0e10cSrcweir return mpImpl->isLastLineDefault(); 77cdf0e10cSrcweir } 78cdf0e10cSrcweir isIdentity() const79cdf0e10cSrcweir bool B3DHomMatrix::isIdentity() const 80cdf0e10cSrcweir { 81cdf0e10cSrcweir if(mpImpl.same_object(IdentityMatrix::get())) 82cdf0e10cSrcweir return true; 83cdf0e10cSrcweir 84cdf0e10cSrcweir return mpImpl->isIdentity(); 85cdf0e10cSrcweir } 86cdf0e10cSrcweir identity()87cdf0e10cSrcweir void B3DHomMatrix::identity() 88cdf0e10cSrcweir { 89cdf0e10cSrcweir mpImpl = IdentityMatrix::get(); 90cdf0e10cSrcweir } 91cdf0e10cSrcweir isInvertible() const92cdf0e10cSrcweir bool B3DHomMatrix::isInvertible() const 93cdf0e10cSrcweir { 94cdf0e10cSrcweir return mpImpl->isInvertible(); 95cdf0e10cSrcweir } 96cdf0e10cSrcweir invert()97cdf0e10cSrcweir bool B3DHomMatrix::invert() 98cdf0e10cSrcweir { 99cdf0e10cSrcweir Impl3DHomMatrix aWork(*mpImpl); 100cdf0e10cSrcweir sal_uInt16* pIndex = new sal_uInt16[mpImpl->getEdgeLength()]; 101cdf0e10cSrcweir sal_Int16 nParity; 102cdf0e10cSrcweir 103cdf0e10cSrcweir if(aWork.ludcmp(pIndex, nParity)) 104cdf0e10cSrcweir { 105cdf0e10cSrcweir mpImpl->doInvert(aWork, pIndex); 106cdf0e10cSrcweir delete[] pIndex; 107cdf0e10cSrcweir 108cdf0e10cSrcweir return true; 109cdf0e10cSrcweir } 110cdf0e10cSrcweir 111cdf0e10cSrcweir delete[] pIndex; 112cdf0e10cSrcweir return false; 113cdf0e10cSrcweir } 114cdf0e10cSrcweir isNormalized() const115cdf0e10cSrcweir bool B3DHomMatrix::isNormalized() const 116cdf0e10cSrcweir { 117cdf0e10cSrcweir return mpImpl->isNormalized(); 118cdf0e10cSrcweir } 119cdf0e10cSrcweir normalize()120cdf0e10cSrcweir void B3DHomMatrix::normalize() 121cdf0e10cSrcweir { 122cdf0e10cSrcweir if(!const_cast<const B3DHomMatrix*>(this)->mpImpl->isNormalized()) 123cdf0e10cSrcweir mpImpl->doNormalize(); 124cdf0e10cSrcweir } 125cdf0e10cSrcweir determinant() const126cdf0e10cSrcweir double B3DHomMatrix::determinant() const 127cdf0e10cSrcweir { 128cdf0e10cSrcweir return mpImpl->doDeterminant(); 129cdf0e10cSrcweir } 130cdf0e10cSrcweir trace() const131cdf0e10cSrcweir double B3DHomMatrix::trace() const 132cdf0e10cSrcweir { 133cdf0e10cSrcweir return mpImpl->doTrace(); 134cdf0e10cSrcweir } 135cdf0e10cSrcweir transpose()136cdf0e10cSrcweir void B3DHomMatrix::transpose() 137cdf0e10cSrcweir { 138cdf0e10cSrcweir mpImpl->doTranspose(); 139cdf0e10cSrcweir } 140cdf0e10cSrcweir operator +=(const B3DHomMatrix & rMat)141cdf0e10cSrcweir B3DHomMatrix& B3DHomMatrix::operator+=(const B3DHomMatrix& rMat) 142cdf0e10cSrcweir { 143cdf0e10cSrcweir mpImpl->doAddMatrix(*rMat.mpImpl); 144cdf0e10cSrcweir return *this; 145cdf0e10cSrcweir } 146cdf0e10cSrcweir operator -=(const B3DHomMatrix & rMat)147cdf0e10cSrcweir B3DHomMatrix& B3DHomMatrix::operator-=(const B3DHomMatrix& rMat) 148cdf0e10cSrcweir { 149cdf0e10cSrcweir mpImpl->doSubMatrix(*rMat.mpImpl); 150cdf0e10cSrcweir return *this; 151cdf0e10cSrcweir } 152cdf0e10cSrcweir operator *=(double fValue)153cdf0e10cSrcweir B3DHomMatrix& B3DHomMatrix::operator*=(double fValue) 154cdf0e10cSrcweir { 155cdf0e10cSrcweir const double fOne(1.0); 156cdf0e10cSrcweir 157cdf0e10cSrcweir if(!fTools::equal(fOne, fValue)) 158cdf0e10cSrcweir mpImpl->doMulMatrix(fValue); 159cdf0e10cSrcweir 160cdf0e10cSrcweir return *this; 161cdf0e10cSrcweir } 162cdf0e10cSrcweir operator /=(double fValue)163cdf0e10cSrcweir B3DHomMatrix& B3DHomMatrix::operator/=(double fValue) 164cdf0e10cSrcweir { 165cdf0e10cSrcweir const double fOne(1.0); 166cdf0e10cSrcweir 167cdf0e10cSrcweir if(!fTools::equal(fOne, fValue)) 168cdf0e10cSrcweir mpImpl->doMulMatrix(1.0 / fValue); 169cdf0e10cSrcweir 170cdf0e10cSrcweir return *this; 171cdf0e10cSrcweir } 172cdf0e10cSrcweir operator *=(const B3DHomMatrix & rMat)173cdf0e10cSrcweir B3DHomMatrix& B3DHomMatrix::operator*=(const B3DHomMatrix& rMat) 174cdf0e10cSrcweir { 175cdf0e10cSrcweir if(!rMat.isIdentity()) 176cdf0e10cSrcweir mpImpl->doMulMatrix(*rMat.mpImpl); 177cdf0e10cSrcweir 178cdf0e10cSrcweir return *this; 179cdf0e10cSrcweir } 180cdf0e10cSrcweir operator ==(const B3DHomMatrix & rMat) const181cdf0e10cSrcweir bool B3DHomMatrix::operator==(const B3DHomMatrix& rMat) const 182cdf0e10cSrcweir { 183cdf0e10cSrcweir if(mpImpl.same_object(rMat.mpImpl)) 184cdf0e10cSrcweir return true; 185cdf0e10cSrcweir 186cdf0e10cSrcweir return mpImpl->isEqual(*rMat.mpImpl); 187cdf0e10cSrcweir } 188cdf0e10cSrcweir operator !=(const B3DHomMatrix & rMat) const189cdf0e10cSrcweir bool B3DHomMatrix::operator!=(const B3DHomMatrix& rMat) const 190cdf0e10cSrcweir { 191cdf0e10cSrcweir return !(*this == rMat); 192cdf0e10cSrcweir } 193cdf0e10cSrcweir rotate(double fAngleX,double fAngleY,double fAngleZ)194cdf0e10cSrcweir void B3DHomMatrix::rotate(double fAngleX,double fAngleY,double fAngleZ) 195cdf0e10cSrcweir { 196cdf0e10cSrcweir if(!fTools::equalZero(fAngleX) || !fTools::equalZero(fAngleY) || !fTools::equalZero(fAngleZ)) 197cdf0e10cSrcweir { 198cdf0e10cSrcweir if(!fTools::equalZero(fAngleX)) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir Impl3DHomMatrix aRotMatX; 201cdf0e10cSrcweir double fSin(sin(fAngleX)); 202cdf0e10cSrcweir double fCos(cos(fAngleX)); 203cdf0e10cSrcweir 204cdf0e10cSrcweir aRotMatX.set(1, 1, fCos); 205cdf0e10cSrcweir aRotMatX.set(2, 2, fCos); 206cdf0e10cSrcweir aRotMatX.set(2, 1, fSin); 207cdf0e10cSrcweir aRotMatX.set(1, 2, -fSin); 208cdf0e10cSrcweir 209cdf0e10cSrcweir mpImpl->doMulMatrix(aRotMatX); 210cdf0e10cSrcweir } 211cdf0e10cSrcweir 212cdf0e10cSrcweir if(!fTools::equalZero(fAngleY)) 213cdf0e10cSrcweir { 214cdf0e10cSrcweir Impl3DHomMatrix aRotMatY; 215cdf0e10cSrcweir double fSin(sin(fAngleY)); 216cdf0e10cSrcweir double fCos(cos(fAngleY)); 217cdf0e10cSrcweir 218cdf0e10cSrcweir aRotMatY.set(0, 0, fCos); 219cdf0e10cSrcweir aRotMatY.set(2, 2, fCos); 220cdf0e10cSrcweir aRotMatY.set(0, 2, fSin); 221cdf0e10cSrcweir aRotMatY.set(2, 0, -fSin); 222cdf0e10cSrcweir 223cdf0e10cSrcweir mpImpl->doMulMatrix(aRotMatY); 224cdf0e10cSrcweir } 225cdf0e10cSrcweir 226cdf0e10cSrcweir if(!fTools::equalZero(fAngleZ)) 227cdf0e10cSrcweir { 228cdf0e10cSrcweir Impl3DHomMatrix aRotMatZ; 229cdf0e10cSrcweir double fSin(sin(fAngleZ)); 230cdf0e10cSrcweir double fCos(cos(fAngleZ)); 231cdf0e10cSrcweir 232cdf0e10cSrcweir aRotMatZ.set(0, 0, fCos); 233cdf0e10cSrcweir aRotMatZ.set(1, 1, fCos); 234cdf0e10cSrcweir aRotMatZ.set(1, 0, fSin); 235cdf0e10cSrcweir aRotMatZ.set(0, 1, -fSin); 236cdf0e10cSrcweir 237cdf0e10cSrcweir mpImpl->doMulMatrix(aRotMatZ); 238cdf0e10cSrcweir } 239cdf0e10cSrcweir } 240cdf0e10cSrcweir } 241cdf0e10cSrcweir translate(double fX,double fY,double fZ)242cdf0e10cSrcweir void B3DHomMatrix::translate(double fX, double fY, double fZ) 243cdf0e10cSrcweir { 244cdf0e10cSrcweir if(!fTools::equalZero(fX) || !fTools::equalZero(fY) || !fTools::equalZero(fZ)) 245cdf0e10cSrcweir { 246cdf0e10cSrcweir Impl3DHomMatrix aTransMat; 247cdf0e10cSrcweir 248cdf0e10cSrcweir aTransMat.set(0, 3, fX); 249cdf0e10cSrcweir aTransMat.set(1, 3, fY); 250cdf0e10cSrcweir aTransMat.set(2, 3, fZ); 251cdf0e10cSrcweir 252cdf0e10cSrcweir mpImpl->doMulMatrix(aTransMat); 253cdf0e10cSrcweir } 254cdf0e10cSrcweir } 255cdf0e10cSrcweir scale(double fX,double fY,double fZ)256cdf0e10cSrcweir void B3DHomMatrix::scale(double fX, double fY, double fZ) 257cdf0e10cSrcweir { 258cdf0e10cSrcweir const double fOne(1.0); 259cdf0e10cSrcweir 260cdf0e10cSrcweir if(!fTools::equal(fOne, fX) || !fTools::equal(fOne, fY) ||!fTools::equal(fOne, fZ)) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir Impl3DHomMatrix aScaleMat; 263cdf0e10cSrcweir 264cdf0e10cSrcweir aScaleMat.set(0, 0, fX); 265cdf0e10cSrcweir aScaleMat.set(1, 1, fY); 266cdf0e10cSrcweir aScaleMat.set(2, 2, fZ); 267cdf0e10cSrcweir 268cdf0e10cSrcweir mpImpl->doMulMatrix(aScaleMat); 269cdf0e10cSrcweir } 270cdf0e10cSrcweir } 271cdf0e10cSrcweir shearXY(double fSx,double fSy)272cdf0e10cSrcweir void B3DHomMatrix::shearXY(double fSx, double fSy) 273cdf0e10cSrcweir { 274*45d1b581Smseidel // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) 275cdf0e10cSrcweir if(!fTools::equalZero(fSx) || !fTools::equalZero(fSy)) 276cdf0e10cSrcweir { 277cdf0e10cSrcweir Impl3DHomMatrix aShearXYMat; 278cdf0e10cSrcweir 279cdf0e10cSrcweir aShearXYMat.set(0, 2, fSx); 280cdf0e10cSrcweir aShearXYMat.set(1, 2, fSy); 281cdf0e10cSrcweir 282cdf0e10cSrcweir mpImpl->doMulMatrix(aShearXYMat); 283cdf0e10cSrcweir } 284cdf0e10cSrcweir } 285cdf0e10cSrcweir shearYZ(double fSy,double fSz)286cdf0e10cSrcweir void B3DHomMatrix::shearYZ(double fSy, double fSz) 287cdf0e10cSrcweir { 288*45d1b581Smseidel // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) 289cdf0e10cSrcweir if(!fTools::equalZero(fSy) || !fTools::equalZero(fSz)) 290cdf0e10cSrcweir { 291cdf0e10cSrcweir Impl3DHomMatrix aShearYZMat; 292cdf0e10cSrcweir 293cdf0e10cSrcweir aShearYZMat.set(1, 0, fSy); 294cdf0e10cSrcweir aShearYZMat.set(2, 0, fSz); 295cdf0e10cSrcweir 296cdf0e10cSrcweir mpImpl->doMulMatrix(aShearYZMat); 297cdf0e10cSrcweir } 298cdf0e10cSrcweir } 299cdf0e10cSrcweir shearXZ(double fSx,double fSz)300cdf0e10cSrcweir void B3DHomMatrix::shearXZ(double fSx, double fSz) 301cdf0e10cSrcweir { 302*45d1b581Smseidel // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) 303cdf0e10cSrcweir if(!fTools::equalZero(fSx) || !fTools::equalZero(fSz)) 304cdf0e10cSrcweir { 305cdf0e10cSrcweir Impl3DHomMatrix aShearXZMat; 306cdf0e10cSrcweir 307cdf0e10cSrcweir aShearXZMat.set(0, 1, fSx); 308cdf0e10cSrcweir aShearXZMat.set(2, 1, fSz); 309cdf0e10cSrcweir 310cdf0e10cSrcweir mpImpl->doMulMatrix(aShearXZMat); 311cdf0e10cSrcweir } 312cdf0e10cSrcweir } 313cdf0e10cSrcweir frustum(double fLeft,double fRight,double fBottom,double fTop,double fNear,double fFar)314cdf0e10cSrcweir void B3DHomMatrix::frustum(double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar) 315cdf0e10cSrcweir { 316cdf0e10cSrcweir const double fZero(0.0); 317cdf0e10cSrcweir const double fOne(1.0); 318cdf0e10cSrcweir 319cdf0e10cSrcweir if(!fTools::more(fNear, fZero)) 320cdf0e10cSrcweir { 321cdf0e10cSrcweir fNear = 0.001; 322cdf0e10cSrcweir } 323cdf0e10cSrcweir 324cdf0e10cSrcweir if(!fTools::more(fFar, fZero)) 325cdf0e10cSrcweir { 326cdf0e10cSrcweir fFar = fOne; 327cdf0e10cSrcweir } 328cdf0e10cSrcweir 329cdf0e10cSrcweir if(fTools::equal(fNear, fFar)) 330cdf0e10cSrcweir { 331cdf0e10cSrcweir fFar = fNear + fOne; 332cdf0e10cSrcweir } 333cdf0e10cSrcweir 334cdf0e10cSrcweir if(fTools::equal(fLeft, fRight)) 335cdf0e10cSrcweir { 336cdf0e10cSrcweir fLeft -= fOne; 337cdf0e10cSrcweir fRight += fOne; 338cdf0e10cSrcweir } 339cdf0e10cSrcweir 340cdf0e10cSrcweir if(fTools::equal(fTop, fBottom)) 341cdf0e10cSrcweir { 342cdf0e10cSrcweir fBottom -= fOne; 343cdf0e10cSrcweir fTop += fOne; 344cdf0e10cSrcweir } 345cdf0e10cSrcweir 346cdf0e10cSrcweir Impl3DHomMatrix aFrustumMat; 347cdf0e10cSrcweir 348cdf0e10cSrcweir aFrustumMat.set(0, 0, 2.0 * fNear / (fRight - fLeft)); 349cdf0e10cSrcweir aFrustumMat.set(1, 1, 2.0 * fNear / (fTop - fBottom)); 350cdf0e10cSrcweir aFrustumMat.set(0, 2, (fRight + fLeft) / (fRight - fLeft)); 351cdf0e10cSrcweir aFrustumMat.set(1, 2, (fTop + fBottom) / (fTop - fBottom)); 352cdf0e10cSrcweir aFrustumMat.set(2, 2, -fOne * ((fFar + fNear) / (fFar - fNear))); 353cdf0e10cSrcweir aFrustumMat.set(3, 2, -fOne); 354cdf0e10cSrcweir aFrustumMat.set(2, 3, -fOne * ((2.0 * fFar * fNear) / (fFar - fNear))); 355cdf0e10cSrcweir aFrustumMat.set(3, 3, fZero); 356cdf0e10cSrcweir 357cdf0e10cSrcweir mpImpl->doMulMatrix(aFrustumMat); 358cdf0e10cSrcweir } 359cdf0e10cSrcweir ortho(double fLeft,double fRight,double fBottom,double fTop,double fNear,double fFar)360cdf0e10cSrcweir void B3DHomMatrix::ortho(double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar) 361cdf0e10cSrcweir { 362cdf0e10cSrcweir if(fTools::equal(fNear, fFar)) 363cdf0e10cSrcweir { 364cdf0e10cSrcweir fFar = fNear + 1.0; 365cdf0e10cSrcweir } 366cdf0e10cSrcweir 367cdf0e10cSrcweir if(fTools::equal(fLeft, fRight)) 368cdf0e10cSrcweir { 369cdf0e10cSrcweir fLeft -= 1.0; 370cdf0e10cSrcweir fRight += 1.0; 371cdf0e10cSrcweir } 372cdf0e10cSrcweir 373cdf0e10cSrcweir if(fTools::equal(fTop, fBottom)) 374cdf0e10cSrcweir { 375cdf0e10cSrcweir fBottom -= 1.0; 376cdf0e10cSrcweir fTop += 1.0; 377cdf0e10cSrcweir } 378cdf0e10cSrcweir 379cdf0e10cSrcweir Impl3DHomMatrix aOrthoMat; 380cdf0e10cSrcweir 381cdf0e10cSrcweir aOrthoMat.set(0, 0, 2.0 / (fRight - fLeft)); 382cdf0e10cSrcweir aOrthoMat.set(1, 1, 2.0 / (fTop - fBottom)); 383cdf0e10cSrcweir aOrthoMat.set(2, 2, -1.0 * (2.0 / (fFar - fNear))); 384cdf0e10cSrcweir aOrthoMat.set(0, 3, -1.0 * ((fRight + fLeft) / (fRight - fLeft))); 385cdf0e10cSrcweir aOrthoMat.set(1, 3, -1.0 * ((fTop + fBottom) / (fTop - fBottom))); 386cdf0e10cSrcweir aOrthoMat.set(2, 3, -1.0 * ((fFar + fNear) / (fFar - fNear))); 387cdf0e10cSrcweir 388cdf0e10cSrcweir mpImpl->doMulMatrix(aOrthoMat); 389cdf0e10cSrcweir } 390cdf0e10cSrcweir orientation(B3DPoint aVRP,B3DVector aVPN,B3DVector aVUV)391cdf0e10cSrcweir void B3DHomMatrix::orientation(B3DPoint aVRP, B3DVector aVPN, B3DVector aVUV) 392cdf0e10cSrcweir { 393cdf0e10cSrcweir Impl3DHomMatrix aOrientationMat; 394cdf0e10cSrcweir 395cdf0e10cSrcweir // translate -VRP 396cdf0e10cSrcweir aOrientationMat.set(0, 3, -aVRP.getX()); 397cdf0e10cSrcweir aOrientationMat.set(1, 3, -aVRP.getY()); 398cdf0e10cSrcweir aOrientationMat.set(2, 3, -aVRP.getZ()); 399cdf0e10cSrcweir 400cdf0e10cSrcweir // build rotation 401cdf0e10cSrcweir aVUV.normalize(); 402cdf0e10cSrcweir aVPN.normalize(); 403cdf0e10cSrcweir 404cdf0e10cSrcweir // build x-axis as peroendicular fron aVUV and aVPN 405cdf0e10cSrcweir B3DVector aRx(aVUV.getPerpendicular(aVPN)); 406cdf0e10cSrcweir aRx.normalize(); 407cdf0e10cSrcweir 408cdf0e10cSrcweir // y-axis perpendicular to that 409cdf0e10cSrcweir B3DVector aRy(aVPN.getPerpendicular(aRx)); 410cdf0e10cSrcweir aRy.normalize(); 411cdf0e10cSrcweir 412cdf0e10cSrcweir // the calculated normals are the line vectors of the rotation matrix, 413cdf0e10cSrcweir // set them to create rotation 414cdf0e10cSrcweir aOrientationMat.set(0, 0, aRx.getX()); 415cdf0e10cSrcweir aOrientationMat.set(0, 1, aRx.getY()); 416cdf0e10cSrcweir aOrientationMat.set(0, 2, aRx.getZ()); 417cdf0e10cSrcweir aOrientationMat.set(1, 0, aRy.getX()); 418cdf0e10cSrcweir aOrientationMat.set(1, 1, aRy.getY()); 419cdf0e10cSrcweir aOrientationMat.set(1, 2, aRy.getZ()); 420cdf0e10cSrcweir aOrientationMat.set(2, 0, aVPN.getX()); 421cdf0e10cSrcweir aOrientationMat.set(2, 1, aVPN.getY()); 422cdf0e10cSrcweir aOrientationMat.set(2, 2, aVPN.getZ()); 423cdf0e10cSrcweir 424cdf0e10cSrcweir mpImpl->doMulMatrix(aOrientationMat); 425cdf0e10cSrcweir } 426cdf0e10cSrcweir decompose(B3DTuple & rScale,B3DTuple & rTranslate,B3DTuple & rRotate,B3DTuple & rShear) const427cdf0e10cSrcweir bool B3DHomMatrix::decompose(B3DTuple& rScale, B3DTuple& rTranslate, B3DTuple& rRotate, B3DTuple& rShear) const 428cdf0e10cSrcweir { 429cdf0e10cSrcweir // when perspective is used, decompose is not made here 430cdf0e10cSrcweir if(!mpImpl->isLastLineDefault()) 431cdf0e10cSrcweir return false; 432cdf0e10cSrcweir 433cdf0e10cSrcweir // If determinant is zero, decomposition is not possible 434cdf0e10cSrcweir if(0.0 == determinant()) 435cdf0e10cSrcweir return false; 436cdf0e10cSrcweir 437cdf0e10cSrcweir // isolate translation 438cdf0e10cSrcweir rTranslate.setX(mpImpl->get(0, 3)); 439cdf0e10cSrcweir rTranslate.setY(mpImpl->get(1, 3)); 440cdf0e10cSrcweir rTranslate.setZ(mpImpl->get(2, 3)); 441cdf0e10cSrcweir 442cdf0e10cSrcweir // correct translate values 443cdf0e10cSrcweir rTranslate.correctValues(); 444cdf0e10cSrcweir 445cdf0e10cSrcweir // get scale and shear 446cdf0e10cSrcweir B3DVector aCol0(mpImpl->get(0, 0), mpImpl->get(1, 0), mpImpl->get(2, 0)); 447cdf0e10cSrcweir B3DVector aCol1(mpImpl->get(0, 1), mpImpl->get(1, 1), mpImpl->get(2, 1)); 448cdf0e10cSrcweir B3DVector aCol2(mpImpl->get(0, 2), mpImpl->get(1, 2), mpImpl->get(2, 2)); 449cdf0e10cSrcweir B3DVector aTemp; 450cdf0e10cSrcweir 451cdf0e10cSrcweir // get ScaleX 452cdf0e10cSrcweir rScale.setX(aCol0.getLength()); 453cdf0e10cSrcweir aCol0.normalize(); 454cdf0e10cSrcweir 455cdf0e10cSrcweir // get ShearXY 456cdf0e10cSrcweir rShear.setX(aCol0.scalar(aCol1)); 457cdf0e10cSrcweir 458cdf0e10cSrcweir if(fTools::equalZero(rShear.getX())) 459cdf0e10cSrcweir { 460cdf0e10cSrcweir rShear.setX(0.0); 461cdf0e10cSrcweir } 462cdf0e10cSrcweir else 463cdf0e10cSrcweir { 464cdf0e10cSrcweir aTemp.setX(aCol1.getX() - rShear.getX() * aCol0.getX()); 465cdf0e10cSrcweir aTemp.setY(aCol1.getY() - rShear.getX() * aCol0.getY()); 466cdf0e10cSrcweir aTemp.setZ(aCol1.getZ() - rShear.getX() * aCol0.getZ()); 467cdf0e10cSrcweir aCol1 = aTemp; 468cdf0e10cSrcweir } 469cdf0e10cSrcweir 470cdf0e10cSrcweir // get ScaleY 471cdf0e10cSrcweir rScale.setY(aCol1.getLength()); 472cdf0e10cSrcweir aCol1.normalize(); 473cdf0e10cSrcweir 474cdf0e10cSrcweir const double fShearX(rShear.getX()); 475cdf0e10cSrcweir 476cdf0e10cSrcweir if(!fTools::equalZero(fShearX)) 477cdf0e10cSrcweir { 478cdf0e10cSrcweir rShear.setX(rShear.getX() / rScale.getY()); 479cdf0e10cSrcweir } 480cdf0e10cSrcweir 481cdf0e10cSrcweir // get ShearXZ 482cdf0e10cSrcweir rShear.setY(aCol0.scalar(aCol2)); 483cdf0e10cSrcweir 484cdf0e10cSrcweir if(fTools::equalZero(rShear.getY())) 485cdf0e10cSrcweir { 486cdf0e10cSrcweir rShear.setY(0.0); 487cdf0e10cSrcweir } 488cdf0e10cSrcweir else 489cdf0e10cSrcweir { 490cdf0e10cSrcweir aTemp.setX(aCol2.getX() - rShear.getY() * aCol0.getX()); 491cdf0e10cSrcweir aTemp.setY(aCol2.getY() - rShear.getY() * aCol0.getY()); 492cdf0e10cSrcweir aTemp.setZ(aCol2.getZ() - rShear.getY() * aCol0.getZ()); 493cdf0e10cSrcweir aCol2 = aTemp; 494cdf0e10cSrcweir } 495cdf0e10cSrcweir 496cdf0e10cSrcweir // get ShearYZ 497cdf0e10cSrcweir rShear.setZ(aCol1.scalar(aCol2)); 498cdf0e10cSrcweir 499cdf0e10cSrcweir if(fTools::equalZero(rShear.getZ())) 500cdf0e10cSrcweir { 501cdf0e10cSrcweir rShear.setZ(0.0); 502cdf0e10cSrcweir } 503cdf0e10cSrcweir else 504cdf0e10cSrcweir { 505cdf0e10cSrcweir aTemp.setX(aCol2.getX() - rShear.getZ() * aCol1.getX()); 506cdf0e10cSrcweir aTemp.setY(aCol2.getY() - rShear.getZ() * aCol1.getY()); 507cdf0e10cSrcweir aTemp.setZ(aCol2.getZ() - rShear.getZ() * aCol1.getZ()); 508cdf0e10cSrcweir aCol2 = aTemp; 509cdf0e10cSrcweir } 510cdf0e10cSrcweir 511cdf0e10cSrcweir // get ScaleZ 512cdf0e10cSrcweir rScale.setZ(aCol2.getLength()); 513cdf0e10cSrcweir aCol2.normalize(); 514cdf0e10cSrcweir 515cdf0e10cSrcweir const double fShearY(rShear.getY()); 516cdf0e10cSrcweir 517cdf0e10cSrcweir if(!fTools::equalZero(fShearY)) 518cdf0e10cSrcweir { 519cdf0e10cSrcweir rShear.setY(rShear.getY() / rScale.getZ()); 520cdf0e10cSrcweir } 521cdf0e10cSrcweir 522cdf0e10cSrcweir const double fShearZ(rShear.getZ()); 523cdf0e10cSrcweir 524cdf0e10cSrcweir if(!fTools::equalZero(fShearZ)) 525cdf0e10cSrcweir { 526cdf0e10cSrcweir rShear.setZ(rShear.getZ() / rScale.getZ()); 527cdf0e10cSrcweir } 528cdf0e10cSrcweir 529cdf0e10cSrcweir // correct shear values 530cdf0e10cSrcweir rShear.correctValues(); 531cdf0e10cSrcweir 532cdf0e10cSrcweir // Coordinate system flip? 533cdf0e10cSrcweir if(0.0 > aCol0.scalar(aCol1.getPerpendicular(aCol2))) 534cdf0e10cSrcweir { 535cdf0e10cSrcweir rScale = -rScale; 536cdf0e10cSrcweir aCol0 = -aCol0; 537cdf0e10cSrcweir aCol1 = -aCol1; 538cdf0e10cSrcweir aCol2 = -aCol2; 539cdf0e10cSrcweir } 540cdf0e10cSrcweir 541cdf0e10cSrcweir // correct scale values 542cdf0e10cSrcweir rScale.correctValues(1.0); 543cdf0e10cSrcweir 544cdf0e10cSrcweir // Get rotations 545cdf0e10cSrcweir { 546cdf0e10cSrcweir double fy=0; 547cdf0e10cSrcweir double cy=0; 548cdf0e10cSrcweir 549cdf0e10cSrcweir if( ::basegfx::fTools::equal( aCol0.getZ(), 1.0 ) 550cdf0e10cSrcweir || aCol0.getZ() > 1.0 ) 551cdf0e10cSrcweir { 552cdf0e10cSrcweir fy = -F_PI/2.0; 553cdf0e10cSrcweir cy = 0.0; 554cdf0e10cSrcweir } 555cdf0e10cSrcweir else if( ::basegfx::fTools::equal( aCol0.getZ(), -1.0 ) 556cdf0e10cSrcweir || aCol0.getZ() < -1.0 ) 557cdf0e10cSrcweir { 558cdf0e10cSrcweir fy = F_PI/2.0; 559cdf0e10cSrcweir cy = 0.0; 560cdf0e10cSrcweir } 561cdf0e10cSrcweir else 562cdf0e10cSrcweir { 563cdf0e10cSrcweir fy = asin( -aCol0.getZ() ); 564cdf0e10cSrcweir cy = cos(fy); 565cdf0e10cSrcweir } 566cdf0e10cSrcweir 567cdf0e10cSrcweir rRotate.setY(fy); 568cdf0e10cSrcweir if( ::basegfx::fTools::equalZero( cy ) ) 569cdf0e10cSrcweir { 570cdf0e10cSrcweir if( aCol0.getZ() > 0.0 ) 571cdf0e10cSrcweir rRotate.setX(atan2(-1.0*aCol1.getX(), aCol1.getY())); 572cdf0e10cSrcweir else 573cdf0e10cSrcweir rRotate.setX(atan2(aCol1.getX(), aCol1.getY())); 574cdf0e10cSrcweir rRotate.setZ(0.0); 575cdf0e10cSrcweir } 576cdf0e10cSrcweir else 577cdf0e10cSrcweir { 578cdf0e10cSrcweir rRotate.setX(atan2(aCol1.getZ(), aCol2.getZ())); 579cdf0e10cSrcweir rRotate.setZ(atan2(aCol0.getY(), aCol0.getX())); 580cdf0e10cSrcweir } 581cdf0e10cSrcweir 582*45d1b581Smseidel // correct rotate values 583cdf0e10cSrcweir rRotate.correctValues(); 584cdf0e10cSrcweir } 585cdf0e10cSrcweir 586cdf0e10cSrcweir return true; 587cdf0e10cSrcweir } 588cdf0e10cSrcweir } // end of namespace basegfx 589cdf0e10cSrcweir 590*45d1b581Smseidel /* vim: set noet sw=4 ts=4: */ 591