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