LibreOffice Module svx (master)  1
viewcontactofe3dpolygon.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
22 #include <polygn3d.hxx>
28 #include <memory>
29 
30 
31 namespace sdr::contact
32 {
34  : ViewContactOfE3d(rPolygon)
35  {
36  }
37 
39  {
40  }
41 
43  {
45  const SfxItemSet& rItemSet = GetE3dPolygonObj().GetMergedItemSet();
46  const bool bSuppressFill(GetE3dPolygonObj().GetLineOnly());
49 
50  // get extrude geometry
51  basegfx::B3DPolyPolygon aPolyPolygon3D(GetE3dPolygonObj().GetPolyPolygon3D());
52  const basegfx::B3DPolyPolygon aPolyNormals3D(GetE3dPolygonObj().GetPolyNormals3D());
53  const basegfx::B2DPolyPolygon aPolyTexture2D(GetE3dPolygonObj().GetPolyTexture2D());
54  const bool bNormals(aPolyNormals3D.count() && aPolyNormals3D.count() == aPolyPolygon3D.count());
55  const bool bTexture(aPolyTexture2D.count() && aPolyTexture2D.count() == aPolyPolygon3D.count());
56 
57  if(bNormals || bTexture)
58  {
59  for(sal_uInt32 a(0); a < aPolyPolygon3D.count(); a++)
60  {
61  basegfx::B3DPolygon aCandidate3D(aPolyPolygon3D.getB3DPolygon(a));
62  basegfx::B3DPolygon aNormals3D;
63  basegfx::B2DPolygon aTexture2D;
64 
65  if(bNormals)
66  {
67  aNormals3D = aPolyNormals3D.getB3DPolygon(a);
68  }
69 
70  if(bTexture)
71  {
72  aTexture2D = aPolyTexture2D.getB2DPolygon(a);
73  }
74 
75  for(sal_uInt32 b(0); b < aCandidate3D.count(); b++)
76  {
77  if(bNormals)
78  {
79  sal_uInt32 nNormalCount = aNormals3D.count();
80  if( b < nNormalCount )
81  aCandidate3D.setNormal(b, aNormals3D.getB3DPoint(b));
82  else if( nNormalCount > 0 )
83  aCandidate3D.setNormal(b, aNormals3D.getB3DPoint(0));
84  }
85  if(bTexture)
86  {
87  sal_uInt32 nTextureCount = aTexture2D.count();
88  if( b < nTextureCount )
89  aCandidate3D.setTextureCoordinate(b, aTexture2D.getB2DPoint(b));
90  else if( nTextureCount > 0 )
91  aCandidate3D.setTextureCoordinate(b, aTexture2D.getB2DPoint(0));
92  }
93  }
94 
95  aPolyPolygon3D.setB3DPolygon(a, aCandidate3D);
96  }
97  }
98 
99  // get 3D Object Attributes
100  std::unique_ptr<drawinglayer::attribute::Sdr3DObjectAttribute> pSdr3DObjectAttribute(drawinglayer::primitive2d::createNewSdr3DObjectAttribute(rItemSet));
101 
102  // calculate texture size
103  basegfx::B2DVector aTextureSize(1.0, 1.0);
104 
105  if(bTexture)
106  {
107  // #i98314#
108  // create texture size from object's size
109  const basegfx::B3DRange aObjectRange(basegfx::utils::getRange(aPolyPolygon3D));
110 
111  double fWidth(0.0);
112  double fHeight(0.0);
113 
114  // this is a polygon object, so Width/Height and/or Depth may be zero (e.g. left
115  // wall of chart). Take this into account
116  if(basegfx::fTools::equalZero(aObjectRange.getWidth()))
117  {
118  // width is zero, use height and depth
119  fWidth = aObjectRange.getHeight();
120  fHeight = aObjectRange.getDepth();
121  }
122  else if(basegfx::fTools::equalZero(aObjectRange.getHeight()))
123  {
124  // height is zero, use width and depth
125  fWidth = aObjectRange.getWidth();
126  fHeight = aObjectRange.getDepth();
127  }
128  else
129  {
130  // use width and height
131  fWidth = aObjectRange.getWidth();
132  fHeight = aObjectRange.getHeight();
133  }
134 
135  if(basegfx::fTools::lessOrEqual(fWidth, 0.0) ||basegfx::fTools::lessOrEqual(fHeight, 0.0))
136  {
137  // no texture; fallback to very small size
138  aTextureSize.setX(0.01);
139  aTextureSize.setY(0.01);
140  }
141  else
142  {
143  aTextureSize.setX(fWidth);
144  aTextureSize.setY(fHeight);
145  }
146  }
147 
148  // #i98295#
149  // unfortunately, this SdrObject type which allows a free 3d geometry definition was defined
150  // wrong topologically in relation to its plane normal and 3D visibility when it was invented
151  // a long time ago. Since the API allows creation of this SDrObject type, it is not possible to
152  // simply change this definition. Only the chart should use it, and at least this object type
153  // only exists at Runtime (is not saved and/or loaded in any FileFormat). Still someone external
154  // may have used it in its API. To not risk wrong 3D lightings, I have to switch the orientation
155  // of the polygon here
156  aPolyPolygon3D.flip();
157 
158  // create primitive and add
159  const basegfx::B3DHomMatrix aWorldTransform;
162  aPolyPolygon3D, aWorldTransform, aTextureSize, aAttribute, *pSdr3DObjectAttribute));
163  xRetval = { xReference };
164 
165  return xRetval;
166  }
167 
168 } // end of namespace
169 
170 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool lessOrEqual(const double &rfValA, const double &rfValB)
void setX(double fX)
const E3dPolygonObj & GetE3dPolygonObj() const
virtual drawinglayer::primitive3d::Primitive3DContainer createViewIndependentPrimitive3DContainer() const override
attribute::Sdr3DObjectAttribute * createNewSdr3DObjectAttribute(const SfxItemSet &rSet)
attribute::SdrLineFillShadowAttribute3D createNewSdrLineFillShadowAttribute(const SfxItemSet &rSet, bool bSuppressFill)
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
sal_uInt32 count() const
double getHeight() const
uno_Any a
static bool equalZero(const double &rfVal)
css::uno::Reference< css::graphic::XPrimitive3D > Primitive3DReference
B2DRange getRange(const B2DPolygon &rCandidate)
void setB3DPolygon(sal_uInt32 nIndex, const B3DPolygon &rPolygon)
double getWidth() const
sal_uInt32 count() const
void setY(double fY)
double getDepth() const
B3DPolygon const & getB3DPolygon(sal_uInt32 nIndex) const
sal_uInt32 count() const
basegfx::B2DPoint const & getB2DPoint(sal_uInt32 nIndex) const