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
10*f6e50924SAndrew Rist  *
11*f6e50924SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*f6e50924SAndrew Rist  *
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.
19*f6e50924SAndrew Rist  *
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:
ImplPairDephAndObject(const E3dCompoundObject * pObject,double fDepth)50cdf0e10cSrcweir     ImplPairDephAndObject(const E3dCompoundObject* pObject, double fDepth)
51cdf0e10cSrcweir     :   mpObject(pObject),
52cdf0e10cSrcweir         mfDepth(fDepth)
53cdf0e10cSrcweir     {}
54cdf0e10cSrcweir 
55cdf0e10cSrcweir     // for ::std::sort
operator <(const ImplPairDephAndObject & rComp) const56cdf0e10cSrcweir 	bool operator<(const ImplPairDephAndObject& rComp) const
57cdf0e10cSrcweir     {
58cdf0e10cSrcweir     	return (mfDepth < rComp.mfDepth);
59cdf0e10cSrcweir     }
60cdf0e10cSrcweir 
61cdf0e10cSrcweir     // data read access
getObject() const62cdf0e10cSrcweir     const E3dCompoundObject* getObject() const { return mpObject; }
getDepth() const63cdf0e10cSrcweir     double getDepth() const { return mfDepth; }
64cdf0e10cSrcweir };
65cdf0e10cSrcweir 
66cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
67cdf0e10cSrcweir 
getAllHit3DObjectWithRelativePoint(const basegfx::B3DPoint & rFront,const basegfx::B3DPoint & rBack,const E3dCompoundObject & rObject,const drawinglayer::geometry::ViewInformation3D & rObjectViewInformation3D,::std::vector<basegfx::B3DPoint> & o_rResult,bool bAnyHit)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 
fillViewInformation3DForCompoundObject(drawinglayer::geometry::ViewInformation3D & o_rViewInformation3D,const E3dCompoundObject & rCandidate)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 
getAllHit3DObjectsSortedFrontToBack(const basegfx::B2DPoint & rPoint,const E3dScene & rScene,::std::vector<const E3dCompoundObject * > & o_rResult)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 
checkHitSingle3DObject(const basegfx::B2DPoint & rPoint,const E3dCompoundObject & rCandidate)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