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