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