xref: /trunk/main/basegfx/source/matrix/b3dhommatrix.cxx (revision 45d1b581a3afed2711c07fe77472516d35fbd7b3)
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