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