LibreOffice Module drawinglayer (master) 1
sdrlatheprimitive3d.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
29#include <utility>
30
31
32using namespace com::sun::star;
33
34
36{
38 {
40
41 // get slices
42 const Slice3DVector& rSliceVector = getSlices();
43
44 if(!rSliceVector.empty())
45 {
46 const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0));
47 const bool bClosedRotation(!bBackScale && getHorizontalSegments() && basegfx::fTools::equal(getRotation(), 2 * M_PI));
48 sal_uInt32 a;
49
50 // decide what to create
51 const css::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
52 const bool bCreateNormals(css::drawing::NormalsKind_SPECIFIC == eNormalsKind);
53 const bool bCreateTextureCoordinatesX(css::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
54 const bool bCreateTextureCoordinatesY(css::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
55 basegfx::B2DHomMatrix aTexTransform;
56
57 if(!getSdrLFSAttribute().getFill().isDefault()
58 && (bCreateTextureCoordinatesX || bCreateTextureCoordinatesY))
59 {
60 aTexTransform.set(0, 0, 0.0);
61 aTexTransform.set(0, 1, 1.0);
62 aTexTransform.set(1, 0, 1.0);
63 aTexTransform.set(1, 1, 0.0);
64
65 aTexTransform.translate(0.0, -0.5);
66 aTexTransform.scale(1.0, -1.0);
67 aTexTransform.translate(0.0, 0.5);
68 }
69
70 // create geometry
71 std::vector< basegfx::B3DPolyPolygon > aFill;
72 extractPlanesFromSlice(aFill, rSliceVector,
73 bCreateNormals, getSmoothNormals(), getSmoothLids(), bClosedRotation,
74 0.85, 0.6, bCreateTextureCoordinatesX || bCreateTextureCoordinatesY, aTexTransform);
75
76 // get full range
77 const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
78
79 // normal creation
80 if(!getSdrLFSAttribute().getFill().isDefault())
81 {
82 if(css::drawing::NormalsKind_SPHERE == eNormalsKind)
83 {
85 }
86 else if(css::drawing::NormalsKind_FLAT == eNormalsKind)
87 {
89 }
90
91 if(getSdr3DObjectAttribute().getNormalsInvert())
92 {
94 }
95 }
96
97 // texture coordinates
98 if(!getSdrLFSAttribute().getFill().isDefault())
99 {
101 getSdr3DObjectAttribute().getTextureProjectionX(),
102 getSdr3DObjectAttribute().getTextureProjectionY(),
103 aFill,
104 aRange,
106 }
107
108 if(!getSdrLFSAttribute().getFill().isDefault())
109 {
110 // add fill
112 aFill,
113 getTransform(),
116 getSdrLFSAttribute().getFill(),
117 getSdrLFSAttribute().getFillFloatTransGradient());
118 }
119 else
120 {
121 // create simplified 3d hit test geometry
123 aFill,
124 getTransform(),
127 }
128
129 // add line
130 if(!getSdrLFSAttribute().getLine().isDefault())
131 {
132 if(getSdr3DObjectAttribute().getReducedLineGeometry())
133 {
134 // create geometric outlines with reduced line geometry for chart
135 const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
136 const sal_uInt32 nCount(aHorLine.count());
137 basegfx::B3DPolyPolygon aNewLineGeometry;
138
139 for(a = 1; a < nCount; a++)
140 {
141 // for each loop pair create the connection edges
143 rViewInformation,
144 getTransform(),
145 aHorLine.getB3DPolygon(a - 1),
146 aHorLine.getB3DPolygon(a),
147 aNewLineGeometry);
148 }
149
150 for(a = 0; a < nCount; a++)
151 {
152 // filter hor lines for empty loops (those who have their defining point on the Y-Axis)
153 basegfx::B3DPolygon aCandidate(aHorLine.getB3DPolygon(a));
154 aCandidate.removeDoublePoints();
155
156 if(aCandidate.count())
157 {
158 aNewLineGeometry.append(aCandidate);
159 }
160 }
161
162 if(aNewLineGeometry.count())
163 {
165 aNewLineGeometry, getTransform(), getSdrLFSAttribute().getLine()));
166 aRetval.append(aLines);
167 }
168 }
169 else
170 {
171 // extract line geometry from slices
172 const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
173 const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
174
175 // add horizontal lines
177 aHorLine, getTransform(), getSdrLFSAttribute().getLine()));
178 aRetval.append(aHorLines);
179
180 // add vertical lines
182 aVerLine, getTransform(), getSdrLFSAttribute().getLine()));
183 aRetval.append(aVerLines);
184 }
185 }
186
187 // add shadow
188 if(!getSdrLFSAttribute().getShadow().isDefault()
189 && !aRetval.empty())
190 {
192 aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
193 aRetval.append(aShadow);
194 }
195 }
196
197 return aRetval;
198 }
199
201 {
202 // prepare the polygon. No double points, correct orientations and a correct
203 // outmost polygon are needed
204 // Also important: subdivide here to ensure equal point count for all slices (!)
209
210 // check edge count of first sub-polygon. If different, reSegment polyPolygon. This ensures
211 // that for polyPolygons, the subPolys 1..n only get reSegmented when polygon 0 is different
212 // at all (and not always)
214 const sal_uInt32 nSubEdgeCount(aSubCandidate.isClosed() ? aSubCandidate.count() : (aSubCandidate.count() ? aSubCandidate.count() - 1 : 0));
215
216 if(nSubEdgeCount != getVerticalSegments())
217 {
219 }
220
221 // prepare slices as geometry
223 }
224
226 {
227 // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine()
228 // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
229 if(getPolyPolygon().count() && maSlices.empty())
230 {
231 std::unique_lock aGuard( m_aMutex );
232
233 const_cast< SdrLathePrimitive3D& >(*this).impCreateSlices();
234 }
235
236 return maSlices;
237 }
238
240 const basegfx::B3DHomMatrix& rTransform,
241 const basegfx::B2DVector& rTextureSize,
242 const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
243 const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
244 basegfx::B2DPolyPolygon aPolyPolygon,
245 sal_uInt32 nHorizontalSegments,
246 sal_uInt32 nVerticalSegments,
247 double fDiagonal,
248 double fBackScale,
249 double fRotation,
250 bool bSmoothNormals,
251 bool bSmoothLids,
252 bool bCharacterMode,
253 bool bCloseFront,
254 bool bCloseBack)
255 : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
256 maPolyPolygon(std::move(aPolyPolygon)),
257 mnHorizontalSegments(nHorizontalSegments),
258 mnVerticalSegments(nVerticalSegments),
259 mfDiagonal(fDiagonal),
260 mfBackScale(fBackScale),
261 mfRotation(fRotation),
262 mbSmoothNormals(bSmoothNormals),
263 mbSmoothLids(bSmoothLids),
264 mbCharacterMode(bCharacterMode),
265 mbCloseFront(bCloseFront),
266 mbCloseBack(bCloseBack)
267 {
268 // make sure Rotation is positive
270 {
271 mfRotation = 0.0;
272 }
273
274 // make sure the percentage value getDiagonal() is between 0.0 and 1.0
276 {
277 mfDiagonal = 0.0;
278 }
280 {
281 mfDiagonal = 1.0;
282 }
283
284 // no close front/back when polygon is not closed
285 if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0).isClosed())
286 {
287 mbCloseFront = mbCloseBack = false;
288 }
289
290 // no edge rounding when not closing
291 if(!getCloseFront() && !getCloseBack())
292 {
293 mfDiagonal = 0.0;
294 }
295 }
296
298 {
299 }
300
302 {
303 if(SdrPrimitive3D::operator==(rPrimitive))
304 {
305 const SdrLathePrimitive3D& rCompare = static_cast< const SdrLathePrimitive3D& >(rPrimitive);
306
307 return (getPolyPolygon() == rCompare.getPolyPolygon()
310 && getDiagonal() == rCompare.getDiagonal()
311 && getBackScale() == rCompare.getBackScale()
312 && getRotation() == rCompare.getRotation()
313 && getSmoothNormals() == rCompare.getSmoothNormals()
314 && getSmoothLids() == rCompare.getSmoothLids()
315 && getCharacterMode() == rCompare.getCharacterMode()
316 && getCloseFront() == rCompare.getCloseFront()
317 && getCloseBack() == rCompare.getCloseBack());
318 }
319
320 return false;
321 }
322
324 {
325 // use default from sdrPrimitive3D which uses transformation expanded by line width/2
326 // The parent implementation which uses the ranges of the decomposition would be more
327 // correct, but for historical reasons it is necessary to do the old method: To get
328 // the range of the non-transformed geometry and transform it then. This leads to different
329 // ranges where the new method is more correct, but the need to keep the old behaviour
330 // has priority here.
332 }
333
335 {
336 if(getSdr3DObjectAttribute().getReducedLineGeometry())
337 {
340 && *mpLastRLGViewInformation != rViewInformation))
341 {
342 std::unique_lock aGuard( m_aMutex );
343
344 // conditions of last local decomposition with reduced lines have changed. Remember
345 // new one and clear current decompositiopn
346 SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this);
348 pThat->mpLastRLGViewInformation = rViewInformation;
349 }
350 }
351
352 // no test for buffering needed, call parent
353 return SdrPrimitive3D::get3DDecomposition(rViewInformation);
354 }
355
356 // provide unique ID
358
359} // end of namespace
360
361/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
void translate(double fX, double fY)
void scale(double fX, double fY)
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
bool isClosed() const
sal_uInt32 count() const
sal_uInt32 count() const
void append(const B3DPolygon &rPolygon, sal_uInt32 nCount=1)
B3DPolygon const & getB3DPolygon(sal_uInt32 nIndex) const
sal_uInt32 count() const
void setBuffered3DDecomposition(const Primitive3DContainer &rNew)
const Primitive3DContainer & getBuffered3DDecomposition() const
access methods to maBuffered3DDecomposition.
virtual Primitive3DContainer get3DDecomposition(const geometry::ViewInformation3D &rViewInformation) const override
The getDecomposition default implementation will on demand use create3DDecomposition() if maBuffered3...
void append(const Primitive3DContainer &rSource)
virtual basegfx::B3DRange getB3DRange(const geometry::ViewInformation3D &rViewInformation) const override
get range
SdrLathePrimitive3D(const basegfx::B3DHomMatrix &rTransform, const basegfx::B2DVector &rTextureSize, const attribute::SdrLineFillShadowAttribute3D &rSdrLFSAttribute, const attribute::Sdr3DObjectAttribute &rSdr3DObjectAttribute, basegfx::B2DPolyPolygon aPolyPolygon, sal_uInt32 nHorizontalSegments, sal_uInt32 nVerticalSegments, double fDiagonal, double fBackScale, double fRotation, bool bSmoothNormals, bool bSmoothLids, bool bCharacterMode, bool bCloseFront, bool bCloseBack)
constructor
const basegfx::B2DPolyPolygon & getPolyPolygon() const
data read access
virtual Primitive3DContainer create3DDecomposition(const geometry::ViewInformation3D &rViewInformation) const override
local decomposition.
virtual Primitive3DContainer get3DDecomposition(const geometry::ViewInformation3D &rViewInformation) const override
Overridden to allow for reduced line mode to decide if to buffer decomposition or not.
const Slice3DVector & getSlices() const
get (evtl. create) slices
virtual bool operator==(const BasePrimitive3D &rPrimitive) const override
compare operator
basegfx::B2DPolyPolygon maCorrectedPolyPolygon
geometry helper for slices
std::optional< geometry::ViewInformation3D > mpLastRLGViewInformation
decomposition data when ReducedLineGeometry is used, see get3DDecomposition
const basegfx::B3DHomMatrix & getTransform() const
data read access
basegfx::B3DRange get3DRangeFromSlices(const Slice3DVector &rSlices) const
implementation for primitive3D which will use given Slice3Ds and expand by evtl.
const basegfx::B2DVector & getTextureSize() const
const attribute::Sdr3DObjectAttribute & getSdr3DObjectAttribute() const
const attribute::SdrLineFillShadowAttribute3D & getSdrLFSAttribute() const
int nCount
#define PRIMITIVE3D_ID_SDRLATHEPRIMITIVE3D
uno_Any a
bool lessOrEqual(const T &rfValA, const T &rfValB)
bool equal(T const &rfValA, T const &rfValB)
bool moreOrEqual(const T &rfValA, const T &rfValB)
B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon &rCandidate, sal_uInt32 nSegments)
B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon &rCandidate)
B2DPolygon adaptiveSubdivideByAngle(const B2DPolygon &rCandidate, double fAngleBound)
B2DPolyPolygon correctOrientations(const B2DPolyPolygon &rCandidate)
SdrPrimitive3D class.
void applyNormalsInvertTo3DGeometry(std::vector< basegfx::B3DPolyPolygon > &rFill)
ImplPrimitive3DIDBlock(PolygonHairlinePrimitive3D, PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D) Primitive3DContainer PolygonStrokePrimitive3D
void createLatheSlices(Slice3DVector &rSliceVector, const basegfx::B2DPolyPolygon &rSource, double fBackScale, double fDiagonal, double fRotation, sal_uInt32 nSteps, bool bCharacterMode, bool bCloseFront, bool bCloseBack)
helpers for creation
Primitive3DContainer create3DPolyPolygonFillPrimitives(const std::vector< basegfx::B3DPolyPolygon > &r3DPolyPolygonVector, const basegfx::B3DHomMatrix &rObjectTransform, const basegfx::B2DVector &rTextureSize, const attribute::Sdr3DObjectAttribute &aSdr3DObjectAttribute, const attribute::SdrFillAttribute &rFill, const attribute::FillGradientAttribute &rFillGradient)
basegfx::B3DPolyPolygon extractHorizontalLinesFromSlice(const Slice3DVector &rSliceVector, bool bCloseHorLines)
helpers for geometry extraction
Primitive3DContainer createHiddenGeometryPrimitives3D(const std::vector< basegfx::B3DPolyPolygon > &r3DPolyPolygonVector, const basegfx::B3DHomMatrix &rObjectTransform, const basegfx::B2DVector &rTextureSize, const attribute::Sdr3DObjectAttribute &aSdr3DObjectAttribute)
void applyNormalsKindSphereTo3DGeometry(std::vector< basegfx::B3DPolyPolygon > &rFill, const basegfx::B3DRange &rRange)
basegfx::B3DRange getRangeFrom3DGeometry(std::vector< basegfx::B3DPolyPolygon > &rFill)
void extractPlanesFromSlice(std::vector< basegfx::B3DPolyPolygon > &rFill, const Slice3DVector &rSliceVector, bool bCreateNormals, bool bSmoothNormals, bool bSmoothLids, bool bClosed, double fSmoothNormalsMix, double fSmoothLidsMix, bool bCreateTextureCoordinates, const basegfx::B2DHomMatrix &rTexTransform)
void applyTextureTo3DGeometry(css::drawing::TextureProjectionMode eModeX, css::drawing::TextureProjectionMode eModeY, std::vector< basegfx::B3DPolyPolygon > &rFill, const basegfx::B3DRange &rRange, const basegfx::B2DVector &rTextureSize)
void applyNormalsKindFlatTo3DGeometry(std::vector< basegfx::B3DPolyPolygon > &rFill)
::std::vector< Slice3D > Slice3DVector
typedef for a group of Slice3Ds
Primitive3DContainer createShadowPrimitive3D(const Primitive3DContainer &rSource, const attribute::SdrShadowAttribute &rShadow, bool bShadow3D)
void createReducedOutlines(const geometry::ViewInformation3D &rViewInformation, const basegfx::B3DHomMatrix &rObjectTransform, const basegfx::B3DPolygon &rLoopA, const basegfx::B3DPolygon &rLoopB, basegfx::B3DPolyPolygon &rTarget)
basegfx::B3DPolyPolygon extractVerticalLinesFromSlice(const Slice3DVector &rSliceVector)
Primitive3DContainer create3DPolyPolygonLinePrimitives(const basegfx::B3DPolyPolygon &rUnitPolyPolygon, const basegfx::B3DHomMatrix &rObjectTransform, const attribute::SdrLineAttribute &rLine)
basegfx::B2DPolyPolygon maPolyPolygon