Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / drawinglayer / source / geometry / viewinformation3d.cxx
blob19dd8022deaa1e3970c60befbcae9b218b957dab
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <drawinglayer/geometry/viewinformation3d.hxx>
21 #include <basegfx/range/b3drange.hxx>
22 #include <basegfx/matrix/b3dhommatrix.hxx>
23 #include <com/sun/star/geometry/AffineMatrix3D.hpp>
24 #include <com/sun/star/geometry/RealRectangle3D.hpp>
25 #include <basegfx/tools/canvastools.hxx>
26 #include <rtl/instance.hxx>
29 using namespace com::sun::star;
32 namespace drawinglayer
34 namespace geometry
36 /** Implementation class for ViewInformation3D
38 class ImpViewInformation3D
40 private:
41 // ViewInformation3D implementation can change refcount, so we have only
42 // two memory regions for pairs of ViewInformation3D/ImpViewInformation3D
43 friend class ::drawinglayer::geometry::ViewInformation3D;
45 // the 3D transformations
46 // Object to World. This may change and being adapted when entering 3D transformation
47 // groups
48 basegfx::B3DHomMatrix maObjectTransformation;
50 // World to Camera. This includes VRP, VPN and VUV camera coordinate system
51 basegfx::B3DHomMatrix maOrientation;
53 // Camera to Device with X,Y and Z [-1.0 .. 1.0]. This is the
54 // 3D to 2D projection which may be parallel or perspective. When it is perspective,
55 // the last line of the homogen matrix will NOT be unused
56 basegfx::B3DHomMatrix maProjection;
58 // Device to View with X,Y and Z [0.0 .. 1.0]. This converts from -1 to 1 coordinates
59 // in camera coordinate system to 0 to 1 in unit 2D coordinates. This way it stays
60 // view-independent. To get discrete coordinates, the 2D transformation of a scene
61 // as 2D object needs to be involved
62 basegfx::B3DHomMatrix maDeviceToView;
64 // Object to View is the linear combination of all four transformations. It's
65 // buffered to avoid too much matrix multiplying and created on demand
66 basegfx::B3DHomMatrix maObjectToView;
68 // the point in time
69 double mfViewTime;
71 // the complete PropertyValue representation (if already created)
72 uno::Sequence< beans::PropertyValue > mxViewInformation;
74 // the extra PropertyValues; does not contain the transformations
75 uno::Sequence< beans::PropertyValue > mxExtendedInformation;
77 // the local UNO API strings
78 static OUString getNamePropertyObjectTransformation()
80 return OUString("ObjectTransformation");
83 static OUString getNamePropertyOrientation()
85 return OUString("Orientation");
88 static OUString getNamePropertyProjection()
90 return OUString("Projection");
93 static OUString getNamePropertyProjection_30()
95 return OUString("Projection30");
98 static OUString getNamePropertyProjection_31()
100 return OUString("Projection31");
103 static OUString getNamePropertyProjection_32()
105 return OUString("Projection32");
108 static OUString getNamePropertyProjection_33()
110 return OUString("Projection33");
113 static OUString getNamePropertyDeviceToView()
115 return OUString("DeviceToView");
118 static OUString getNamePropertyTime()
120 return OUString("Time");
123 // a central PropertyValue parsing method to allow transportatin of
124 // all ViewParameters using UNO API
125 void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters)
127 if(rViewParameters.hasElements())
129 const sal_Int32 nCount(rViewParameters.getLength());
130 sal_Int32 nExtendedInsert(0);
132 // prepare extended information for filtering. Maximum size is nCount
133 mxExtendedInformation.realloc(nCount);
135 for(sal_Int32 a(0); a < nCount; a++)
137 const beans::PropertyValue& rProp = rViewParameters[a];
139 if(rProp.Name == getNamePropertyObjectTransformation())
141 css::geometry::AffineMatrix3D aAffineMatrix3D;
142 rProp.Value >>= aAffineMatrix3D;
143 maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
145 else if(rProp.Name == getNamePropertyOrientation())
147 css::geometry::AffineMatrix3D aAffineMatrix3D;
148 rProp.Value >>= aAffineMatrix3D;
149 maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
151 else if(rProp.Name == getNamePropertyProjection())
153 // projection may be defined using a frustum in which case the last line of
154 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
155 // these four values need to be treated extra
156 const double f_30(maProjection.get(3, 0));
157 const double f_31(maProjection.get(3, 1));
158 const double f_32(maProjection.get(3, 2));
159 const double f_33(maProjection.get(3, 3));
161 css::geometry::AffineMatrix3D aAffineMatrix3D;
162 rProp.Value >>= aAffineMatrix3D;
163 maProjection = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
165 maProjection.set(3, 0, f_30);
166 maProjection.set(3, 1, f_31);
167 maProjection.set(3, 2, f_32);
168 maProjection.set(3, 3, f_33);
170 else if(rProp.Name == getNamePropertyProjection_30())
172 double f_30(0.0);
173 rProp.Value >>= f_30;
174 maProjection.set(3, 0, f_30);
176 else if(rProp.Name == getNamePropertyProjection_31())
178 double f_31(0.0);
179 rProp.Value >>= f_31;
180 maProjection.set(3, 1, f_31);
182 else if(rProp.Name == getNamePropertyProjection_32())
184 double f_32(0.0);
185 rProp.Value >>= f_32;
186 maProjection.set(3, 2, f_32);
188 else if(rProp.Name == getNamePropertyProjection_33())
190 double f_33(1.0);
191 rProp.Value >>= f_33;
192 maProjection.set(3, 3, f_33);
194 else if(rProp.Name == getNamePropertyDeviceToView())
196 css::geometry::AffineMatrix3D aAffineMatrix3D;
197 rProp.Value >>= aAffineMatrix3D;
198 maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
200 else if(rProp.Name == getNamePropertyTime())
202 rProp.Value >>= mfViewTime;
204 else
206 // extra information; add to filtered information
207 mxExtendedInformation[nExtendedInsert++] = rProp;
211 // extra information size is now known; realloc to final size
212 mxExtendedInformation.realloc(nExtendedInsert);
216 // central method to create a Sequence of PropertyValues containing he complete
217 // data set
218 void impFillViewInformationFromContent()
220 const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
221 const bool bOrientationUsed(!maOrientation.isIdentity());
222 const bool bProjectionUsed(!maProjection.isIdentity());
223 const bool bDeviceToViewUsed(!maDeviceToView.isIdentity());
224 const bool bTimeUsed(0.0 < mfViewTime);
225 const bool bExtraInformation(mxExtendedInformation.hasElements());
227 // projection may be defined using a frustum in which case the last line of
228 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
229 // these four values need to be treated extra
230 const bool bProjectionUsed_30(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 0)));
231 const bool bProjectionUsed_31(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 1)));
232 const bool bProjectionUsed_32(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 2)));
233 const bool bProjectionUsed_33(bProjectionUsed && !basegfx::fTools::equal(maProjection.get(3, 3), 1.0));
235 sal_uInt32 nIndex(0);
236 const sal_uInt32 nCount(
237 (bObjectTransformationUsed ? 1 : 0) +
238 (bOrientationUsed ? 1 : 0) +
239 (bProjectionUsed ? 1 : 0) +
240 (bProjectionUsed_30 ? 1 : 0) +
241 (bProjectionUsed_31 ? 1 : 0) +
242 (bProjectionUsed_32 ? 1 : 0) +
243 (bProjectionUsed_33 ? 1 : 0) +
244 (bDeviceToViewUsed ? 1 : 0) +
245 (bTimeUsed ? 1 : 0) +
246 (bExtraInformation ? mxExtendedInformation.getLength() : 0));
248 mxViewInformation.realloc(nCount);
250 if(bObjectTransformationUsed)
252 css::geometry::AffineMatrix3D aAffineMatrix3D;
253 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maObjectTransformation);
254 mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation();
255 mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
256 nIndex++;
259 if(bOrientationUsed)
261 css::geometry::AffineMatrix3D aAffineMatrix3D;
262 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maOrientation);
263 mxViewInformation[nIndex].Name = getNamePropertyOrientation();
264 mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
265 nIndex++;
268 if(bProjectionUsed)
270 css::geometry::AffineMatrix3D aAffineMatrix3D;
271 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maProjection);
272 mxViewInformation[nIndex].Name = getNamePropertyProjection();
273 mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
274 nIndex++;
277 if(bProjectionUsed_30)
279 mxViewInformation[nIndex].Name = getNamePropertyProjection_30();
280 mxViewInformation[nIndex].Value <<= maProjection.get(3, 0);
281 nIndex++;
284 if(bProjectionUsed_31)
286 mxViewInformation[nIndex].Name = getNamePropertyProjection_31();
287 mxViewInformation[nIndex].Value <<= maProjection.get(3, 1);
288 nIndex++;
291 if(bProjectionUsed_32)
293 mxViewInformation[nIndex].Name = getNamePropertyProjection_32();
294 mxViewInformation[nIndex].Value <<= maProjection.get(3, 2);
295 nIndex++;
298 if(bProjectionUsed_33)
300 mxViewInformation[nIndex].Name = getNamePropertyProjection_33();
301 mxViewInformation[nIndex].Value <<= maProjection.get(3, 3);
302 nIndex++;
305 if(bDeviceToViewUsed)
307 css::geometry::AffineMatrix3D aAffineMatrix3D;
308 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maDeviceToView);
309 mxViewInformation[nIndex].Name = getNamePropertyDeviceToView();
310 mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
311 nIndex++;
314 if(bTimeUsed)
316 mxViewInformation[nIndex].Name = getNamePropertyTime();
317 mxViewInformation[nIndex].Value <<= mfViewTime;
318 nIndex++;
321 if(bExtraInformation)
323 const sal_Int32 nExtra(mxExtendedInformation.getLength());
325 for(sal_Int32 a(0); a < nExtra; a++)
327 mxViewInformation[nIndex++] = mxExtendedInformation[a];
332 public:
333 ImpViewInformation3D(
334 const basegfx::B3DHomMatrix& rObjectTransformation,
335 const basegfx::B3DHomMatrix& rOrientation,
336 const basegfx::B3DHomMatrix& rProjection,
337 const basegfx::B3DHomMatrix& rDeviceToView,
338 double fViewTime,
339 const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
340 : maObjectTransformation(rObjectTransformation),
341 maOrientation(rOrientation),
342 maProjection(rProjection),
343 maDeviceToView(rDeviceToView),
344 mfViewTime(fViewTime),
345 mxViewInformation(),
346 mxExtendedInformation()
348 impInterpretPropertyValues(rExtendedParameters);
351 explicit ImpViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
352 : maObjectTransformation(),
353 maOrientation(),
354 maProjection(),
355 maDeviceToView(),
356 mfViewTime(),
357 mxViewInformation(rViewParameters),
358 mxExtendedInformation()
360 impInterpretPropertyValues(rViewParameters);
363 ImpViewInformation3D()
364 : maObjectTransformation(),
365 maOrientation(),
366 maProjection(),
367 maDeviceToView(),
368 mfViewTime(),
369 mxViewInformation(),
370 mxExtendedInformation()
374 const basegfx::B3DHomMatrix& getObjectTransformation() const { return maObjectTransformation; }
375 const basegfx::B3DHomMatrix& getOrientation() const { return maOrientation; }
376 const basegfx::B3DHomMatrix& getProjection() const { return maProjection; }
377 const basegfx::B3DHomMatrix& getDeviceToView() const { return maDeviceToView; }
378 double getViewTime() const { return mfViewTime; }
380 const basegfx::B3DHomMatrix& getObjectToView() const
382 // on demand WorldToView creation
384 if(maObjectToView.isIdentity())
386 const_cast< ImpViewInformation3D* >(this)->maObjectToView = maDeviceToView * maProjection * maOrientation * maObjectTransformation;
389 return maObjectToView;
392 const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const
394 if(!mxViewInformation.hasElements())
396 const_cast< ImpViewInformation3D* >(this)->impFillViewInformationFromContent();
399 return mxViewInformation;
402 const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
404 return mxExtendedInformation;
407 bool operator==(const ImpViewInformation3D& rCandidate) const
409 return (maObjectTransformation == rCandidate.maObjectTransformation
410 && maOrientation == rCandidate.maOrientation
411 && maProjection == rCandidate.maProjection
412 && maDeviceToView == rCandidate.maDeviceToView
413 && mfViewTime == rCandidate.mfViewTime
414 && mxExtendedInformation == rCandidate.mxExtendedInformation);
417 } // end of anonymous namespace
418 } // end of namespace drawinglayer
421 namespace drawinglayer
423 namespace geometry
425 namespace
427 struct theGlobalDefault :
428 public rtl::Static< ViewInformation3D::ImplType, theGlobalDefault > {};
431 ViewInformation3D::ViewInformation3D(
432 const basegfx::B3DHomMatrix& rObjectObjectTransformation,
433 const basegfx::B3DHomMatrix& rOrientation,
434 const basegfx::B3DHomMatrix& rProjection,
435 const basegfx::B3DHomMatrix& rDeviceToView,
436 double fViewTime,
437 const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
438 : mpViewInformation3D(ImpViewInformation3D(
439 rObjectObjectTransformation, rOrientation, rProjection,
440 rDeviceToView, fViewTime, rExtendedParameters))
444 ViewInformation3D::ViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
445 : mpViewInformation3D(ImpViewInformation3D(rViewParameters))
449 ViewInformation3D::ViewInformation3D()
450 : mpViewInformation3D(theGlobalDefault::get())
454 ViewInformation3D::ViewInformation3D(const ViewInformation3D& rCandidate)
455 : mpViewInformation3D(rCandidate.mpViewInformation3D)
459 ViewInformation3D::~ViewInformation3D()
463 bool ViewInformation3D::isDefault() const
465 return mpViewInformation3D.same_object(theGlobalDefault::get());
468 ViewInformation3D& ViewInformation3D::operator=(const ViewInformation3D& rCandidate)
470 mpViewInformation3D = rCandidate.mpViewInformation3D;
471 return *this;
474 bool ViewInformation3D::operator==(const ViewInformation3D& rCandidate) const
476 return rCandidate.mpViewInformation3D == mpViewInformation3D;
479 const basegfx::B3DHomMatrix& ViewInformation3D::getObjectTransformation() const
481 return mpViewInformation3D->getObjectTransformation();
484 const basegfx::B3DHomMatrix& ViewInformation3D::getOrientation() const
486 return mpViewInformation3D->getOrientation();
489 const basegfx::B3DHomMatrix& ViewInformation3D::getProjection() const
491 return mpViewInformation3D->getProjection();
494 const basegfx::B3DHomMatrix& ViewInformation3D::getDeviceToView() const
496 return mpViewInformation3D->getDeviceToView();
499 const basegfx::B3DHomMatrix& ViewInformation3D::getObjectToView() const
501 return mpViewInformation3D->getObjectToView();
504 double ViewInformation3D::getViewTime() const
506 return mpViewInformation3D->getViewTime();
509 const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getViewInformationSequence() const
511 return mpViewInformation3D->getViewInformationSequence();
514 const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getExtendedInformationSequence() const
516 return mpViewInformation3D->getExtendedInformationSequence();
518 } // end of namespace geometry
519 } // end of namespace drawinglayer
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */