xref: /AOO41X/main/drawinglayer/source/processor3d/cutfindprocessor3d.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_drawinglayer.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <drawinglayer/processor3d/cutfindprocessor3d.hxx>
32*cdf0e10cSrcweir #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
33*cdf0e10cSrcweir #include <drawinglayer/primitive3d/transformprimitive3d.hxx>
34*cdf0e10cSrcweir #include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
35*cdf0e10cSrcweir #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
36*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygon.hxx>
37*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygontools.hxx>
38*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygontools.hxx>
39*cdf0e10cSrcweir #include <drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir namespace drawinglayer
44*cdf0e10cSrcweir {
45*cdf0e10cSrcweir 	namespace processor3d
46*cdf0e10cSrcweir 	{
47*cdf0e10cSrcweir         CutFindProcessor::CutFindProcessor(const geometry::ViewInformation3D& rViewInformation,
48*cdf0e10cSrcweir             const basegfx::B3DPoint& rFront,
49*cdf0e10cSrcweir             const basegfx::B3DPoint& rBack,
50*cdf0e10cSrcweir             bool bAnyHit)
51*cdf0e10cSrcweir         :   BaseProcessor3D(rViewInformation),
52*cdf0e10cSrcweir             maFront(rFront),
53*cdf0e10cSrcweir             maBack(rBack),
54*cdf0e10cSrcweir             maResult(),
55*cdf0e10cSrcweir             maCombinedTransform(),
56*cdf0e10cSrcweir             mbAnyHit(bAnyHit),
57*cdf0e10cSrcweir 			mbUseInvisiblePrimitiveContent(true)
58*cdf0e10cSrcweir         {
59*cdf0e10cSrcweir         }
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir         void CutFindProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
62*cdf0e10cSrcweir         {
63*cdf0e10cSrcweir 			if(getAnyHit() && maResult.size())
64*cdf0e10cSrcweir 			{
65*cdf0e10cSrcweir 				// stop processing as soon as a hit was recognized
66*cdf0e10cSrcweir 				return;
67*cdf0e10cSrcweir 			}
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir             // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
70*cdf0e10cSrcweir 			switch(rCandidate.getPrimitive3DID())
71*cdf0e10cSrcweir 			{
72*cdf0e10cSrcweir 				case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
73*cdf0e10cSrcweir 				{
74*cdf0e10cSrcweir 					// transform group.
75*cdf0e10cSrcweir 					const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate);
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir 					// remember old and transform front, back to object coordinates
78*cdf0e10cSrcweir 					const basegfx::B3DPoint aLastFront(maFront);
79*cdf0e10cSrcweir 					const basegfx::B3DPoint aLastBack(maBack);
80*cdf0e10cSrcweir 					basegfx::B3DHomMatrix aInverseTrans(rPrimitive.getTransformation());
81*cdf0e10cSrcweir 					aInverseTrans.invert();
82*cdf0e10cSrcweir 					maFront *= aInverseTrans;
83*cdf0e10cSrcweir 					maBack *= aInverseTrans;
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir 					// remember current and create new transformation; add new object transform from right side
86*cdf0e10cSrcweir 					const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
87*cdf0e10cSrcweir 					const geometry::ViewInformation3D aNewViewInformation3D(
88*cdf0e10cSrcweir 						aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(),
89*cdf0e10cSrcweir 						aLastViewInformation3D.getOrientation(),
90*cdf0e10cSrcweir 						aLastViewInformation3D.getProjection(),
91*cdf0e10cSrcweir 						aLastViewInformation3D.getDeviceToView(),
92*cdf0e10cSrcweir 						aLastViewInformation3D.getViewTime(),
93*cdf0e10cSrcweir 						aLastViewInformation3D.getExtendedInformationSequence());
94*cdf0e10cSrcweir 					updateViewInformation(aNewViewInformation3D);
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir                     // #i102956# remember needed back-transform for found cuts (combine from right side)
97*cdf0e10cSrcweir                     const basegfx::B3DHomMatrix aLastCombinedTransform(maCombinedTransform);
98*cdf0e10cSrcweir                     maCombinedTransform = maCombinedTransform * rPrimitive.getTransformation();
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir 					// let break down
101*cdf0e10cSrcweir 					process(rPrimitive.getChildren());
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir 					// restore transformations and front, back
104*cdf0e10cSrcweir                     maCombinedTransform = aLastCombinedTransform;
105*cdf0e10cSrcweir 					updateViewInformation(aLastViewInformation3D);
106*cdf0e10cSrcweir 					maFront = aLastFront;
107*cdf0e10cSrcweir 					maBack = aLastBack;
108*cdf0e10cSrcweir 					break;
109*cdf0e10cSrcweir 				}
110*cdf0e10cSrcweir 				case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
111*cdf0e10cSrcweir 				{
112*cdf0e10cSrcweir 					// PolygonHairlinePrimitive3D, not used for hit test with planes, ignore. This
113*cdf0e10cSrcweir 					// means that also thick line expansion will not be hit-tested as
114*cdf0e10cSrcweir 					// PolyPolygonMaterialPrimitive3D
115*cdf0e10cSrcweir                     break;
116*cdf0e10cSrcweir 				}
117*cdf0e10cSrcweir 				case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D :
118*cdf0e10cSrcweir 				{
119*cdf0e10cSrcweir 					// #i97321#
120*cdf0e10cSrcweir 					// For HatchTexturePrimitive3D, do not use the decomposition since it will produce
121*cdf0e10cSrcweir 					// clipped hatch lines in 3D. It can be used when the hatch also has a filling, but for
122*cdf0e10cSrcweir 					// simplicity, just use the children which are the PolyPolygonMaterialPrimitive3D
123*cdf0e10cSrcweir 					// which define the hatched areas anyways; for HitTest this is more than adequate
124*cdf0e10cSrcweir 					const primitive3d::HatchTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::HatchTexturePrimitive3D& >(rCandidate);
125*cdf0e10cSrcweir 					process(rPrimitive.getChildren());
126*cdf0e10cSrcweir 					break;
127*cdf0e10cSrcweir 				}
128*cdf0e10cSrcweir 				case PRIMITIVE3D_ID_HIDDENGEOMETRYPRIMITIVE3D :
129*cdf0e10cSrcweir 				{
130*cdf0e10cSrcweir 					// HiddenGeometryPrimitive3D; the default decomposition would return an empty seqence,
131*cdf0e10cSrcweir 					// so force this primitive to process it's children directly if the switch is set
132*cdf0e10cSrcweir 					// (which is the default). Else, ignore invisible content
133*cdf0e10cSrcweir 				    const primitive3d::HiddenGeometryPrimitive3D& rHiddenGeometry(static_cast< const primitive3d::HiddenGeometryPrimitive3D& >(rCandidate));
134*cdf0e10cSrcweir        			    const primitive3d::Primitive3DSequence& rChildren = rHiddenGeometry.getChildren();
135*cdf0e10cSrcweir 
136*cdf0e10cSrcweir                     if(rChildren.hasElements())
137*cdf0e10cSrcweir                     {
138*cdf0e10cSrcweir                         if(getUseInvisiblePrimitiveContent())
139*cdf0e10cSrcweir 					    {
140*cdf0e10cSrcweir                             process(rChildren);
141*cdf0e10cSrcweir 					    }
142*cdf0e10cSrcweir                     }
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir                     break;
145*cdf0e10cSrcweir 				}
146*cdf0e10cSrcweir                 case PRIMITIVE3D_ID_UNIFIEDTRANSPARENCETEXTUREPRIMITIVE3D :
147*cdf0e10cSrcweir                 {
148*cdf0e10cSrcweir 					const primitive3d::UnifiedTransparenceTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::UnifiedTransparenceTexturePrimitive3D& >(rCandidate);
149*cdf0e10cSrcweir        			    const primitive3d::Primitive3DSequence rChildren = rPrimitive.getChildren();
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir                     if(rChildren.getLength())
152*cdf0e10cSrcweir                     {
153*cdf0e10cSrcweir     			        if(1.0 <= rPrimitive.getTransparence())
154*cdf0e10cSrcweir                         {
155*cdf0e10cSrcweir                             // not visible, but use for HitTest
156*cdf0e10cSrcweir 					        if(getUseInvisiblePrimitiveContent())
157*cdf0e10cSrcweir 					        {
158*cdf0e10cSrcweir            						process(rChildren);
159*cdf0e10cSrcweir                             }
160*cdf0e10cSrcweir                         }
161*cdf0e10cSrcweir                         else if(rPrimitive.getTransparence() >= 0.0 && rPrimitive.getTransparence() < 1.0)
162*cdf0e10cSrcweir 			            {
163*cdf0e10cSrcweir                             // visible; use content
164*cdf0e10cSrcweir     						process(rChildren);
165*cdf0e10cSrcweir                         }
166*cdf0e10cSrcweir                     }
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir                     break;
169*cdf0e10cSrcweir                 }
170*cdf0e10cSrcweir 				case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
171*cdf0e10cSrcweir 				{
172*cdf0e10cSrcweir 					// PolyPolygonMaterialPrimitive3D
173*cdf0e10cSrcweir 					const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate);
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir                     if(!maFront.equal(maBack))
176*cdf0e10cSrcweir                     {
177*cdf0e10cSrcweir            			    const basegfx::B3DPolyPolygon& rPolyPolygon = rPrimitive.getB3DPolyPolygon();
178*cdf0e10cSrcweir                         const sal_uInt32 nPolyCount(rPolyPolygon.count());
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir                         if(nPolyCount)
181*cdf0e10cSrcweir                         {
182*cdf0e10cSrcweir            			        const basegfx::B3DPolygon aPolygon(rPolyPolygon.getB3DPolygon(0));
183*cdf0e10cSrcweir                             const sal_uInt32 nPointCount(aPolygon.count());
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir                             if(nPointCount > 2)
186*cdf0e10cSrcweir                             {
187*cdf0e10cSrcweir                                 const basegfx::B3DVector aPlaneNormal(aPolygon.getNormal());
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir                                 if(!aPlaneNormal.equalZero())
190*cdf0e10cSrcweir                                 {
191*cdf0e10cSrcweir                                     const basegfx::B3DPoint aPointOnPlane(aPolygon.getB3DPoint(0));
192*cdf0e10cSrcweir                                     double fCut(0.0);
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir                                     if(basegfx::tools::getCutBetweenLineAndPlane(aPlaneNormal, aPointOnPlane, maFront, maBack, fCut))
195*cdf0e10cSrcweir                                     {
196*cdf0e10cSrcweir                                         const basegfx::B3DPoint aCutPoint(basegfx::interpolate(maFront, maBack, fCut));
197*cdf0e10cSrcweir 
198*cdf0e10cSrcweir                                         if(basegfx::tools::isInside(rPolyPolygon, aCutPoint, false))
199*cdf0e10cSrcweir                                         {
200*cdf0e10cSrcweir                                             // #i102956# add result. Do not forget to do this in the coordinate
201*cdf0e10cSrcweir                                             // system the processor get started with, so use the collected
202*cdf0e10cSrcweir                                             // combined transformation from processed TransformPrimitive3D's
203*cdf0e10cSrcweir                                             maResult.push_back(maCombinedTransform * aCutPoint);
204*cdf0e10cSrcweir                                         }
205*cdf0e10cSrcweir                                     }
206*cdf0e10cSrcweir                                 }
207*cdf0e10cSrcweir                             }
208*cdf0e10cSrcweir                         }
209*cdf0e10cSrcweir                     }
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir                     break;
212*cdf0e10cSrcweir 				}
213*cdf0e10cSrcweir 				default :
214*cdf0e10cSrcweir 				{
215*cdf0e10cSrcweir 					// process recursively
216*cdf0e10cSrcweir 					process(rCandidate.get3DDecomposition(getViewInformation3D()));
217*cdf0e10cSrcweir 					break;
218*cdf0e10cSrcweir 				}
219*cdf0e10cSrcweir             }
220*cdf0e10cSrcweir         }
221*cdf0e10cSrcweir 	} // end of namespace processor3d
222*cdf0e10cSrcweir } // end of namespace drawinglayer
223*cdf0e10cSrcweir 
224*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
225*cdf0e10cSrcweir // eof
226