/src/libreoffice/basegfx/source/matrix/b3dhommatrix.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <basegfx/matrix/b3dhommatrix.hxx> |
21 | | #include <basegfx/matrix/hommatrixtemplate.hxx> |
22 | | #include <basegfx/vector/b3dvector.hxx> |
23 | | #include <memory> |
24 | | |
25 | | namespace basegfx |
26 | | { |
27 | | typedef ::basegfx::internal::ImplHomMatrixTemplate< 4 >Impl3DHomMatrix_Base; |
28 | | class Impl3DHomMatrix : public Impl3DHomMatrix_Base |
29 | | { |
30 | | }; |
31 | | |
32 | 130k | B3DHomMatrix::B3DHomMatrix() = default; |
33 | | |
34 | 6.54k | B3DHomMatrix::B3DHomMatrix(const B3DHomMatrix&) = default; |
35 | | |
36 | 0 | B3DHomMatrix::B3DHomMatrix(B3DHomMatrix&&) = default; |
37 | | |
38 | 137k | B3DHomMatrix::~B3DHomMatrix() = default; |
39 | | |
40 | 37.9k | B3DHomMatrix& B3DHomMatrix::operator=(const B3DHomMatrix&) = default; |
41 | | |
42 | 0 | B3DHomMatrix& B3DHomMatrix::operator=(B3DHomMatrix&&) = default; |
43 | | |
44 | | double B3DHomMatrix::get(sal_uInt16 nRow, sal_uInt16 nColumn) const |
45 | 555k | { |
46 | 555k | return mpImpl->get(nRow, nColumn); |
47 | 555k | } |
48 | | |
49 | | void B3DHomMatrix::set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue) |
50 | 382k | { |
51 | 382k | mpImpl->set(nRow, nColumn, fValue); |
52 | 382k | } |
53 | | |
54 | | bool B3DHomMatrix::isLastLineDefault() const |
55 | 28.5k | { |
56 | 28.5k | return mpImpl->isLastLineDefault(); |
57 | 28.5k | } |
58 | | |
59 | | bool B3DHomMatrix::isIdentity() const |
60 | 77.1k | { |
61 | 77.1k | return mpImpl->isIdentity(); |
62 | 77.1k | } |
63 | | |
64 | | void B3DHomMatrix::identity() |
65 | 22.8k | { |
66 | 22.8k | *mpImpl = Impl3DHomMatrix(); |
67 | 22.8k | } |
68 | | |
69 | | void B3DHomMatrix::invert() |
70 | 22.8k | { |
71 | 22.8k | Impl3DHomMatrix aWork(*mpImpl); |
72 | 22.8k | std::unique_ptr<sal_uInt16[]> pIndex( new sal_uInt16[Impl3DHomMatrix_Base::getEdgeLength()] ); |
73 | 22.8k | sal_Int16 nParity; |
74 | | |
75 | 22.8k | if(aWork.ludcmp(pIndex.get(), nParity)) |
76 | 22.8k | { |
77 | 22.8k | mpImpl->doInvert(aWork, pIndex.get()); |
78 | 22.8k | } |
79 | 22.8k | } |
80 | | |
81 | | double B3DHomMatrix::determinant() const |
82 | 0 | { |
83 | 0 | return mpImpl->doDeterminant(); |
84 | 0 | } |
85 | | |
86 | | B3DHomMatrix& B3DHomMatrix::operator+=(const B3DHomMatrix& rMat) |
87 | 0 | { |
88 | 0 | mpImpl->doAddMatrix(*rMat.mpImpl); |
89 | 0 | return *this; |
90 | 0 | } |
91 | | |
92 | | B3DHomMatrix& B3DHomMatrix::operator-=(const B3DHomMatrix& rMat) |
93 | 0 | { |
94 | 0 | mpImpl->doSubMatrix(*rMat.mpImpl); |
95 | 0 | return *this; |
96 | 0 | } |
97 | | |
98 | | B3DHomMatrix& B3DHomMatrix::operator*=(const B3DHomMatrix& rMat) |
99 | 71.2k | { |
100 | 71.2k | if(rMat.isIdentity()) |
101 | 68.2k | { |
102 | | // multiply with identity, no change -> nothing to do |
103 | 68.2k | } |
104 | 3.02k | else if(isIdentity()) |
105 | 2.88k | { |
106 | | // we are identity, result will be rMat -> assign |
107 | 2.88k | *this = rMat; |
108 | 2.88k | } |
109 | 139 | else |
110 | 139 | { |
111 | | // multiply |
112 | 139 | mpImpl->doMulMatrix(*rMat.mpImpl); |
113 | 139 | } |
114 | 71.2k | return *this; |
115 | 71.2k | } |
116 | | |
117 | | bool B3DHomMatrix::operator==(const B3DHomMatrix& rMat) const |
118 | 6.52k | { |
119 | 6.52k | if(mpImpl.same_object(rMat.mpImpl)) |
120 | 0 | return true; |
121 | | |
122 | 6.52k | return mpImpl->isEqual(*rMat.mpImpl); |
123 | 6.52k | } |
124 | | |
125 | | void B3DHomMatrix::rotate(double fAngleX,double fAngleY,double fAngleZ) |
126 | 15.3k | { |
127 | 15.3k | if(fTools::equalZero(fAngleX) && fTools::equalZero(fAngleY) && fTools::equalZero(fAngleZ)) |
128 | 8.56k | return; |
129 | | |
130 | 6.74k | if(!fTools::equalZero(fAngleX)) |
131 | 292 | { |
132 | 292 | Impl3DHomMatrix aRotMatX; |
133 | 292 | double fSin(sin(fAngleX)); |
134 | 292 | double fCos(cos(fAngleX)); |
135 | | |
136 | 292 | aRotMatX.set(1, 1, fCos); |
137 | 292 | aRotMatX.set(2, 2, fCos); |
138 | 292 | aRotMatX.set(2, 1, fSin); |
139 | 292 | aRotMatX.set(1, 2, -fSin); |
140 | | |
141 | 292 | mpImpl->doMulMatrix(aRotMatX); |
142 | 292 | } |
143 | | |
144 | 6.74k | if(!fTools::equalZero(fAngleY)) |
145 | 2.78k | { |
146 | 2.78k | Impl3DHomMatrix aRotMatY; |
147 | 2.78k | double fSin(sin(fAngleY)); |
148 | 2.78k | double fCos(cos(fAngleY)); |
149 | | |
150 | 2.78k | aRotMatY.set(0, 0, fCos); |
151 | 2.78k | aRotMatY.set(2, 2, fCos); |
152 | 2.78k | aRotMatY.set(0, 2, fSin); |
153 | 2.78k | aRotMatY.set(2, 0, -fSin); |
154 | | |
155 | 2.78k | mpImpl->doMulMatrix(aRotMatY); |
156 | 2.78k | } |
157 | | |
158 | 6.74k | if(fTools::equalZero(fAngleZ)) |
159 | 3.01k | return; |
160 | | |
161 | 3.72k | Impl3DHomMatrix aRotMatZ; |
162 | 3.72k | double fSin(sin(fAngleZ)); |
163 | 3.72k | double fCos(cos(fAngleZ)); |
164 | | |
165 | 3.72k | aRotMatZ.set(0, 0, fCos); |
166 | 3.72k | aRotMatZ.set(1, 1, fCos); |
167 | 3.72k | aRotMatZ.set(1, 0, fSin); |
168 | 3.72k | aRotMatZ.set(0, 1, -fSin); |
169 | | |
170 | 3.72k | mpImpl->doMulMatrix(aRotMatZ); |
171 | 3.72k | } |
172 | | |
173 | | void B3DHomMatrix::rotate(const B3DTuple& rRotation) |
174 | 0 | { |
175 | 0 | rotate(rRotation.getX(), rRotation.getY(), rRotation.getZ()); |
176 | 0 | } |
177 | | |
178 | | void B3DHomMatrix::translate(double fX, double fY, double fZ) |
179 | 32.1k | { |
180 | 32.1k | if(!fTools::equalZero(fX) || !fTools::equalZero(fY) || !fTools::equalZero(fZ)) |
181 | 23.6k | { |
182 | 23.6k | Impl3DHomMatrix aTransMat; |
183 | | |
184 | 23.6k | aTransMat.set(0, 3, fX); |
185 | 23.6k | aTransMat.set(1, 3, fY); |
186 | 23.6k | aTransMat.set(2, 3, fZ); |
187 | | |
188 | 23.6k | mpImpl->doMulMatrix(aTransMat); |
189 | 23.6k | } |
190 | 32.1k | } |
191 | | |
192 | | void B3DHomMatrix::translate(const B3DTuple& rRotation) |
193 | 0 | { |
194 | 0 | translate(rRotation.getX(), rRotation.getY(), rRotation.getZ()); |
195 | 0 | } |
196 | | |
197 | | void B3DHomMatrix::scale(double fX, double fY, double fZ) |
198 | 2.32k | { |
199 | 2.32k | const double fOne(1.0); |
200 | | |
201 | 2.32k | if(!fTools::equal(fOne, fX) || !fTools::equal(fOne, fY) ||!fTools::equal(fOne, fZ)) |
202 | 2.32k | { |
203 | 2.32k | Impl3DHomMatrix aScaleMat; |
204 | | |
205 | 2.32k | aScaleMat.set(0, 0, fX); |
206 | 2.32k | aScaleMat.set(1, 1, fY); |
207 | 2.32k | aScaleMat.set(2, 2, fZ); |
208 | | |
209 | 2.32k | mpImpl->doMulMatrix(aScaleMat); |
210 | 2.32k | } |
211 | 2.32k | } |
212 | | |
213 | | void B3DHomMatrix::scale(const B3DTuple& rRotation) |
214 | 0 | { |
215 | 0 | scale(rRotation.getX(), rRotation.getY(), rRotation.getZ()); |
216 | 0 | } |
217 | | |
218 | | void B3DHomMatrix::shearXY(double fSx, double fSy) |
219 | 2.56k | { |
220 | | // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) |
221 | 2.56k | if(!fTools::equalZero(fSx) || !fTools::equalZero(fSy)) |
222 | 2.56k | { |
223 | 2.56k | Impl3DHomMatrix aShearXYMat; |
224 | | |
225 | 2.56k | aShearXYMat.set(0, 2, fSx); |
226 | 2.56k | aShearXYMat.set(1, 2, fSy); |
227 | | |
228 | 2.56k | mpImpl->doMulMatrix(aShearXYMat); |
229 | 2.56k | } |
230 | 2.56k | } |
231 | | |
232 | | void B3DHomMatrix::shearXZ(double fSx, double fSz) |
233 | 0 | { |
234 | | // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) |
235 | 0 | if(!fTools::equalZero(fSx) || !fTools::equalZero(fSz)) |
236 | 0 | { |
237 | 0 | Impl3DHomMatrix aShearXZMat; |
238 | |
|
239 | 0 | aShearXZMat.set(0, 1, fSx); |
240 | 0 | aShearXZMat.set(2, 1, fSz); |
241 | |
|
242 | 0 | mpImpl->doMulMatrix(aShearXZMat); |
243 | 0 | } |
244 | 0 | } |
245 | | void B3DHomMatrix::frustum(double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar) |
246 | 0 | { |
247 | 0 | const double fZero(0.0); |
248 | 0 | const double fOne(1.0); |
249 | |
|
250 | 0 | if(!fTools::more(fNear, fZero)) |
251 | 0 | { |
252 | 0 | fNear = 0.001; |
253 | 0 | } |
254 | |
|
255 | 0 | if(!fTools::more(fFar, fZero)) |
256 | 0 | { |
257 | 0 | fFar = fOne; |
258 | 0 | } |
259 | |
|
260 | 0 | if(fTools::equal(fNear, fFar)) |
261 | 0 | { |
262 | 0 | fFar = fNear + fOne; |
263 | 0 | } |
264 | |
|
265 | 0 | if(fTools::equal(fLeft, fRight)) |
266 | 0 | { |
267 | 0 | fLeft -= fOne; |
268 | 0 | fRight += fOne; |
269 | 0 | } |
270 | |
|
271 | 0 | if(fTools::equal(fTop, fBottom)) |
272 | 0 | { |
273 | 0 | fBottom -= fOne; |
274 | 0 | fTop += fOne; |
275 | 0 | } |
276 | |
|
277 | 0 | Impl3DHomMatrix aFrustumMat; |
278 | |
|
279 | 0 | aFrustumMat.set(0, 0, 2.0 * fNear / (fRight - fLeft)); |
280 | 0 | aFrustumMat.set(1, 1, 2.0 * fNear / (fTop - fBottom)); |
281 | 0 | aFrustumMat.set(0, 2, (fRight + fLeft) / (fRight - fLeft)); |
282 | 0 | aFrustumMat.set(1, 2, (fTop + fBottom) / (fTop - fBottom)); |
283 | 0 | aFrustumMat.set(2, 2, -fOne * ((fFar + fNear) / (fFar - fNear))); |
284 | 0 | aFrustumMat.set(3, 2, -fOne); |
285 | 0 | aFrustumMat.set(2, 3, -fOne * ((2.0 * fFar * fNear) / (fFar - fNear))); |
286 | 0 | aFrustumMat.set(3, 3, fZero); |
287 | |
|
288 | 0 | mpImpl->doMulMatrix(aFrustumMat); |
289 | 0 | } |
290 | | |
291 | | void B3DHomMatrix::ortho(double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar) |
292 | 0 | { |
293 | 0 | if(fTools::equal(fNear, fFar)) |
294 | 0 | { |
295 | 0 | fFar = fNear + 1.0; |
296 | 0 | } |
297 | |
|
298 | 0 | if(fTools::equal(fLeft, fRight)) |
299 | 0 | { |
300 | 0 | fLeft -= 1.0; |
301 | 0 | fRight += 1.0; |
302 | 0 | } |
303 | |
|
304 | 0 | if(fTools::equal(fTop, fBottom)) |
305 | 0 | { |
306 | 0 | fBottom -= 1.0; |
307 | 0 | fTop += 1.0; |
308 | 0 | } |
309 | |
|
310 | 0 | Impl3DHomMatrix aOrthoMat; |
311 | |
|
312 | 0 | aOrthoMat.set(0, 0, 2.0 / (fRight - fLeft)); |
313 | 0 | aOrthoMat.set(1, 1, 2.0 / (fTop - fBottom)); |
314 | 0 | aOrthoMat.set(2, 2, -1.0 * (2.0 / (fFar - fNear))); |
315 | 0 | aOrthoMat.set(0, 3, -1.0 * ((fRight + fLeft) / (fRight - fLeft))); |
316 | 0 | aOrthoMat.set(1, 3, -1.0 * ((fTop + fBottom) / (fTop - fBottom))); |
317 | 0 | aOrthoMat.set(2, 3, -1.0 * ((fFar + fNear) / (fFar - fNear))); |
318 | |
|
319 | 0 | mpImpl->doMulMatrix(aOrthoMat); |
320 | 0 | } |
321 | | |
322 | | void B3DHomMatrix::orientation(const B3DPoint& rVRP, B3DVector aVPN, B3DVector aVUV) |
323 | 0 | { |
324 | 0 | Impl3DHomMatrix aOrientationMat; |
325 | | |
326 | | // translate -VRP |
327 | 0 | aOrientationMat.set(0, 3, -rVRP.getX()); |
328 | 0 | aOrientationMat.set(1, 3, -rVRP.getY()); |
329 | 0 | aOrientationMat.set(2, 3, -rVRP.getZ()); |
330 | | |
331 | | // build rotation |
332 | 0 | aVUV.normalize(); |
333 | 0 | aVPN.normalize(); |
334 | | |
335 | | // build x-axis as perpendicular from aVUV and aVPN |
336 | 0 | B3DVector aRx(aVUV.getPerpendicular(aVPN)); |
337 | 0 | aRx.normalize(); |
338 | | |
339 | | // y-axis perpendicular to that |
340 | 0 | B3DVector aRy(aVPN.getPerpendicular(aRx)); |
341 | 0 | aRy.normalize(); |
342 | | |
343 | | // the calculated normals are the line vectors of the rotation matrix, |
344 | | // set them to create rotation |
345 | 0 | aOrientationMat.set(0, 0, aRx.getX()); |
346 | 0 | aOrientationMat.set(0, 1, aRx.getY()); |
347 | 0 | aOrientationMat.set(0, 2, aRx.getZ()); |
348 | 0 | aOrientationMat.set(1, 0, aRy.getX()); |
349 | 0 | aOrientationMat.set(1, 1, aRy.getY()); |
350 | 0 | aOrientationMat.set(1, 2, aRy.getZ()); |
351 | 0 | aOrientationMat.set(2, 0, aVPN.getX()); |
352 | 0 | aOrientationMat.set(2, 1, aVPN.getY()); |
353 | 0 | aOrientationMat.set(2, 2, aVPN.getZ()); |
354 | |
|
355 | 0 | mpImpl->doMulMatrix(aOrientationMat); |
356 | 0 | } |
357 | | |
358 | | void B3DHomMatrix::decompose(B3DTuple& rScale, B3DTuple& rTranslate, B3DTuple& rRotate, B3DTuple& rShear) const |
359 | 0 | { |
360 | | // when perspective is used, decompose is not made here |
361 | 0 | if(!mpImpl->isLastLineDefault()) |
362 | 0 | return; |
363 | | |
364 | | // If determinant is zero, decomposition is not possible |
365 | 0 | if(determinant() == 0.0) |
366 | 0 | return; |
367 | | |
368 | | // isolate translation |
369 | 0 | rTranslate.setX(mpImpl->get(0, 3)); |
370 | 0 | rTranslate.setY(mpImpl->get(1, 3)); |
371 | 0 | rTranslate.setZ(mpImpl->get(2, 3)); |
372 | | |
373 | | // correct translate values |
374 | 0 | rTranslate.correctValues(); |
375 | | |
376 | | // get scale and shear |
377 | 0 | B3DVector aCol0(mpImpl->get(0, 0), mpImpl->get(1, 0), mpImpl->get(2, 0)); |
378 | 0 | B3DVector aCol1(mpImpl->get(0, 1), mpImpl->get(1, 1), mpImpl->get(2, 1)); |
379 | 0 | B3DVector aCol2(mpImpl->get(0, 2), mpImpl->get(1, 2), mpImpl->get(2, 2)); |
380 | 0 | B3DVector aTemp; |
381 | | |
382 | | // get ScaleX |
383 | 0 | rScale.setX(aCol0.getLength()); |
384 | 0 | aCol0.normalize(); |
385 | | |
386 | | // get ShearXY |
387 | 0 | rShear.setX(aCol0.scalar(aCol1)); |
388 | |
|
389 | 0 | if(fTools::equalZero(rShear.getX())) |
390 | 0 | { |
391 | 0 | rShear.setX(0.0); |
392 | 0 | } |
393 | 0 | else |
394 | 0 | { |
395 | 0 | aTemp.setX(aCol1.getX() - rShear.getX() * aCol0.getX()); |
396 | 0 | aTemp.setY(aCol1.getY() - rShear.getX() * aCol0.getY()); |
397 | 0 | aTemp.setZ(aCol1.getZ() - rShear.getX() * aCol0.getZ()); |
398 | 0 | aCol1 = aTemp; |
399 | 0 | } |
400 | | |
401 | | // get ScaleY |
402 | 0 | rScale.setY(aCol1.getLength()); |
403 | 0 | aCol1.normalize(); |
404 | |
|
405 | 0 | const double fShearX(rShear.getX()); |
406 | |
|
407 | 0 | if(!fTools::equalZero(fShearX)) |
408 | 0 | { |
409 | 0 | rShear.setX(rShear.getX() / rScale.getY()); |
410 | 0 | } |
411 | | |
412 | | // get ShearXZ |
413 | 0 | rShear.setY(aCol0.scalar(aCol2)); |
414 | |
|
415 | 0 | if(fTools::equalZero(rShear.getY())) |
416 | 0 | { |
417 | 0 | rShear.setY(0.0); |
418 | 0 | } |
419 | 0 | else |
420 | 0 | { |
421 | 0 | aTemp.setX(aCol2.getX() - rShear.getY() * aCol0.getX()); |
422 | 0 | aTemp.setY(aCol2.getY() - rShear.getY() * aCol0.getY()); |
423 | 0 | aTemp.setZ(aCol2.getZ() - rShear.getY() * aCol0.getZ()); |
424 | 0 | aCol2 = aTemp; |
425 | 0 | } |
426 | | |
427 | | // get ShearYZ |
428 | 0 | rShear.setZ(aCol1.scalar(aCol2)); |
429 | |
|
430 | 0 | if(fTools::equalZero(rShear.getZ())) |
431 | 0 | { |
432 | 0 | rShear.setZ(0.0); |
433 | 0 | } |
434 | 0 | else |
435 | 0 | { |
436 | 0 | aTemp.setX(aCol2.getX() - rShear.getZ() * aCol1.getX()); |
437 | 0 | aTemp.setY(aCol2.getY() - rShear.getZ() * aCol1.getY()); |
438 | 0 | aTemp.setZ(aCol2.getZ() - rShear.getZ() * aCol1.getZ()); |
439 | 0 | aCol2 = aTemp; |
440 | 0 | } |
441 | | |
442 | | // get ScaleZ |
443 | 0 | rScale.setZ(aCol2.getLength()); |
444 | 0 | aCol2.normalize(); |
445 | |
|
446 | 0 | const double fShearY(rShear.getY()); |
447 | |
|
448 | 0 | if(!fTools::equalZero(fShearY)) |
449 | 0 | { |
450 | 0 | rShear.setY(rShear.getY() / rScale.getZ()); |
451 | 0 | } |
452 | |
|
453 | 0 | const double fShearZ(rShear.getZ()); |
454 | |
|
455 | 0 | if(!fTools::equalZero(fShearZ)) |
456 | 0 | { |
457 | 0 | rShear.setZ(rShear.getZ() / rScale.getZ()); |
458 | 0 | } |
459 | | |
460 | | // correct shear values |
461 | 0 | rShear.correctValues(); |
462 | | |
463 | | // Coordinate system flip? |
464 | 0 | if(0.0 > aCol0.scalar(aCol1.getPerpendicular(aCol2))) |
465 | 0 | { |
466 | 0 | rScale = -rScale; |
467 | 0 | aCol0 = -aCol0; |
468 | 0 | aCol1 = -aCol1; |
469 | 0 | aCol2 = -aCol2; |
470 | 0 | } |
471 | | |
472 | | // correct scale values |
473 | 0 | rScale.correctValues(1.0); |
474 | | |
475 | | // Get rotations |
476 | 0 | { |
477 | 0 | double fy=0; |
478 | 0 | double cy=0; |
479 | |
|
480 | 0 | if( ::basegfx::fTools::equal( aCol0.getZ(), 1.0 ) |
481 | 0 | || aCol0.getZ() > 1.0 ) |
482 | 0 | { |
483 | 0 | fy = -M_PI/2.0; |
484 | 0 | cy = 0.0; |
485 | 0 | } |
486 | 0 | else if( ::basegfx::fTools::equal( aCol0.getZ(), -1.0 ) |
487 | 0 | || aCol0.getZ() < -1.0 ) |
488 | 0 | { |
489 | 0 | fy = M_PI/2.0; |
490 | 0 | cy = 0.0; |
491 | 0 | } |
492 | 0 | else |
493 | 0 | { |
494 | 0 | fy = asin( -aCol0.getZ() ); |
495 | 0 | cy = cos(fy); |
496 | 0 | } |
497 | |
|
498 | 0 | rRotate.setY(fy); |
499 | 0 | if( ::basegfx::fTools::equalZero( cy ) ) |
500 | 0 | { |
501 | 0 | if( aCol0.getZ() > 0.0 ) |
502 | 0 | rRotate.setX(atan2(-1.0*aCol1.getX(), aCol1.getY())); |
503 | 0 | else |
504 | 0 | rRotate.setX(atan2(aCol1.getX(), aCol1.getY())); |
505 | 0 | rRotate.setZ(0.0); |
506 | 0 | } |
507 | 0 | else |
508 | 0 | { |
509 | 0 | rRotate.setX(atan2(aCol1.getZ(), aCol2.getZ())); |
510 | 0 | rRotate.setZ(atan2(aCol0.getY(), aCol0.getX())); |
511 | 0 | } |
512 | | |
513 | | // correct rotate values |
514 | 0 | rRotate.correctValues(); |
515 | 0 | } |
516 | 0 | } |
517 | | } // end of namespace basegfx |
518 | | |
519 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |