LCOV - code coverage report
Current view: top level - svx/source/engine3d - helperhittest3d.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 22 106 20.8 %
Date: 2015-06-13 12:38:46 Functions: 1 7 14.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11