1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <o3tl/numeric.hxx>
22 #include <svx/strings.hrc>
23 #include <svx/dialmgr.hxx>
24 #include <svx/svdhdl.hxx>
25 #include <svx/svdmodel.hxx>
26 #include <svx/svdobjkind.hxx>
27 #include <svx/scene3d.hxx>
28 #include <svx/obj3d.hxx>
29 #include <sdr/properties/e3dproperties.hxx>
30 #include <sdr/properties/e3dcompoundproperties.hxx>
31 #include <basegfx/polygon/b3dpolypolygontools.hxx>
32 #include <basegfx/point/b3dpoint.hxx>
33 #include <basegfx/matrix/b3dhommatrix.hxx>
34 #include <basegfx/matrix/b2dhommatrix.hxx>
35 #include <basegfx/polygon/b2dpolypolygontools.hxx>
36 #include <svx/helperhittest3d.hxx>
37 #include <sdr/contact/viewcontactofe3d.hxx>
38 #include <drawinglayer/geometry/viewinformation3d.hxx>
39 #include <com/sun/star/uno/Sequence.h>
40 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
41 #include <svx/e3dsceneupdater.hxx>
42 #include <comphelper/configuration.hxx>
44 using namespace com::sun::star
;
46 std::unique_ptr
<sdr::properties::BaseProperties
> E3dObject::CreateObjectSpecificProperties()
48 return std::make_unique
<sdr::properties::E3dProperties
>(*this);
51 E3dObject::E3dObject(SdrModel
& rSdrModel
)
52 : SdrAttrObj(rSdrModel
),
60 E3dObject::E3dObject(SdrModel
& rSdrModel
, E3dObject
const & rSource
)
61 : SdrAttrObj(rSdrModel
, rSource
),
68 // BoundVol can be copied since also the children are copied
69 maLocalBoundVol
= rSource
.maLocalBoundVol
;
70 maTransformation
= rSource
.maTransformation
;
72 // Because the parent may have changed, definitely redefine the total
73 // transformation next time
74 SetTransformChanged();
76 // Copy selection status
77 mbIsSelected
= rSource
.mbIsSelected
;
80 E3dObject::~E3dObject()
84 void E3dObject::SetSelected(bool bNew
)
86 if(mbIsSelected
!= bNew
)
92 // Break, default implementations
93 bool E3dObject::IsBreakObjPossible()
98 rtl::Reference
<SdrAttrObj
> E3dObject::GetBreakObj()
103 SdrInventor
E3dObject::GetObjInventor() const
105 return SdrInventor::E3d
;
108 SdrObjKind
E3dObject::GetObjIdentifier() const
110 return SdrObjKind::E3D_Object
;
113 // Determine the capabilities of the object
114 void E3dObject::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
116 rInfo
.bResizeFreeAllowed
= true;
117 rInfo
.bResizePropAllowed
= true;
118 rInfo
.bRotateFreeAllowed
= true;
119 rInfo
.bRotate90Allowed
= true;
120 rInfo
.bMirrorFreeAllowed
= false;
121 rInfo
.bMirror45Allowed
= false;
122 rInfo
.bMirror90Allowed
= false;
123 rInfo
.bShearAllowed
= false;
124 rInfo
.bEdgeRadiusAllowed
= false;
125 rInfo
.bCanConvToPath
= false;
127 // no transparence for 3d objects
128 rInfo
.bTransparenceAllowed
= false;
130 // Convert 3D objects in a group of polygons:
131 // At first not only possible, because the creation of a group of
132 // 2D polygons would be required which need to be sorted by depth,
133 // ie at intersections be cut relative to each other. Also the texture
134 // coordinates were an unsolved problem.
135 rInfo
.bCanConvToPoly
= false;
136 rInfo
.bCanConvToContour
= false;
137 rInfo
.bCanConvToPathLineToArea
= false;
138 rInfo
.bCanConvToPolyLineToArea
= false;
141 // resize object, used from old 2d interfaces, e.g. in Move/Scale dialog (F4)
142 void E3dObject::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
144 // Movement in X, Y in the eye coordinate system
145 E3dScene
* pScene(getRootE3dSceneFromE3dObject());
147 if(nullptr == pScene
)
152 // transform pos from 2D world to 3D eye
153 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pScene
->GetViewContact());
154 const drawinglayer::geometry::ViewInformation3D
& aViewInfo3D(rVCScene
.getViewInformation3D());
155 basegfx::B2DPoint
aScaleCenter2D(static_cast<double>(rRef
.X()), static_cast<double>(rRef
.Y()));
156 basegfx::B2DHomMatrix
aInverseSceneTransform(rVCScene
.getObjectTransformation());
158 aInverseSceneTransform
.invert();
159 aScaleCenter2D
= aInverseSceneTransform
* aScaleCenter2D
;
161 basegfx::B3DPoint
aScaleCenter3D(aScaleCenter2D
.getX(), aScaleCenter2D
.getY(), 0.5);
162 basegfx::B3DHomMatrix
aInverseViewToEye(aViewInfo3D
.getDeviceToView() * aViewInfo3D
.getProjection());
164 aInverseViewToEye
.invert();
165 aScaleCenter3D
= aInverseViewToEye
* aScaleCenter3D
;
168 double fScaleX(xFact
);
169 double fScaleY(yFact
);
172 basegfx::B3DHomMatrix
aInverseOrientation(aViewInfo3D
.getOrientation());
173 aInverseOrientation
.invert();
174 basegfx::B3DHomMatrix
aFullTransform(GetFullTransform());
175 basegfx::B3DHomMatrix
aTrans(aFullTransform
);
177 aTrans
*= aViewInfo3D
.getOrientation();
178 aTrans
.translate(-aScaleCenter3D
.getX(), -aScaleCenter3D
.getY(), -aScaleCenter3D
.getZ());
179 aTrans
.scale(fScaleX
, fScaleY
, 1.0);
180 aTrans
.translate(aScaleCenter3D
.getX(), aScaleCenter3D
.getY(), aScaleCenter3D
.getZ());
181 aTrans
*= aInverseOrientation
;
182 aFullTransform
.invert();
183 aTrans
*= aFullTransform
;
186 basegfx::B3DHomMatrix
aObjTrans(GetTransform());
189 E3DModifySceneSnapRectUpdater
aUpdater(this);
190 SetTransform(aObjTrans
);
193 // Move object in 2D is needed when using cursor keys
194 void E3dObject::NbcMove(const Size
& rSize
)
196 // Movement in X, Y in the eye coordinate system
197 E3dScene
* pScene(getRootE3dSceneFromE3dObject());
199 if(nullptr == pScene
)
204 //Dimensions of the scene in 3D and 2D for comparison
205 tools::Rectangle aRect
= pScene
->GetSnapRect();
206 basegfx::B3DHomMatrix aInvDispTransform
;
207 E3dScene
* pParent(getParentE3dSceneFromE3dObject());
209 if(nullptr != pParent
)
211 aInvDispTransform
= pParent
->GetFullTransform();
212 aInvDispTransform
.invert();
215 // BoundVolume from 3d world to 3d eye
216 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pScene
->GetViewContact());
217 const drawinglayer::geometry::ViewInformation3D
& aViewInfo3D(rVCScene
.getViewInformation3D());
218 basegfx::B3DRange
aEyeVol(pScene
->GetBoundVolume());
219 aEyeVol
.transform(aViewInfo3D
.getOrientation());
221 if ((aRect
.GetWidth() == 0) || (aRect
.GetHeight() == 0))
222 throw o3tl::divide_by_zero();
224 // build relative movement vector in eye coordinates
225 basegfx::B3DPoint
aMove(
226 static_cast<double>(rSize
.Width()) * aEyeVol
.getWidth() / static_cast<double>(aRect
.GetWidth()),
227 static_cast<double>(-rSize
.Height()) * aEyeVol
.getHeight() / static_cast<double>(aRect
.GetHeight()),
229 basegfx::B3DPoint
aPos(0.0, 0.0, 0.0);
231 // movement vector to local coordinates of objects' parent
232 basegfx::B3DHomMatrix
aInverseOrientation(aViewInfo3D
.getOrientation());
233 aInverseOrientation
.invert();
234 basegfx::B3DHomMatrix
aCompleteTrans(aInvDispTransform
* aInverseOrientation
);
236 aMove
= aCompleteTrans
* aMove
;
237 aPos
= aCompleteTrans
* aPos
;
239 // build transformation and apply
240 basegfx::B3DHomMatrix aTranslate
;
241 aTranslate
.translate(aMove
.getX() - aPos
.getX(), aMove
.getY() - aPos
.getY(), aMove
.getZ() - aPos
.getZ());
243 E3DModifySceneSnapRectUpdater
aUpdater(pScene
);
244 SetTransform(aTranslate
* GetTransform());
247 void E3dObject::RecalcSnapRect()
249 maSnapRect
= tools::Rectangle();
252 // Inform parent of changes in the structure (eg by transformation), in this
253 // process the object in which the change has occurred is returned.
254 void E3dObject::StructureChanged()
256 E3dScene
* pParent(getParentE3dSceneFromE3dObject());
258 if(nullptr != pParent
)
260 pParent
->InvalidateBoundVolume();
261 pParent
->StructureChanged();
265 E3dScene
* E3dObject::getParentE3dSceneFromE3dObject() const
267 return DynCastE3dScene(getParentSdrObjectFromSdrObject());
270 // Determine the top-level scene object
271 E3dScene
* E3dObject::getRootE3dSceneFromE3dObject() const
273 E3dScene
* pParent(getParentE3dSceneFromE3dObject());
275 if(nullptr != pParent
)
277 return pParent
->getRootE3dSceneFromE3dObject();
283 // Calculate enclosed volume, including all child objects
284 basegfx::B3DRange
E3dObject::RecalcBoundVolume() const
286 basegfx::B3DRange aRetval
;
287 if (comphelper::IsFuzzing()) // skip slow path for fuzzing
290 const sdr::contact::ViewContactOfE3d
* pVCOfE3D
= dynamic_cast< const sdr::contact::ViewContactOfE3d
* >(&GetViewContact());
294 // BoundVolume is without 3D object transformation, use correct sequence
295 const drawinglayer::primitive3d::Primitive3DContainer
& xLocalSequence(pVCOfE3D
->getVIP3DSWithoutObjectTransform());
297 if(!xLocalSequence
.empty())
299 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
300 const drawinglayer::geometry::ViewInformation3D
aLocalViewInformation3D(aEmptyParameters
);
302 aRetval
= xLocalSequence
.getB3DRange(aLocalViewInformation3D
);
309 // Get enclosed volume and possibly recalculate it
310 const basegfx::B3DRange
& E3dObject::GetBoundVolume() const
312 if(maLocalBoundVol
.isEmpty())
314 const_cast< E3dObject
* >(this)->maLocalBoundVol
= RecalcBoundVolume();
317 return maLocalBoundVol
;
320 void E3dObject::InvalidateBoundVolume()
322 maLocalBoundVol
.reset();
325 // Pass on the changes in transformation to all child objects
326 void E3dObject::SetTransformChanged()
328 InvalidateBoundVolume();
329 mbTfHasChanged
= true;
332 // Define the hierarchical transformation over all Parents, store in
333 // maFullTransform and return them
334 const basegfx::B3DHomMatrix
& E3dObject::GetFullTransform() const
338 basegfx::B3DHomMatrix
aNewFullTransformation(maTransformation
);
339 E3dScene
* pParent(getParentE3dSceneFromE3dObject());
341 if(nullptr != pParent
)
343 aNewFullTransformation
= pParent
->GetFullTransform() * aNewFullTransformation
;
346 const_cast< E3dObject
* >(this)->maFullTransform
= std::move(aNewFullTransformation
);
347 const_cast< E3dObject
* >(this)->mbTfHasChanged
= false;
350 return maFullTransform
;
353 void E3dObject::NbcSetTransform(const basegfx::B3DHomMatrix
& rMatrix
)
355 if(maTransformation
!= rMatrix
)
357 maTransformation
= rMatrix
;
358 SetTransformChanged();
363 // Set transformation matrix with repaint broadcast
364 void E3dObject::SetTransform(const basegfx::B3DHomMatrix
& rMatrix
)
366 if(rMatrix
!= maTransformation
)
368 NbcSetTransform(rMatrix
);
370 BroadcastObjectChange();
371 if (m_pUserCall
!= nullptr) m_pUserCall
->Changed(*this, SdrUserCallType::Resize
, tools::Rectangle());
375 basegfx::B3DPolyPolygon
E3dObject::CreateWireframe() const
377 const basegfx::B3DRange
aBoundVolume(GetBoundVolume());
378 return basegfx::utils::createCubePolyPolygonFromB3DRange(aBoundVolume
);
381 // Get the name of the object (singular)
382 OUString
E3dObject::TakeObjNameSingul() const
384 OUString sName
= SvxResId(STR_ObjNameSingulObj3d
);
386 OUString
aName(GetName());
387 if (!aName
.isEmpty())
389 sName
+= " '" + aName
+ "'";
394 // Get the name of the object (plural)
395 OUString
E3dObject::TakeObjNamePlural() const
397 return SvxResId(STR_ObjNamePluralObj3d
);
400 rtl::Reference
<SdrObject
> E3dObject::CloneSdrObject(SdrModel
& rTargetModel
) const
402 return new E3dObject(rTargetModel
, *this);
405 std::unique_ptr
<SdrObjGeoData
> E3dObject::NewGeoData() const
407 return std::make_unique
<E3DObjGeoData
>();
410 void E3dObject::SaveGeoData(SdrObjGeoData
& rGeo
) const
412 SdrAttrObj::SaveGeoData (rGeo
);
414 static_cast<E3DObjGeoData
&>(rGeo
).maLocalBoundVol
= maLocalBoundVol
;
415 static_cast<E3DObjGeoData
&>(rGeo
).maTransformation
= maTransformation
;
418 void E3dObject::RestoreGeoData(const SdrObjGeoData
& rGeo
)
420 maLocalBoundVol
= static_cast<const E3DObjGeoData
&>(rGeo
).maLocalBoundVol
;
421 E3DModifySceneSnapRectUpdater
aUpdater(this);
422 NbcSetTransform(static_cast<const E3DObjGeoData
&>(rGeo
).maTransformation
);
423 SdrAttrObj::RestoreGeoData (rGeo
);
426 // 2D-rotation of a 3D-body, normally this is done by the scene itself.
427 // This is however a correct implementation, because everything that has
428 // happened is a rotation around the axis perpendicular to the screen and that
429 // is regardless of how the scene has been rotated up until now.
430 void E3dObject::NbcRotate(const Point
& rRef
, Degree100 nAngle
, double sn
, double cs
)
432 // So currently the gluepoints are defined relative to the scene aOutRect.
433 // Before turning the gluepoints are defined relative to the page. They
434 // take no part in the rotation of the scene. To ensure this, there is the
435 // SetGlueReallyAbsolute(sal_True);
436 double fAngleInRad
= toRadians(nAngle
);
438 basegfx::B3DHomMatrix aRotateZ
;
439 aRotateZ
.rotate(0.0, 0.0, fAngleInRad
);
440 NbcSetTransform(aRotateZ
* GetTransform());
442 SetBoundAndSnapRectsDirty(); // This forces a recalculation of all BoundRects
443 NbcRotateGluePoints(rRef
,nAngle
,sn
,cs
); // Rotate the gluepoints (who still
444 // have coordinates relative to the
446 SetGlueReallyAbsolute(false); // from now they are again relative to BoundRect (that is defined as aOutRect)
449 std::unique_ptr
<sdr::properties::BaseProperties
> E3dCompoundObject::CreateObjectSpecificProperties()
451 return std::make_unique
<sdr::properties::E3dCompoundProperties
>(*this);
454 E3dCompoundObject::E3dCompoundObject(SdrModel
& rSdrModel
)
455 : E3dObject(rSdrModel
)
459 E3dCompoundObject::E3dCompoundObject(SdrModel
& rSdrModel
, E3dCompoundObject
const & rSource
)
460 : E3dObject(rSdrModel
, rSource
)
464 E3dCompoundObject::~E3dCompoundObject ()
468 basegfx::B2DPolyPolygon
E3dCompoundObject::TakeXorPoly() const
470 basegfx::B2DPolyPolygon aRetval
;
471 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
472 drawinglayer::geometry::ViewInformation3D
aViewInfo3D(aEmptyParameters
);
473 E3dScene
* pRootScene
= fillViewInformation3DForCompoundObject(aViewInfo3D
, *this);
477 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pRootScene
->GetViewContact());
478 const basegfx::B3DPolyPolygon
aCubePolyPolygon(CreateWireframe());
479 aRetval
= basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon
,
480 aViewInfo3D
.getObjectToView() * GetTransform());
481 aRetval
.transform(rVCScene
.getObjectTransformation());
487 sal_uInt32
E3dCompoundObject::GetHdlCount() const
489 // 8 corners + 1 E3dVolumeMarker (= Wireframe representation)
493 void E3dCompoundObject::AddToHdlList(SdrHdlList
& rHdlList
) const
495 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
496 drawinglayer::geometry::ViewInformation3D
aViewInfo3D(aEmptyParameters
);
497 E3dScene
* pRootScene
= fillViewInformation3DForCompoundObject(aViewInfo3D
, *this);
501 const basegfx::B3DRange
aBoundVolume(GetBoundVolume());
503 if(!aBoundVolume
.isEmpty())
505 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pRootScene
->GetViewContact());
507 for(sal_uInt32
a(0); a
< 8; a
++)
509 basegfx::B3DPoint aPos3D
;
513 case 0 : aPos3D
.setX(aBoundVolume
.getMinX()); aPos3D
.setY(aBoundVolume
.getMinY()); aPos3D
.setZ(aBoundVolume
.getMinZ()); break;
514 case 1 : aPos3D
.setX(aBoundVolume
.getMinX()); aPos3D
.setY(aBoundVolume
.getMinY()); aPos3D
.setZ(aBoundVolume
.getMaxZ()); break;
515 case 2 : aPos3D
.setX(aBoundVolume
.getMinX()); aPos3D
.setY(aBoundVolume
.getMaxY()); aPos3D
.setZ(aBoundVolume
.getMinZ()); break;
516 case 3 : aPos3D
.setX(aBoundVolume
.getMinX()); aPos3D
.setY(aBoundVolume
.getMaxY()); aPos3D
.setZ(aBoundVolume
.getMaxZ()); break;
517 case 4 : aPos3D
.setX(aBoundVolume
.getMaxX()); aPos3D
.setY(aBoundVolume
.getMinY()); aPos3D
.setZ(aBoundVolume
.getMinZ()); break;
518 case 5 : aPos3D
.setX(aBoundVolume
.getMaxX()); aPos3D
.setY(aBoundVolume
.getMinY()); aPos3D
.setZ(aBoundVolume
.getMaxZ()); break;
519 case 6 : aPos3D
.setX(aBoundVolume
.getMaxX()); aPos3D
.setY(aBoundVolume
.getMaxY()); aPos3D
.setZ(aBoundVolume
.getMinZ()); break;
520 case 7 : aPos3D
.setX(aBoundVolume
.getMaxX()); aPos3D
.setY(aBoundVolume
.getMaxY()); aPos3D
.setZ(aBoundVolume
.getMaxZ()); break;
524 aPos3D
*= aViewInfo3D
.getObjectToView() * GetTransform();
526 // create 2d relative scene
527 basegfx::B2DPoint
aPos2D(aPos3D
.getX(), aPos3D
.getY());
530 aPos2D
*= rVCScene
.getObjectTransformation();
532 rHdlList
.AddHdl(std::make_unique
<SdrHdl
>(Point(basegfx::fround
<tools::Long
>(aPos2D
.getX()), basegfx::fround
<tools::Long
>(aPos2D
.getY())), SdrHdlKind::BezierWeight
));
537 const basegfx::B2DPolyPolygon
aPolyPolygon(TakeXorPoly());
539 if(aPolyPolygon
.count())
541 rHdlList
.AddHdl(std::make_unique
<E3dVolumeMarker
>(aPolyPolygon
));
545 SdrObjKind
E3dCompoundObject::GetObjIdentifier() const
547 return SdrObjKind::E3D_CompoundObject
;
550 void E3dCompoundObject::RecalcSnapRect()
552 if (comphelper::IsFuzzing()) // skip slow path for fuzzing
555 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
556 drawinglayer::geometry::ViewInformation3D
aViewInfo3D(aEmptyParameters
);
557 E3dScene
* pRootScene
= fillViewInformation3DForCompoundObject(aViewInfo3D
, *this);
558 maSnapRect
= tools::Rectangle();
563 // get VC of 3D candidate
564 const sdr::contact::ViewContactOfE3d
* pVCOfE3D
= dynamic_cast< const sdr::contact::ViewContactOfE3d
* >(&GetViewContact());
569 // get 3D primitive sequence
570 const drawinglayer::primitive3d::Primitive3DContainer
xLocalSequence(pVCOfE3D
->getViewIndependentPrimitive3DContainer());
572 if(xLocalSequence
.empty())
576 basegfx::B3DRange
aBoundVolume(xLocalSequence
.getB3DRange(aViewInfo3D
));
578 // transform bound volume to relative scene coordinates
579 aBoundVolume
.transform(aViewInfo3D
.getObjectToView());
581 // build 2d relative scene range
582 basegfx::B2DRange
aSnapRange(
583 aBoundVolume
.getMinX(), aBoundVolume
.getMinY(),
584 aBoundVolume
.getMaxX(), aBoundVolume
.getMaxY());
586 // transform to 2D world coordinates
587 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pRootScene
->GetViewContact());
588 aSnapRange
.transform(rVCScene
.getObjectTransformation());
591 maSnapRect
= tools::Rectangle(
592 sal_Int32(floor(aSnapRange
.getMinX())), sal_Int32(floor(aSnapRange
.getMinY())),
593 sal_Int32(ceil(aSnapRange
.getMaxX())), sal_Int32(ceil(aSnapRange
.getMaxY())));
596 rtl::Reference
<SdrObject
> E3dCompoundObject::CloneSdrObject(SdrModel
& rTargetModel
) const
598 return new E3dCompoundObject(rTargetModel
, *this);
601 // convert given basegfx::B3DPolyPolygon to screen coor
602 basegfx::B2DPolyPolygon
E3dCompoundObject::TransformToScreenCoor(const basegfx::B3DPolyPolygon
& rCandidate
) const
604 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
605 drawinglayer::geometry::ViewInformation3D
aViewInfo3D(aEmptyParameters
);
606 E3dScene
* pRootScene
= fillViewInformation3DForCompoundObject(aViewInfo3D
, *this);
607 basegfx::B2DPolyPolygon aRetval
;
611 aRetval
= basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(rCandidate
,
612 aViewInfo3D
.getObjectToView() * GetTransform());
613 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pRootScene
->GetViewContact());
614 aRetval
.transform(rVCScene
.getObjectTransformation());
620 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */