xref: /AOO41X/main/svx/source/sdr/contact/viewcontactofe3dpolygon.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
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_svx.hxx"
26 
27 #include <svx/sdr/contact/viewcontactofe3dpolygon.hxx>
28 #include <svx/polygn3d.hxx>
29 #include <drawinglayer/primitive3d/sdrpolypolygonprimitive3d.hxx>
30 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
31 #include <svx/sdr/primitive3d/sdrattributecreator3d.hxx>
32 #include <basegfx/polygon/b3dpolygon.hxx>
33 #include <basegfx/polygon/b3dpolypolygontools.hxx>
34 
35 //////////////////////////////////////////////////////////////////////////////
36 
37 namespace sdr
38 {
39     namespace contact
40     {
ViewContactOfE3dPolygon(E3dPolygonObj & rPolygon)41         ViewContactOfE3dPolygon::ViewContactOfE3dPolygon(E3dPolygonObj& rPolygon)
42         :   ViewContactOfE3d(rPolygon)
43         {
44         }
45 
~ViewContactOfE3dPolygon()46         ViewContactOfE3dPolygon::~ViewContactOfE3dPolygon()
47         {
48         }
49 
createViewIndependentPrimitive3DSequence() const50         drawinglayer::primitive3d::Primitive3DSequence ViewContactOfE3dPolygon::createViewIndependentPrimitive3DSequence() const
51         {
52             drawinglayer::primitive3d::Primitive3DSequence xRetval;
53             const SfxItemSet& rItemSet = GetE3dPolygonObj().GetMergedItemSet();
54             const bool bSuppressFill(GetE3dPolygonObj().GetLineOnly());
55             const drawinglayer::attribute::SdrLineFillShadowAttribute3D aAttribute(
56                 drawinglayer::primitive2d::createNewSdrLineFillShadowAttribute(rItemSet, bSuppressFill));
57 
58             // get extrude geometry
59             basegfx::B3DPolyPolygon aPolyPolygon3D(GetE3dPolygonObj().GetPolyPolygon3D());
60             const basegfx::B3DPolyPolygon aPolyNormals3D(GetE3dPolygonObj().GetPolyNormals3D());
61             const basegfx::B2DPolyPolygon aPolyTexture2D(GetE3dPolygonObj().GetPolyTexture2D());
62             const bool bNormals(aPolyNormals3D.count() && aPolyNormals3D.count() == aPolyPolygon3D.count());
63             const bool bTexture(aPolyTexture2D.count() && aPolyTexture2D.count() == aPolyPolygon3D.count());
64 
65             if(bNormals || bTexture)
66             {
67                 for(sal_uInt32 a(0L); a < aPolyPolygon3D.count(); a++)
68                 {
69                     basegfx::B3DPolygon aCandidate3D(aPolyPolygon3D.getB3DPolygon(a));
70                     basegfx::B3DPolygon aNormals3D;
71                     basegfx::B2DPolygon aTexture2D;
72 
73                     if(bNormals)
74                     {
75                         aNormals3D = aPolyNormals3D.getB3DPolygon(a);
76                     }
77 
78                     if(bTexture)
79                     {
80                         aTexture2D = aPolyTexture2D.getB2DPolygon(a);
81                     }
82 
83                     for(sal_uInt32 b(0L); b < aCandidate3D.count(); b++)
84                     {
85                         if(bNormals)
86                         {
87                             sal_uInt32 nNormalCount = aNormals3D.count();
88                             if( b < nNormalCount )
89                                 aCandidate3D.setNormal(b, aNormals3D.getB3DPoint(b));
90                             else if( nNormalCount > 0 )
91                                 aCandidate3D.setNormal(b, aNormals3D.getB3DPoint(0));
92                         }
93                         if(bTexture)
94                         {
95                             sal_uInt32 nTextureCount = aTexture2D.count();
96                             if( b < nTextureCount )
97                                 aCandidate3D.setTextureCoordinate(b, aTexture2D.getB2DPoint(b));
98                             else if( nTextureCount > 0 )
99                                 aCandidate3D.setTextureCoordinate(b, aTexture2D.getB2DPoint(0));
100                         }
101                     }
102 
103                     aPolyPolygon3D.setB3DPolygon(a, aCandidate3D);
104                 }
105             }
106 
107             // get 3D Object Attributes
108             drawinglayer::attribute::Sdr3DObjectAttribute* pSdr3DObjectAttribute = drawinglayer::primitive2d::createNewSdr3DObjectAttribute(rItemSet);
109 
110             // calculate texture size
111             basegfx::B2DVector aTextureSize(1.0, 1.0);
112 
113             if(bTexture)
114             {
115                 // #i98314#
116                 // create texture size from object's size
117                 const basegfx::B3DRange aObjectRange(basegfx::tools::getRange(aPolyPolygon3D));
118 
119                 double fWidth(0.0);
120                 double fHeight(0.0);
121 
122                 // this is a polygon object, so Width/Height and/or Depth may be zero (e.g. left
123                 // wall of chart). Take this into account
124                 if(basegfx::fTools::equalZero(aObjectRange.getWidth()))
125                 {
126                     // width is zero, use height and depth
127                     fWidth = aObjectRange.getHeight();
128                     fHeight = aObjectRange.getDepth();
129                 }
130                 else if(basegfx::fTools::equalZero(aObjectRange.getHeight()))
131                 {
132                     // height is zero, use width and depth
133                     fWidth = aObjectRange.getWidth();
134                     fHeight = aObjectRange.getDepth();
135                 }
136                 else
137                 {
138                     // use width and height
139                     fWidth = aObjectRange.getWidth();
140                     fHeight = aObjectRange.getHeight();
141                 }
142 
143                 if(basegfx::fTools::lessOrEqual(fWidth, 0.0) ||basegfx::fTools::lessOrEqual(fHeight, 0.0))
144                 {
145                     // no texture; fallback to very small size
146                     aTextureSize.setX(0.01);
147                     aTextureSize.setY(0.01);
148                 }
149                 else
150                 {
151                     aTextureSize.setX(fWidth);
152                     aTextureSize.setY(fHeight);
153                 }
154             }
155 
156             // #i98295#
157             // unfortunately, this SdrObject type which allows a free 3d geometry definition was defined
158             // wrong topologically in relation to it's plane normal and 3D visibility when it was invented
159             // a long time ago. Since the API allows creation of this SDrObject type, it is not possible to
160             // simply change this definition. Only the chart should use it, and at least this object type
161             // only exists at Runtime (is not saved and/or loaded in any FileFormat). Still someone external
162             // may have used it in it's API. To not risk wrong 3D lightings, i have to switch the orientation
163             // of the polygon here
164             aPolyPolygon3D.flip();
165 
166             // create primitive and add
167             const basegfx::B3DHomMatrix aWorldTransform;
168             const drawinglayer::primitive3d::Primitive3DReference xReference(
169                 new drawinglayer::primitive3d::SdrPolyPolygonPrimitive3D(
170                     aPolyPolygon3D, aWorldTransform, aTextureSize, aAttribute, *pSdr3DObjectAttribute));
171             xRetval = drawinglayer::primitive3d::Primitive3DSequence(&xReference, 1);
172 
173             // delete 3D Object Attributes
174             delete pSdr3DObjectAttribute;
175 
176             return xRetval;
177         }
178     } // end of namespace contact
179 } // end of namespace sdr
180 
181 //////////////////////////////////////////////////////////////////////////////
182 // eof
183