1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_svx.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <svx/helperhittest3d.hxx> 32*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx> 33*cdf0e10cSrcweir #include <svx/svdpage.hxx> 34*cdf0e10cSrcweir #include <svx/scene3d.hxx> 35*cdf0e10cSrcweir #include <svx/svditer.hxx> 36*cdf0e10cSrcweir #include <drawinglayer/processor3d/cutfindprocessor3d.hxx> 37*cdf0e10cSrcweir #include <svx/sdr/contact/viewcontactofe3d.hxx> 38*cdf0e10cSrcweir #include <svx/sdr/contact/viewcontactofe3dscene.hxx> 39*cdf0e10cSrcweir #include <com/sun/star/uno/Sequence.h> 40*cdf0e10cSrcweir 41*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir using namespace com::sun::star; 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir class ImplPairDephAndObject 48*cdf0e10cSrcweir { 49*cdf0e10cSrcweir private: 50*cdf0e10cSrcweir const E3dCompoundObject* mpObject; 51*cdf0e10cSrcweir double mfDepth; 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir public: 54*cdf0e10cSrcweir ImplPairDephAndObject(const E3dCompoundObject* pObject, double fDepth) 55*cdf0e10cSrcweir : mpObject(pObject), 56*cdf0e10cSrcweir mfDepth(fDepth) 57*cdf0e10cSrcweir {} 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir // for ::std::sort 60*cdf0e10cSrcweir bool operator<(const ImplPairDephAndObject& rComp) const 61*cdf0e10cSrcweir { 62*cdf0e10cSrcweir return (mfDepth < rComp.mfDepth); 63*cdf0e10cSrcweir } 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir // data read access 66*cdf0e10cSrcweir const E3dCompoundObject* getObject() const { return mpObject; } 67*cdf0e10cSrcweir double getDepth() const { return mfDepth; } 68*cdf0e10cSrcweir }; 69*cdf0e10cSrcweir 70*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir void getAllHit3DObjectWithRelativePoint( 73*cdf0e10cSrcweir const basegfx::B3DPoint& rFront, 74*cdf0e10cSrcweir const basegfx::B3DPoint& rBack, 75*cdf0e10cSrcweir const E3dCompoundObject& rObject, 76*cdf0e10cSrcweir const drawinglayer::geometry::ViewInformation3D& rObjectViewInformation3D, 77*cdf0e10cSrcweir ::std::vector< basegfx::B3DPoint >& o_rResult, 78*cdf0e10cSrcweir bool bAnyHit) 79*cdf0e10cSrcweir { 80*cdf0e10cSrcweir o_rResult.clear(); 81*cdf0e10cSrcweir 82*cdf0e10cSrcweir if(!rFront.equal(rBack)) 83*cdf0e10cSrcweir { 84*cdf0e10cSrcweir // rObject is a E3dCompoundObject, so it cannot be a scene (which is a E3dObject) 85*cdf0e10cSrcweir const sdr::contact::ViewContactOfE3d& rVCObject = static_cast< sdr::contact::ViewContactOfE3d& >(rObject.GetViewContact()); 86*cdf0e10cSrcweir const drawinglayer::primitive3d::Primitive3DSequence aPrimitives(rVCObject.getViewIndependentPrimitive3DSequence()); 87*cdf0e10cSrcweir 88*cdf0e10cSrcweir if(aPrimitives.hasElements()) 89*cdf0e10cSrcweir { 90*cdf0e10cSrcweir // make BoundVolume empty and overlapping test for speedup 91*cdf0e10cSrcweir const basegfx::B3DRange aObjectRange(drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(aPrimitives, rObjectViewInformation3D)); 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir if(!aObjectRange.isEmpty()) 94*cdf0e10cSrcweir { 95*cdf0e10cSrcweir const basegfx::B3DRange aFrontBackRange(rFront, rBack); 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir if(aObjectRange.overlaps(aFrontBackRange)) 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir // bound volumes hit, geometric cut tests needed 100*cdf0e10cSrcweir drawinglayer::processor3d::CutFindProcessor aCutFindProcessor(rObjectViewInformation3D, rFront, rBack, bAnyHit); 101*cdf0e10cSrcweir aCutFindProcessor.process(aPrimitives); 102*cdf0e10cSrcweir o_rResult = aCutFindProcessor.getCutPoints(); 103*cdf0e10cSrcweir } 104*cdf0e10cSrcweir } 105*cdf0e10cSrcweir } 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 110*cdf0e10cSrcweir 111*cdf0e10cSrcweir E3dScene* fillViewInformation3DForCompoundObject(drawinglayer::geometry::ViewInformation3D& o_rViewInformation3D, const E3dCompoundObject& rCandidate) 112*cdf0e10cSrcweir { 113*cdf0e10cSrcweir // Search for root scene (outmost scene) of the 3d object since e.g. in chart, multiple scenes may 114*cdf0e10cSrcweir // be placed between object and outmost scene. On that search, remember the in-between scene's 115*cdf0e10cSrcweir // transformation for the correct complete ObjectTransformation. For historical reasons, the 116*cdf0e10cSrcweir // root scene's own object transformation is part of the scene's ViewTransformation, o do not 117*cdf0e10cSrcweir // add it. For more details, see ViewContactOfE3dScene::createViewInformation3D. 118*cdf0e10cSrcweir E3dScene* pParentScene = dynamic_cast< E3dScene* >(rCandidate.GetParentObj()); 119*cdf0e10cSrcweir E3dScene* pRootScene = 0; 120*cdf0e10cSrcweir basegfx::B3DHomMatrix aInBetweenSceneMatrix; 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir while(pParentScene) 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir E3dScene* pParentParentScene = dynamic_cast< E3dScene* >(pParentScene->GetParentObj()); 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir if(pParentParentScene) 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir // pParentScene is a in-between scene 129*cdf0e10cSrcweir aInBetweenSceneMatrix = pParentScene->GetTransform() * aInBetweenSceneMatrix; 130*cdf0e10cSrcweir } 131*cdf0e10cSrcweir else 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir // pParentScene is the root scene 134*cdf0e10cSrcweir pRootScene = pParentScene; 135*cdf0e10cSrcweir } 136*cdf0e10cSrcweir 137*cdf0e10cSrcweir pParentScene = pParentParentScene; 138*cdf0e10cSrcweir } 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir if(pRootScene) 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); 143*cdf0e10cSrcweir 144*cdf0e10cSrcweir if(aInBetweenSceneMatrix.isIdentity()) 145*cdf0e10cSrcweir { 146*cdf0e10cSrcweir o_rViewInformation3D = rVCScene.getViewInformation3D(); 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir else 149*cdf0e10cSrcweir { 150*cdf0e10cSrcweir // build new ViewInformation containing all transforms for the candidate 151*cdf0e10cSrcweir const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D()); 152*cdf0e10cSrcweir 153*cdf0e10cSrcweir o_rViewInformation3D = drawinglayer::geometry::ViewInformation3D( 154*cdf0e10cSrcweir aViewInfo3D.getObjectTransformation() * aInBetweenSceneMatrix, 155*cdf0e10cSrcweir aViewInfo3D.getOrientation(), 156*cdf0e10cSrcweir aViewInfo3D.getProjection(), 157*cdf0e10cSrcweir aViewInfo3D.getDeviceToView(), 158*cdf0e10cSrcweir aViewInfo3D.getViewTime(), 159*cdf0e10cSrcweir aViewInfo3D.getExtendedInformationSequence()); 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir } 162*cdf0e10cSrcweir else 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir const uno::Sequence< beans::PropertyValue > aEmptyParameters; 165*cdf0e10cSrcweir o_rViewInformation3D = drawinglayer::geometry::ViewInformation3D(aEmptyParameters); 166*cdf0e10cSrcweir } 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir return pRootScene; 169*cdf0e10cSrcweir } 170*cdf0e10cSrcweir 171*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir SVX_DLLPUBLIC void getAllHit3DObjectsSortedFrontToBack( 174*cdf0e10cSrcweir const basegfx::B2DPoint& rPoint, 175*cdf0e10cSrcweir const E3dScene& rScene, 176*cdf0e10cSrcweir ::std::vector< const E3dCompoundObject* >& o_rResult) 177*cdf0e10cSrcweir { 178*cdf0e10cSrcweir o_rResult.clear(); 179*cdf0e10cSrcweir SdrObjList* pList = rScene.GetSubList(); 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir if(pList && pList->GetObjCount()) 182*cdf0e10cSrcweir { 183*cdf0e10cSrcweir // prepare relative HitPoint. To do so, get the VC of the 3DScene and from there 184*cdf0e10cSrcweir // the Scene's 2D transformation. Multiplying with the inverse transformation 185*cdf0e10cSrcweir // will create a point relative to the 3D scene as unit-2d-object 186*cdf0e10cSrcweir const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rScene.GetViewContact()); 187*cdf0e10cSrcweir basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation()); 188*cdf0e10cSrcweir aInverseSceneTransform.invert(); 189*cdf0e10cSrcweir const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * rPoint); 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir // check if test point is inside scene's area at all 192*cdf0e10cSrcweir if(aRelativePoint.getX() >= 0.0 && aRelativePoint.getX() <= 1.0 && aRelativePoint.getY() >= 0.0 && aRelativePoint.getY() <= 1.0) 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir SdrObjListIter aIterator(*pList, IM_DEEPNOGROUPS); 195*cdf0e10cSrcweir ::std::vector< ImplPairDephAndObject > aDepthAndObjectResults; 196*cdf0e10cSrcweir const uno::Sequence< beans::PropertyValue > aEmptyParameters; 197*cdf0e10cSrcweir drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); 198*cdf0e10cSrcweir 199*cdf0e10cSrcweir while(aIterator.IsMore()) 200*cdf0e10cSrcweir { 201*cdf0e10cSrcweir const E3dCompoundObject* pCandidate = dynamic_cast< const E3dCompoundObject* >(aIterator.Next()); 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir if(pCandidate) 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir fillViewInformation3DForCompoundObject(aViewInfo3D, *pCandidate); 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir // create HitPoint Front and Back, transform to object coordinates 208*cdf0e10cSrcweir basegfx::B3DHomMatrix aViewToObject(aViewInfo3D.getObjectToView()); 209*cdf0e10cSrcweir aViewToObject.invert(); 210*cdf0e10cSrcweir const basegfx::B3DPoint aFront(aViewToObject * basegfx::B3DPoint(aRelativePoint.getX(), aRelativePoint.getY(), 0.0)); 211*cdf0e10cSrcweir const basegfx::B3DPoint aBack(aViewToObject * basegfx::B3DPoint(aRelativePoint.getX(), aRelativePoint.getY(), 1.0)); 212*cdf0e10cSrcweir 213*cdf0e10cSrcweir if(!aFront.equal(aBack)) 214*cdf0e10cSrcweir { 215*cdf0e10cSrcweir // get all hit points with object 216*cdf0e10cSrcweir ::std::vector< basegfx::B3DPoint > aHitsWithObject; 217*cdf0e10cSrcweir getAllHit3DObjectWithRelativePoint(aFront, aBack, *pCandidate, aViewInfo3D, aHitsWithObject, false); 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir for(sal_uInt32 a(0); a < aHitsWithObject.size(); a++) 220*cdf0e10cSrcweir { 221*cdf0e10cSrcweir const basegfx::B3DPoint aPointInViewCoordinates(aViewInfo3D.getObjectToView() * aHitsWithObject[a]); 222*cdf0e10cSrcweir aDepthAndObjectResults.push_back(ImplPairDephAndObject(pCandidate, aPointInViewCoordinates.getZ())); 223*cdf0e10cSrcweir } 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir } 226*cdf0e10cSrcweir } 227*cdf0e10cSrcweir 228*cdf0e10cSrcweir // fill nRetval 229*cdf0e10cSrcweir const sal_uInt32 nCount(aDepthAndObjectResults.size()); 230*cdf0e10cSrcweir 231*cdf0e10cSrcweir if(nCount) 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir // sort aDepthAndObjectResults by depth 234*cdf0e10cSrcweir ::std::sort(aDepthAndObjectResults.begin(), aDepthAndObjectResults.end()); 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir // copy SdrObject pointers to return result set 237*cdf0e10cSrcweir ::std::vector< ImplPairDephAndObject >::iterator aIterator2(aDepthAndObjectResults.begin()); 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir for(;aIterator2 != aDepthAndObjectResults.end(); aIterator2++) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir o_rResult.push_back(aIterator2->getObject()); 242*cdf0e10cSrcweir } 243*cdf0e10cSrcweir } 244*cdf0e10cSrcweir } 245*cdf0e10cSrcweir } 246*cdf0e10cSrcweir } 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir bool checkHitSingle3DObject( 251*cdf0e10cSrcweir const basegfx::B2DPoint& rPoint, 252*cdf0e10cSrcweir const E3dCompoundObject& rCandidate) 253*cdf0e10cSrcweir { 254*cdf0e10cSrcweir const uno::Sequence< beans::PropertyValue > aEmptyParameters; 255*cdf0e10cSrcweir drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); 256*cdf0e10cSrcweir E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, rCandidate); 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir if(pRootScene) 259*cdf0e10cSrcweir { 260*cdf0e10cSrcweir // prepare relative HitPoint. To do so, get the VC of the 3DScene and from there 261*cdf0e10cSrcweir // the Scene's 2D transformation. Multiplying with the inverse transformation 262*cdf0e10cSrcweir // will create a point relative to the 3D scene as unit-2d-object 263*cdf0e10cSrcweir const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); 264*cdf0e10cSrcweir basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation()); 265*cdf0e10cSrcweir aInverseSceneTransform.invert(); 266*cdf0e10cSrcweir const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * rPoint); 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir // check if test point is inside scene's area at all 269*cdf0e10cSrcweir if(aRelativePoint.getX() >= 0.0 && aRelativePoint.getX() <= 1.0 && aRelativePoint.getY() >= 0.0 && aRelativePoint.getY() <= 1.0) 270*cdf0e10cSrcweir { 271*cdf0e10cSrcweir // create HitPoint Front and Back, transform to object coordinates 272*cdf0e10cSrcweir basegfx::B3DHomMatrix aViewToObject(aViewInfo3D.getObjectToView()); 273*cdf0e10cSrcweir aViewToObject.invert(); 274*cdf0e10cSrcweir const basegfx::B3DPoint aFront(aViewToObject * basegfx::B3DPoint(aRelativePoint.getX(), aRelativePoint.getY(), 0.0)); 275*cdf0e10cSrcweir const basegfx::B3DPoint aBack(aViewToObject * basegfx::B3DPoint(aRelativePoint.getX(), aRelativePoint.getY(), 1.0)); 276*cdf0e10cSrcweir 277*cdf0e10cSrcweir if(!aFront.equal(aBack)) 278*cdf0e10cSrcweir { 279*cdf0e10cSrcweir // get all hit points with object 280*cdf0e10cSrcweir ::std::vector< basegfx::B3DPoint > aHitsWithObject; 281*cdf0e10cSrcweir getAllHit3DObjectWithRelativePoint(aFront, aBack, rCandidate, aViewInfo3D, aHitsWithObject, true); 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir if(aHitsWithObject.size()) 284*cdf0e10cSrcweir { 285*cdf0e10cSrcweir return true; 286*cdf0e10cSrcweir } 287*cdf0e10cSrcweir } 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir } 290*cdf0e10cSrcweir 291*cdf0e10cSrcweir return false; 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 295*cdf0e10cSrcweir // eof 296