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