/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "svx/svdstr.hrc" #include "svx/svdglob.hxx" #include #include #include #include #include "svx/svditer.hxx" #include "svx/globl3d.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ////////////////////////////////////////////////////////////////////////////// using namespace com::sun::star; // List for 3D-Objects TYPEINIT1(E3dObjList, SdrObjList); E3dObjList::E3dObjList(SdrModel* pNewModel, SdrPage* pNewPage, E3dObjList* pNewUpList) : SdrObjList(pNewModel, pNewPage, pNewUpList) { } E3dObjList::E3dObjList(const E3dObjList& rSrcList) : SdrObjList(rSrcList) { } E3dObjList::~E3dObjList() { } void E3dObjList::NbcInsertObject(SdrObject* pObj, sal_uIntPtr nPos, const SdrInsertReason* pReason) { // Get owner DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "Insert 3D object in parent != 3DObject"); // Is it even a 3D object? if(pObj && pObj->ISA(E3dObject)) { // Normal 3D object, insert means // call parent SdrObjList::NbcInsertObject(pObj, nPos, pReason); } else { // No 3D object, inserted a page in place in a scene ... GetOwnerObj()->GetPage()->InsertObject(pObj, nPos); } } void E3dObjList::InsertObject(SdrObject* pObj, sal_uIntPtr nPos, const SdrInsertReason* pReason) { OSL_ENSURE(GetOwnerObj()->ISA(E3dObject), "Insert 3D object in non-3D Parent"); // call parent SdrObjList::InsertObject(pObj, nPos, pReason); E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene(); if(pScene) { pScene->Cleanup3DDepthMapper(); } } SdrObject* E3dObjList::NbcRemoveObject(sal_uIntPtr nObjNum) { DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "Remove 3D object from Parent != 3DObject"); // call parent SdrObject* pRetval = SdrObjList::NbcRemoveObject(nObjNum); E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene(); if(pScene) { pScene->Cleanup3DDepthMapper(); } return pRetval; } SdrObject* E3dObjList::RemoveObject(sal_uIntPtr nObjNum) { OSL_ENSURE(GetOwnerObj()->ISA(E3dObject), "3D object is removed from non-3D Parent"); // call parent SdrObject* pRetval = SdrObjList::RemoveObject(nObjNum); E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene(); if(pScene) { pScene->Cleanup3DDepthMapper(); } return pRetval; } ////////////////////////////////////////////////////////////////////////////// sdr::properties::BaseProperties* E3dObject::CreateObjectSpecificProperties() { return new sdr::properties::E3dProperties(*this); } ////////////////////////////////////////////////////////////////////////////// TYPEINIT1(E3dObject, SdrAttrObj); E3dObject::E3dObject() : maSubList(), maLocalBoundVol(), maTransformation(), maFullTransform(), mbTfHasChanged(true), mbIsSelected(false) { bIs3DObj = true; maSubList.SetOwnerObj(this); maSubList.SetListKind(SDROBJLIST_GROUPOBJ); bClosedObj = true; } E3dObject::~E3dObject() { } void E3dObject::SetSelected(bool bNew) { if((bool)mbIsSelected != bNew) { mbIsSelected = bNew; } for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) { E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); if(pCandidate) { pCandidate->SetSelected(bNew); } } } // Break, default implementations sal_Bool E3dObject::IsBreakObjPossible() { return sal_False; } SdrAttrObj* E3dObject::GetBreakObj() { return 0L; } // SetRectsDirty must be done through the local SdrSubList void E3dObject::SetRectsDirty(sal_Bool bNotMyself) { // call parent SdrAttrObj::SetRectsDirty(bNotMyself); for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) { E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); if(pCandidate) { pCandidate->SetRectsDirty(bNotMyself); } } } sal_uInt32 E3dObject::GetObjInventor() const { return E3dInventor; } sal_uInt16 E3dObject::GetObjIdentifier() const { return E3D_OBJECT_ID; } // Determine the capabilities of the object void E3dObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const { rInfo.bResizeFreeAllowed = sal_True; rInfo.bResizePropAllowed = sal_True; rInfo.bRotateFreeAllowed = sal_True; rInfo.bRotate90Allowed = sal_True; rInfo.bMirrorFreeAllowed = sal_False; rInfo.bMirror45Allowed = sal_False; rInfo.bMirror90Allowed = sal_False; rInfo.bShearAllowed = sal_False; rInfo.bEdgeRadiusAllowed = sal_False; rInfo.bCanConvToPath = sal_False; // no transparence for 3d objects rInfo.bTransparenceAllowed = sal_False; // gradient depends on fillstyle // BM *** check if SetItem is NULL *** XFillStyle eFillStyle = ((XFillStyleItem&)(GetMergedItem(XATTR_FILLSTYLE))).GetValue(); rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT); // Convert 3D objects in a group of polygons: // At first not only possible, because the creation of a group of // 2D polygons would be required which need to be sorted by depth, // ie at intersections be cut relative to each other. Also the texture // coorinates were an unsolved problem. rInfo.bCanConvToPoly = sal_False; rInfo.bCanConvToContour = sal_False; rInfo.bCanConvToPathLineToArea = sal_False; rInfo.bCanConvToPolyLineToArea = sal_False; } void E3dObject::NbcSetLayer(SdrLayerID nLayer) { SdrAttrObj::NbcSetLayer(nLayer); for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) { E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); if(pCandidate) { pCandidate->NbcSetLayer(nLayer); } } } // Set ObjList also on SubList void E3dObject::SetObjList(SdrObjList* pNewObjList) { SdrObject::SetObjList(pNewObjList); maSubList.SetUpList(pNewObjList); } void E3dObject::SetPage(SdrPage* pNewPage) { SdrAttrObj::SetPage(pNewPage); maSubList.SetPage(pNewPage); } void E3dObject::SetModel(SdrModel* pNewModel) { SdrAttrObj::SetModel(pNewModel); maSubList.SetModel(pNewModel); } // resize object, used from old 2d interfaces, e.g. in Move/Scale dialog (F4) void E3dObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) { // Movement in X, Y in the eye coordinate system E3dScene* pScene = GetScene(); if(pScene) { // transform pos from 2D world to 3D eye const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact()); const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D()); basegfx::B2DPoint aScaleCenter2D((double)rRef.X(), (double)rRef.Y()); basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation()); aInverseSceneTransform.invert(); aScaleCenter2D = aInverseSceneTransform * aScaleCenter2D; basegfx::B3DPoint aScaleCenter3D(aScaleCenter2D.getX(), aScaleCenter2D.getY(), 0.5); basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection()); aInverseViewToEye.invert(); aScaleCenter3D = aInverseViewToEye * aScaleCenter3D; // Get scale factors double fScaleX(xFact); double fScaleY(yFact); // build transform basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation()); aInverseOrientation.invert(); basegfx::B3DHomMatrix mFullTransform(GetFullTransform()); basegfx::B3DHomMatrix mTrans(mFullTransform); mTrans *= aViewInfo3D.getOrientation(); mTrans.translate(-aScaleCenter3D.getX(), -aScaleCenter3D.getY(), -aScaleCenter3D.getZ()); mTrans.scale(fScaleX, fScaleY, 1.0); mTrans.translate(aScaleCenter3D.getX(), aScaleCenter3D.getY(), aScaleCenter3D.getZ()); mTrans *= aInverseOrientation; mFullTransform.invert(); mTrans *= mFullTransform; // Apply basegfx::B3DHomMatrix mObjTrans(GetTransform()); mObjTrans *= mTrans; E3DModifySceneSnapRectUpdater aUpdater(this); SetTransform(mObjTrans); } } // Move object in 2D is needed when using cursor keys void E3dObject::NbcMove(const Size& rSize) { // Movement in X, Y in the eye coordinate system E3dScene* pScene = GetScene(); if(pScene) { //Dimensions of the scene in 3D and 2D for comparison Rectangle aRect = pScene->GetSnapRect(); basegfx::B3DHomMatrix mInvDispTransform; if(GetParentObj()) { mInvDispTransform = GetParentObj()->GetFullTransform(); mInvDispTransform.invert(); } // BoundVolume from 3d world to 3d eye const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact()); const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D()); basegfx::B3DRange aEyeVol(pScene->GetBoundVolume()); aEyeVol.transform(aViewInfo3D.getOrientation()); // build relative movement vector in eye coordinates basegfx::B3DPoint aMove( (double)rSize.Width() * aEyeVol.getWidth() / (double)aRect.GetWidth(), (double)-rSize.Height() * aEyeVol.getHeight() / (double)aRect.GetHeight(), 0.0); basegfx::B3DPoint aPos(0.0, 0.0, 0.0); // movement vector to local coordinates of objects' parent basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation()); aInverseOrientation.invert(); basegfx::B3DHomMatrix aCompleteTrans(mInvDispTransform * aInverseOrientation); aMove = aCompleteTrans * aMove; aPos = aCompleteTrans * aPos; // build transformation and apply basegfx::B3DHomMatrix aTranslate; aTranslate.translate(aMove.getX() - aPos.getX(), aMove.getY() - aPos.getY(), aMove.getZ() - aPos.getZ()); E3DModifySceneSnapRectUpdater aUpdater(pScene); SetTransform(aTranslate * GetTransform()); } } // Return the sublist, but only if it contains objects! SdrObjList* E3dObject::GetSubList() const { return &(const_cast< E3dObjList& >(maSubList)); } void E3dObject::RecalcSnapRect() { maSnapRect = Rectangle(); for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) { E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); if(pCandidate) { maSnapRect.Union(pCandidate->GetSnapRect()); } } } // Inform the parent about insertion of a 3D object, so that the parent is able // treat the particualar objects in a special way (eg Light / Label in E3dScene) void E3dObject::NewObjectInserted(const E3dObject* p3DObj) { if(GetParentObj()) GetParentObj()->NewObjectInserted(p3DObj); } // Inform parent of changes in the structure (eg by transformation), in this // process the object in which the change has occurred is returned. void E3dObject::StructureChanged() { if ( GetParentObj() ) { GetParentObj()->InvalidateBoundVolume(); GetParentObj()->StructureChanged(); } } void E3dObject::Insert3DObj(E3dObject* p3DObj) { DBG_ASSERT(p3DObj, "Insert3DObj with NULL-pointer!"); SdrPage* pPg = pPage; maSubList.InsertObject(p3DObj); pPage = pPg; InvalidateBoundVolume(); NewObjectInserted(p3DObj); StructureChanged(); } void E3dObject::Remove3DObj(E3dObject* p3DObj) { DBG_ASSERT(p3DObj, "Remove3DObj with NULL-pointer!"); if(p3DObj->GetParentObj() == this) { SdrPage* pPg = pPage; maSubList.RemoveObject(p3DObj->GetOrdNum()); pPage = pPg; InvalidateBoundVolume(); StructureChanged(); } } E3dObject* E3dObject::GetParentObj() const { E3dObject* pRetval = NULL; if(GetObjList() && GetObjList()->GetOwnerObj() && GetObjList()->GetOwnerObj()->ISA(E3dObject)) pRetval = ((E3dObject*)GetObjList()->GetOwnerObj()); return pRetval; } // Determine the top-level scene object E3dScene* E3dObject::GetScene() const { if(GetParentObj()) return GetParentObj()->GetScene(); return NULL; } // Calculate enclosed volume, including all child objects basegfx::B3DRange E3dObject::RecalcBoundVolume() const { basegfx::B3DRange aRetval; const sal_uInt32 nObjCnt(maSubList.GetObjCount()); if(nObjCnt) { for(sal_uInt32 a(0); a < nObjCnt; a++) { const E3dObject* p3DObject = dynamic_cast< const E3dObject* >(maSubList.GetObj(a)); if(p3DObject) { basegfx::B3DRange aLocalRange(p3DObject->GetBoundVolume()); aLocalRange.transform(p3DObject->GetTransform()); aRetval.expand(aLocalRange); } } } else { // single 3D object const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact()); if(pVCOfE3D) { // BoundVolume is without 3D object transformation, use correct sequence const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getVIP3DSWithoutObjectTransform()); if(xLocalSequence.hasElements()) { const uno::Sequence< beans::PropertyValue > aEmptyParameters; const drawinglayer::geometry::ViewInformation3D aLocalViewInformation3D(aEmptyParameters); aRetval = drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence( xLocalSequence, aLocalViewInformation3D); } } } return aRetval; } // Get enclosed volume and possibly recalculate it const basegfx::B3DRange& E3dObject::GetBoundVolume() const { if(maLocalBoundVol.isEmpty()) { const_cast< E3dObject* >(this)->maLocalBoundVol = RecalcBoundVolume(); } return maLocalBoundVol; } void E3dObject::InvalidateBoundVolume() { maLocalBoundVol.reset(); } // Pass on the changes of the BoundVolumes to all child objects void E3dObject::SetBoundVolInvalid() { InvalidateBoundVolume(); for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) { E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); if(pCandidate) { pCandidate->SetBoundVolInvalid(); } } } // Pass on the changes in transformation to all child objects void E3dObject::SetTransformChanged() { InvalidateBoundVolume(); mbTfHasChanged = true; for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) { E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); if(pCandidate) { pCandidate->SetTransformChanged(); } } } // Define the hierarchical transformation over all Parents, store in // maFullTransform and return them const basegfx::B3DHomMatrix& E3dObject::GetFullTransform() const { if(mbTfHasChanged) { basegfx::B3DHomMatrix aNewFullTransformation(maTransformation); if ( GetParentObj() ) { aNewFullTransformation = GetParentObj()->GetFullTransform() * aNewFullTransformation; } const_cast< E3dObject* >(this)->maFullTransform = aNewFullTransformation; const_cast< E3dObject* >(this)->mbTfHasChanged = false; } return maFullTransform; } const basegfx::B3DHomMatrix& E3dObject::GetTransform() const { return maTransformation; } void E3dObject::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix) { if(maTransformation != rMatrix) { maTransformation = rMatrix; SetTransformChanged(); StructureChanged(); } } // Set transformation matrix with repaint broadcast void E3dObject::SetTransform(const basegfx::B3DHomMatrix& rMatrix) { if(rMatrix != maTransformation) { NbcSetTransform(rMatrix); SetChanged(); BroadcastObjectChange(); if (pUserCall != NULL) pUserCall->Changed(*this, SDRUSERCALL_RESIZE, Rectangle()); } } basegfx::B3DPolyPolygon E3dObject::CreateWireframe() const { const basegfx::B3DRange aBoundVolume(GetBoundVolume()); return basegfx::tools::createCubePolyPolygonFromB3DRange(aBoundVolume); } // Get the name of the object (singular) void E3dObject::TakeObjNameSingul(XubString& rName) const { rName=ImpGetResStr(STR_ObjNameSingulObj3d); String aName( GetName() ); if(aName.Len()) { rName += sal_Unicode(' '); rName += sal_Unicode('\''); rName += aName; rName += sal_Unicode('\''); } } // Get the name of the object (plural) void E3dObject::TakeObjNamePlural(XubString& rName) const { rName=ImpGetResStr(STR_ObjNamePluralObj3d); } E3dObject* E3dObject::Clone() const { return CloneHelper< E3dObject >(); } E3dObject& E3dObject::operator=(const E3dObject& rObj) { if( this == &rObj ) return *this; SdrObject::operator=(rObj); const E3dObject& r3DObj = (const E3dObject&) rObj; if (r3DObj.GetSubList()) { maSubList.CopyObjects(*r3DObj.GetSubList()); } // BoundVol can be copied since also the children are copied maLocalBoundVol = r3DObj.maLocalBoundVol; maTransformation = r3DObj.maTransformation; // Because the parent may have changed, definitely redefine the total // transformation next time SetTransformChanged(); // Copy selection status mbIsSelected = r3DObj.mbIsSelected; return *this; } SdrObjGeoData *E3dObject::NewGeoData() const { return new E3DObjGeoData; } void E3dObject::SaveGeoData(SdrObjGeoData& rGeo) const { SdrAttrObj::SaveGeoData (rGeo); ((E3DObjGeoData &) rGeo).maLocalBoundVol = maLocalBoundVol; ((E3DObjGeoData &) rGeo).maTransformation = maTransformation; } void E3dObject::RestGeoData(const SdrObjGeoData& rGeo) { maLocalBoundVol = ((E3DObjGeoData &) rGeo).maLocalBoundVol; E3DModifySceneSnapRectUpdater aUpdater(this); NbcSetTransform(((E3DObjGeoData &) rGeo).maTransformation); SdrAttrObj::RestGeoData (rGeo); } // 2D-rotation of a 3D-body, normally this is done by the scene itself. // This is however a correct implementation, because everything that has // happened is a rotation around the axis perpendicular to the screen and that // is regardless of how the scene has been rotated up until now. void E3dObject::NbcRotate(const Point& rRef, long nWink, double sn, double cs) { // So currently the glue points are defined relative to the scene aOutRect. // Before turning the glue points are defined relative to the page. They // take no part in the rotation of the scene. To ensure this, there is the // SetGlueReallyAbsolute(sal_True); double fWinkelInRad = nWink/100 * F_PI180; basegfx::B3DHomMatrix aRotateZ; aRotateZ.rotate(0.0, 0.0, fWinkelInRad); NbcSetTransform(aRotateZ * GetTransform()); SetRectsDirty(); // This forces a recalculation of all BoundRects NbcRotateGluePoints(rRef,nWink,sn,cs); // Rotate the glue points (who still // have coordinates relative to the // original page) SetGlueReallyAbsolute(sal_False); // from now they are again relative to BoundRect (that is defined as aOutRect) } /*************************************************************************/ ////////////////////////////////////////////////////////////////////////////// sdr::properties::BaseProperties* E3dCompoundObject::CreateObjectSpecificProperties() { return new sdr::properties::E3dCompoundProperties(*this); } ////////////////////////////////////////////////////////////////////////////// TYPEINIT1(E3dCompoundObject, E3dObject); E3dCompoundObject::E3dCompoundObject() : E3dObject(), aMaterialAmbientColor(), bCreateNormals(false), bCreateTexture(false) { // Set defaults E3dDefaultAttributes aDefault; SetDefaultAttributes(aDefault); } E3dCompoundObject::E3dCompoundObject(E3dDefaultAttributes& rDefault) : E3dObject(), aMaterialAmbientColor(), bCreateNormals(false), bCreateTexture(false) { // Set defaults SetDefaultAttributes(rDefault); } void E3dCompoundObject::SetDefaultAttributes(E3dDefaultAttributes& rDefault) { // Set defaults aMaterialAmbientColor = rDefault.GetDefaultAmbientColor(); bCreateNormals = rDefault.GetDefaultCreateNormals(); bCreateTexture = rDefault.GetDefaultCreateTexture(); } E3dCompoundObject::~E3dCompoundObject () { } basegfx::B2DPolyPolygon E3dCompoundObject::TakeXorPoly() const { basegfx::B2DPolyPolygon aRetval; const uno::Sequence< beans::PropertyValue > aEmptyParameters; drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this); if(pRootScene) { const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe()); aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon, aViewInfo3D.getObjectToView() * GetTransform()); aRetval.transform(rVCScene.getObjectTransformation()); } return aRetval; } sal_uInt32 E3dCompoundObject::GetHdlCount() const { // 8 corners + 1 E3dVolumeMarker (= Wireframe representation) return 9L; } void E3dCompoundObject::AddToHdlList(SdrHdlList& rHdlList) const { const uno::Sequence< beans::PropertyValue > aEmptyParameters; drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this); if(pRootScene) { const basegfx::B3DRange aBoundVolume(GetBoundVolume()); if(!aBoundVolume.isEmpty()) { const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); for(sal_uInt32 a(0); a < 8; a++) { basegfx::B3DPoint aPos3D; switch(a) { case 0 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break; case 1 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break; case 2 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break; case 3 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break; case 4 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break; case 5 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break; case 6 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break; case 7 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break; } // to 3d view coor aPos3D *= aViewInfo3D.getObjectToView() * GetTransform(); // create 2d relative scene basegfx::B2DPoint aPos2D(aPos3D.getX(), aPos3D.getY()); // to 2d world coor aPos2D *= rVCScene.getObjectTransformation(); rHdlList.AddHdl(new SdrHdl(Point(basegfx::fround(aPos2D.getX()), basegfx::fround(aPos2D.getY())), HDL_BWGT)); } } } const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly()); if(aPolyPolygon.count()) { E3dVolumeMarker* pVolMarker = new E3dVolumeMarker(aPolyPolygon); rHdlList.AddHdl(pVolMarker); } } sal_uInt16 E3dCompoundObject::GetObjIdentifier() const { return E3D_COMPOUNDOBJ_ID; } void E3dCompoundObject::RecalcSnapRect() { const uno::Sequence< beans::PropertyValue > aEmptyParameters; drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this); maSnapRect = Rectangle(); if(pRootScene) { // get VC of 3D candidate const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact()); if(pVCOfE3D) { // get 3D primitive sequence const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getViewIndependentPrimitive3DSequence()); if(xLocalSequence.hasElements()) { // get BoundVolume basegfx::B3DRange aBoundVolume(drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence( xLocalSequence, aViewInfo3D)); // transform bound volume to relative scene coordinates aBoundVolume.transform(aViewInfo3D.getObjectToView()); // build 2d relative scene range basegfx::B2DRange aSnapRange( aBoundVolume.getMinX(), aBoundVolume.getMinY(), aBoundVolume.getMaxX(), aBoundVolume.getMaxY()); // transform to 2D world coordiantes const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); aSnapRange.transform(rVCScene.getObjectTransformation()); // snap to integer maSnapRect = Rectangle( sal_Int32(floor(aSnapRange.getMinX())), sal_Int32(floor(aSnapRange.getMinY())), sal_Int32(ceil(aSnapRange.getMaxX())), sal_Int32(ceil(aSnapRange.getMaxY()))); } } } } E3dCompoundObject* E3dCompoundObject::Clone() const { return CloneHelper< E3dCompoundObject >(); } // convert given basegfx::B3DPolyPolygon to screen coor basegfx::B2DPolyPolygon E3dCompoundObject::TransformToScreenCoor(const basegfx::B3DPolyPolygon& rCandidate) { const uno::Sequence< beans::PropertyValue > aEmptyParameters; drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this); basegfx::B2DPolyPolygon aRetval; if(pRootScene) { aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rCandidate, aViewInfo3D.getObjectToView() * GetTransform()); const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); aRetval.transform(rVCScene.getObjectTransformation()); } return aRetval; } sal_Bool E3dCompoundObject::IsAOrdNumRemapCandidate(E3dScene*& prScene) const { if(GetObjList() && GetObjList()->GetOwnerObj() && GetObjList()->GetOwnerObj()->ISA(E3dScene)) { prScene = (E3dScene*)GetObjList()->GetOwnerObj(); return sal_True; } return sal_False; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */