1*464702f4SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*464702f4SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*464702f4SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*464702f4SAndrew Rist  * distributed with this work for additional information
6*464702f4SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*464702f4SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*464702f4SAndrew Rist  * "License"); you may not use this file except in compliance
9*464702f4SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*464702f4SAndrew Rist  *
11*464702f4SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*464702f4SAndrew Rist  *
13*464702f4SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*464702f4SAndrew Rist  * software distributed under the License is distributed on an
15*464702f4SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*464702f4SAndrew Rist  * KIND, either express or implied.  See the License for the
17*464702f4SAndrew Rist  * specific language governing permissions and limitations
18*464702f4SAndrew Rist  * under the License.
19*464702f4SAndrew Rist  *
20*464702f4SAndrew Rist  *************************************************************/
21*464702f4SAndrew Rist 
22*464702f4SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <drawinglayer/processor3d/cutfindprocessor3d.hxx>
28cdf0e10cSrcweir #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
29cdf0e10cSrcweir #include <drawinglayer/primitive3d/transformprimitive3d.hxx>
30cdf0e10cSrcweir #include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
31cdf0e10cSrcweir #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
32cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygon.hxx>
33cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygontools.hxx>
34cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygontools.hxx>
35cdf0e10cSrcweir #include <drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
38cdf0e10cSrcweir 
39cdf0e10cSrcweir namespace drawinglayer
40cdf0e10cSrcweir {
41cdf0e10cSrcweir 	namespace processor3d
42cdf0e10cSrcweir 	{
CutFindProcessor(const geometry::ViewInformation3D & rViewInformation,const basegfx::B3DPoint & rFront,const basegfx::B3DPoint & rBack,bool bAnyHit)43cdf0e10cSrcweir         CutFindProcessor::CutFindProcessor(const geometry::ViewInformation3D& rViewInformation,
44cdf0e10cSrcweir             const basegfx::B3DPoint& rFront,
45cdf0e10cSrcweir             const basegfx::B3DPoint& rBack,
46cdf0e10cSrcweir             bool bAnyHit)
47cdf0e10cSrcweir         :   BaseProcessor3D(rViewInformation),
48cdf0e10cSrcweir             maFront(rFront),
49cdf0e10cSrcweir             maBack(rBack),
50cdf0e10cSrcweir             maResult(),
51cdf0e10cSrcweir             maCombinedTransform(),
52cdf0e10cSrcweir             mbAnyHit(bAnyHit),
53cdf0e10cSrcweir 			mbUseInvisiblePrimitiveContent(true)
54cdf0e10cSrcweir         {
55cdf0e10cSrcweir         }
56cdf0e10cSrcweir 
processBasePrimitive3D(const primitive3d::BasePrimitive3D & rCandidate)57cdf0e10cSrcweir         void CutFindProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
58cdf0e10cSrcweir         {
59cdf0e10cSrcweir 			if(getAnyHit() && maResult.size())
60cdf0e10cSrcweir 			{
61cdf0e10cSrcweir 				// stop processing as soon as a hit was recognized
62cdf0e10cSrcweir 				return;
63cdf0e10cSrcweir 			}
64cdf0e10cSrcweir 
65cdf0e10cSrcweir             // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
66cdf0e10cSrcweir 			switch(rCandidate.getPrimitive3DID())
67cdf0e10cSrcweir 			{
68cdf0e10cSrcweir 				case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
69cdf0e10cSrcweir 				{
70cdf0e10cSrcweir 					// transform group.
71cdf0e10cSrcweir 					const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate);
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 					// remember old and transform front, back to object coordinates
74cdf0e10cSrcweir 					const basegfx::B3DPoint aLastFront(maFront);
75cdf0e10cSrcweir 					const basegfx::B3DPoint aLastBack(maBack);
76cdf0e10cSrcweir 					basegfx::B3DHomMatrix aInverseTrans(rPrimitive.getTransformation());
77cdf0e10cSrcweir 					aInverseTrans.invert();
78cdf0e10cSrcweir 					maFront *= aInverseTrans;
79cdf0e10cSrcweir 					maBack *= aInverseTrans;
80cdf0e10cSrcweir 
81cdf0e10cSrcweir 					// remember current and create new transformation; add new object transform from right side
82cdf0e10cSrcweir 					const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
83cdf0e10cSrcweir 					const geometry::ViewInformation3D aNewViewInformation3D(
84cdf0e10cSrcweir 						aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(),
85cdf0e10cSrcweir 						aLastViewInformation3D.getOrientation(),
86cdf0e10cSrcweir 						aLastViewInformation3D.getProjection(),
87cdf0e10cSrcweir 						aLastViewInformation3D.getDeviceToView(),
88cdf0e10cSrcweir 						aLastViewInformation3D.getViewTime(),
89cdf0e10cSrcweir 						aLastViewInformation3D.getExtendedInformationSequence());
90cdf0e10cSrcweir 					updateViewInformation(aNewViewInformation3D);
91cdf0e10cSrcweir 
92cdf0e10cSrcweir                     // #i102956# remember needed back-transform for found cuts (combine from right side)
93cdf0e10cSrcweir                     const basegfx::B3DHomMatrix aLastCombinedTransform(maCombinedTransform);
94cdf0e10cSrcweir                     maCombinedTransform = maCombinedTransform * rPrimitive.getTransformation();
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 					// let break down
97cdf0e10cSrcweir 					process(rPrimitive.getChildren());
98cdf0e10cSrcweir 
99cdf0e10cSrcweir 					// restore transformations and front, back
100cdf0e10cSrcweir                     maCombinedTransform = aLastCombinedTransform;
101cdf0e10cSrcweir 					updateViewInformation(aLastViewInformation3D);
102cdf0e10cSrcweir 					maFront = aLastFront;
103cdf0e10cSrcweir 					maBack = aLastBack;
104cdf0e10cSrcweir 					break;
105cdf0e10cSrcweir 				}
106cdf0e10cSrcweir 				case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
107cdf0e10cSrcweir 				{
108cdf0e10cSrcweir 					// PolygonHairlinePrimitive3D, not used for hit test with planes, ignore. This
109cdf0e10cSrcweir 					// means that also thick line expansion will not be hit-tested as
110cdf0e10cSrcweir 					// PolyPolygonMaterialPrimitive3D
111cdf0e10cSrcweir                     break;
112cdf0e10cSrcweir 				}
113cdf0e10cSrcweir 				case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D :
114cdf0e10cSrcweir 				{
115cdf0e10cSrcweir 					// #i97321#
116cdf0e10cSrcweir 					// For HatchTexturePrimitive3D, do not use the decomposition since it will produce
117cdf0e10cSrcweir 					// clipped hatch lines in 3D. It can be used when the hatch also has a filling, but for
118cdf0e10cSrcweir 					// simplicity, just use the children which are the PolyPolygonMaterialPrimitive3D
119cdf0e10cSrcweir 					// which define the hatched areas anyways; for HitTest this is more than adequate
120cdf0e10cSrcweir 					const primitive3d::HatchTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::HatchTexturePrimitive3D& >(rCandidate);
121cdf0e10cSrcweir 					process(rPrimitive.getChildren());
122cdf0e10cSrcweir 					break;
123cdf0e10cSrcweir 				}
124cdf0e10cSrcweir 				case PRIMITIVE3D_ID_HIDDENGEOMETRYPRIMITIVE3D :
125cdf0e10cSrcweir 				{
126cdf0e10cSrcweir 					// HiddenGeometryPrimitive3D; the default decomposition would return an empty seqence,
127cdf0e10cSrcweir 					// so force this primitive to process it's children directly if the switch is set
128cdf0e10cSrcweir 					// (which is the default). Else, ignore invisible content
129cdf0e10cSrcweir 				    const primitive3d::HiddenGeometryPrimitive3D& rHiddenGeometry(static_cast< const primitive3d::HiddenGeometryPrimitive3D& >(rCandidate));
130cdf0e10cSrcweir        			    const primitive3d::Primitive3DSequence& rChildren = rHiddenGeometry.getChildren();
131cdf0e10cSrcweir 
132cdf0e10cSrcweir                     if(rChildren.hasElements())
133cdf0e10cSrcweir                     {
134cdf0e10cSrcweir                         if(getUseInvisiblePrimitiveContent())
135cdf0e10cSrcweir 					    {
136cdf0e10cSrcweir                             process(rChildren);
137cdf0e10cSrcweir 					    }
138cdf0e10cSrcweir                     }
139cdf0e10cSrcweir 
140cdf0e10cSrcweir                     break;
141cdf0e10cSrcweir 				}
142cdf0e10cSrcweir                 case PRIMITIVE3D_ID_UNIFIEDTRANSPARENCETEXTUREPRIMITIVE3D :
143cdf0e10cSrcweir                 {
144cdf0e10cSrcweir 					const primitive3d::UnifiedTransparenceTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::UnifiedTransparenceTexturePrimitive3D& >(rCandidate);
145cdf0e10cSrcweir        			    const primitive3d::Primitive3DSequence rChildren = rPrimitive.getChildren();
146cdf0e10cSrcweir 
147cdf0e10cSrcweir                     if(rChildren.getLength())
148cdf0e10cSrcweir                     {
149cdf0e10cSrcweir     			        if(1.0 <= rPrimitive.getTransparence())
150cdf0e10cSrcweir                         {
151cdf0e10cSrcweir                             // not visible, but use for HitTest
152cdf0e10cSrcweir 					        if(getUseInvisiblePrimitiveContent())
153cdf0e10cSrcweir 					        {
154cdf0e10cSrcweir            						process(rChildren);
155cdf0e10cSrcweir                             }
156cdf0e10cSrcweir                         }
157cdf0e10cSrcweir                         else if(rPrimitive.getTransparence() >= 0.0 && rPrimitive.getTransparence() < 1.0)
158cdf0e10cSrcweir 			            {
159cdf0e10cSrcweir                             // visible; use content
160cdf0e10cSrcweir     						process(rChildren);
161cdf0e10cSrcweir                         }
162cdf0e10cSrcweir                     }
163cdf0e10cSrcweir 
164cdf0e10cSrcweir                     break;
165cdf0e10cSrcweir                 }
166cdf0e10cSrcweir 				case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
167cdf0e10cSrcweir 				{
168cdf0e10cSrcweir 					// PolyPolygonMaterialPrimitive3D
169cdf0e10cSrcweir 					const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate);
170cdf0e10cSrcweir 
171cdf0e10cSrcweir                     if(!maFront.equal(maBack))
172cdf0e10cSrcweir                     {
173cdf0e10cSrcweir            			    const basegfx::B3DPolyPolygon& rPolyPolygon = rPrimitive.getB3DPolyPolygon();
174cdf0e10cSrcweir                         const sal_uInt32 nPolyCount(rPolyPolygon.count());
175cdf0e10cSrcweir 
176cdf0e10cSrcweir                         if(nPolyCount)
177cdf0e10cSrcweir                         {
178cdf0e10cSrcweir            			        const basegfx::B3DPolygon aPolygon(rPolyPolygon.getB3DPolygon(0));
179cdf0e10cSrcweir                             const sal_uInt32 nPointCount(aPolygon.count());
180cdf0e10cSrcweir 
181cdf0e10cSrcweir                             if(nPointCount > 2)
182cdf0e10cSrcweir                             {
183cdf0e10cSrcweir                                 const basegfx::B3DVector aPlaneNormal(aPolygon.getNormal());
184cdf0e10cSrcweir 
185cdf0e10cSrcweir                                 if(!aPlaneNormal.equalZero())
186cdf0e10cSrcweir                                 {
187cdf0e10cSrcweir                                     const basegfx::B3DPoint aPointOnPlane(aPolygon.getB3DPoint(0));
188cdf0e10cSrcweir                                     double fCut(0.0);
189cdf0e10cSrcweir 
190cdf0e10cSrcweir                                     if(basegfx::tools::getCutBetweenLineAndPlane(aPlaneNormal, aPointOnPlane, maFront, maBack, fCut))
191cdf0e10cSrcweir                                     {
192cdf0e10cSrcweir                                         const basegfx::B3DPoint aCutPoint(basegfx::interpolate(maFront, maBack, fCut));
193cdf0e10cSrcweir 
194cdf0e10cSrcweir                                         if(basegfx::tools::isInside(rPolyPolygon, aCutPoint, false))
195cdf0e10cSrcweir                                         {
196cdf0e10cSrcweir                                             // #i102956# add result. Do not forget to do this in the coordinate
197cdf0e10cSrcweir                                             // system the processor get started with, so use the collected
198cdf0e10cSrcweir                                             // combined transformation from processed TransformPrimitive3D's
199cdf0e10cSrcweir                                             maResult.push_back(maCombinedTransform * aCutPoint);
200cdf0e10cSrcweir                                         }
201cdf0e10cSrcweir                                     }
202cdf0e10cSrcweir                                 }
203cdf0e10cSrcweir                             }
204cdf0e10cSrcweir                         }
205cdf0e10cSrcweir                     }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir                     break;
208cdf0e10cSrcweir 				}
209cdf0e10cSrcweir 				default :
210cdf0e10cSrcweir 				{
211cdf0e10cSrcweir 					// process recursively
212cdf0e10cSrcweir 					process(rCandidate.get3DDecomposition(getViewInformation3D()));
213cdf0e10cSrcweir 					break;
214cdf0e10cSrcweir 				}
215cdf0e10cSrcweir             }
216cdf0e10cSrcweir         }
217cdf0e10cSrcweir 	} // end of namespace processor3d
218cdf0e10cSrcweir } // end of namespace drawinglayer
219cdf0e10cSrcweir 
220cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
221cdf0e10cSrcweir // eof
222