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