/src/libreoffice/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx
Line | Count | Source |
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 | | #include <sal/config.h> |
21 | | |
22 | | #include <cmath> |
23 | | |
24 | | #include <drawinglayer/primitive3d/sdrextrudeprimitive3d.hxx> |
25 | | #include <basegfx/matrix/b2dhommatrix.hxx> |
26 | | #include <basegfx/polygon/b2dpolygontools.hxx> |
27 | | #include <basegfx/polygon/b3dpolygon.hxx> |
28 | | #include <primitive3d/sdrdecompositiontools3d.hxx> |
29 | | #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> |
30 | | #include <drawinglayer/geometry/viewinformation3d.hxx> |
31 | | #include <drawinglayer/attribute/sdrfillattribute.hxx> |
32 | | #include <drawinglayer/attribute/sdrlineattribute.hxx> |
33 | | #include <drawinglayer/attribute/sdrshadowattribute.hxx> |
34 | | #include <utility> |
35 | | |
36 | | |
37 | | using namespace com::sun::star; |
38 | | |
39 | | |
40 | | namespace drawinglayer::primitive3d |
41 | | { |
42 | | Primitive3DContainer SdrExtrudePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const |
43 | 0 | { |
44 | 0 | Primitive3DContainer aRetval; |
45 | | |
46 | | // get slices |
47 | 0 | const Slice3DVector& rSliceVector = getSlices(); |
48 | |
|
49 | 0 | if(!rSliceVector.empty()) |
50 | 0 | { |
51 | 0 | sal_uInt32 a; |
52 | | |
53 | | // decide what to create |
54 | 0 | const css::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind()); |
55 | 0 | const bool bCreateNormals(css::drawing::NormalsKind_SPECIFIC == eNormalsKind); |
56 | 0 | const bool bCreateTextureCoordinatesX(css::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); |
57 | 0 | const bool bCreateTextureCoordinatesY(css::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); |
58 | 0 | basegfx::B2DHomMatrix aTexTransform; |
59 | |
|
60 | 0 | if(!getSdrLFSAttribute().getFill().isDefault() && (bCreateTextureCoordinatesX || bCreateTextureCoordinatesY)) |
61 | 0 | { |
62 | 0 | const basegfx::B2DPolygon aFirstPolygon(maCorrectedPolyPolygon.getB2DPolygon(0)); |
63 | 0 | const double fFrontLength(basegfx::utils::getLength(aFirstPolygon)); |
64 | 0 | const double fFrontArea(basegfx::utils::getArea(aFirstPolygon)); |
65 | 0 | const double fSqrtFrontArea(sqrt(fFrontArea)); |
66 | 0 | double fRelativeTextureWidth = basegfx::fTools::equalZero(fSqrtFrontArea) ? 1.0 : fFrontLength / fSqrtFrontArea; |
67 | 0 | fRelativeTextureWidth = std::trunc(fRelativeTextureWidth - 0.5); |
68 | |
|
69 | 0 | if(fRelativeTextureWidth < 1.0) |
70 | 0 | { |
71 | 0 | fRelativeTextureWidth = 1.0; |
72 | 0 | } |
73 | |
|
74 | 0 | aTexTransform.translate(-0.5, -0.5); |
75 | 0 | aTexTransform.scale(-1.0, -1.0); |
76 | 0 | aTexTransform.translate(0.5, 0.5); |
77 | 0 | aTexTransform.scale(fRelativeTextureWidth, 1.0); |
78 | 0 | } |
79 | | |
80 | | // create geometry |
81 | 0 | std::vector< basegfx::B3DPolyPolygon > aFill; |
82 | 0 | extractPlanesFromSlice(aFill, rSliceVector, |
83 | 0 | bCreateNormals, getSmoothNormals(), getSmoothLids(), false, |
84 | 0 | 0.5, 0.6, bCreateTextureCoordinatesX || bCreateTextureCoordinatesY, aTexTransform); |
85 | | |
86 | | // get full range |
87 | 0 | const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill)); |
88 | | |
89 | | // normal creation |
90 | 0 | if(!getSdrLFSAttribute().getFill().isDefault()) |
91 | 0 | { |
92 | 0 | if(css::drawing::NormalsKind_SPHERE == eNormalsKind) |
93 | 0 | { |
94 | 0 | applyNormalsKindSphereTo3DGeometry(aFill, aRange); |
95 | 0 | } |
96 | 0 | else if(css::drawing::NormalsKind_FLAT == eNormalsKind) |
97 | 0 | { |
98 | 0 | applyNormalsKindFlatTo3DGeometry(aFill); |
99 | 0 | } |
100 | |
|
101 | 0 | if(getSdr3DObjectAttribute().getNormalsInvert()) |
102 | 0 | { |
103 | 0 | applyNormalsInvertTo3DGeometry(aFill); |
104 | 0 | } |
105 | 0 | } |
106 | | |
107 | | // texture coordinates |
108 | 0 | if(!getSdrLFSAttribute().getFill().isDefault()) |
109 | 0 | { |
110 | 0 | applyTextureTo3DGeometry( |
111 | 0 | getSdr3DObjectAttribute().getTextureProjectionX(), |
112 | 0 | getSdr3DObjectAttribute().getTextureProjectionY(), |
113 | 0 | aFill, |
114 | 0 | aRange, |
115 | 0 | getTextureSize()); |
116 | 0 | } |
117 | |
|
118 | 0 | if(!getSdrLFSAttribute().getFill().isDefault()) |
119 | 0 | { |
120 | | // add fill |
121 | 0 | aRetval = create3DPolyPolygonFillPrimitives( |
122 | 0 | aFill, |
123 | 0 | getTransform(), |
124 | 0 | getTextureSize(), |
125 | 0 | getSdr3DObjectAttribute(), |
126 | 0 | getSdrLFSAttribute().getFill(), |
127 | 0 | getSdrLFSAttribute().getFillFloatTransGradient()); |
128 | 0 | } |
129 | 0 | else |
130 | 0 | { |
131 | | // create simplified 3d hit test geometry |
132 | 0 | aRetval = createHiddenGeometryPrimitives3D( |
133 | 0 | aFill, |
134 | 0 | getTransform(), |
135 | 0 | getTextureSize(), |
136 | 0 | getSdr3DObjectAttribute()); |
137 | 0 | } |
138 | | |
139 | | // add line |
140 | 0 | if(!getSdrLFSAttribute().getLine().isDefault()) |
141 | 0 | { |
142 | 0 | if(getSdr3DObjectAttribute().getReducedLineGeometry()) |
143 | 0 | { |
144 | | // create geometric outlines with reduced line geometry for chart. |
145 | 0 | const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector)); |
146 | 0 | const sal_uInt32 nCount(aVerLine.count()); |
147 | 0 | basegfx::B3DPolyPolygon aReducedLoops; |
148 | 0 | basegfx::B3DPolyPolygon aNewLineGeometry; |
149 | | |
150 | | // sort out doubles (front and back planes when no edge rounding is done). Since |
151 | | // this is a line geometry merged from PolyPolygons, loop over all Polygons |
152 | 0 | for(a = 0; a < nCount; a++) |
153 | 0 | { |
154 | 0 | const sal_uInt32 nReducedCount(aReducedLoops.count()); |
155 | 0 | const basegfx::B3DPolygon& aCandidate(aVerLine.getB3DPolygon(a)); |
156 | 0 | bool bAdd(true); |
157 | |
|
158 | 0 | if(nReducedCount) |
159 | 0 | { |
160 | 0 | for(sal_uInt32 b(0); bAdd && b < nReducedCount; b++) |
161 | 0 | { |
162 | 0 | if(aCandidate == aReducedLoops.getB3DPolygon(b)) |
163 | 0 | { |
164 | 0 | bAdd = false; |
165 | 0 | } |
166 | 0 | } |
167 | 0 | } |
168 | |
|
169 | 0 | if(bAdd) |
170 | 0 | { |
171 | 0 | aReducedLoops.append(aCandidate); |
172 | 0 | } |
173 | 0 | } |
174 | | |
175 | | // from here work with reduced loops and reduced count without changing them |
176 | 0 | const sal_uInt32 nReducedCount(aReducedLoops.count()); |
177 | |
|
178 | 0 | if(nReducedCount > 1) |
179 | 0 | { |
180 | 0 | for(sal_uInt32 b(1); b < nReducedCount; b++) |
181 | 0 | { |
182 | | // get loop pair |
183 | 0 | const basegfx::B3DPolygon& aCandA(aReducedLoops.getB3DPolygon(b - 1)); |
184 | 0 | const basegfx::B3DPolygon& aCandB(aReducedLoops.getB3DPolygon(b)); |
185 | | |
186 | | // for each loop pair create the connection edges |
187 | 0 | createReducedOutlines( |
188 | 0 | rViewInformation, |
189 | 0 | getTransform(), |
190 | 0 | aCandA, |
191 | 0 | aCandB, |
192 | 0 | aNewLineGeometry); |
193 | 0 | } |
194 | 0 | } |
195 | | |
196 | | // add reduced loops themselves |
197 | 0 | aNewLineGeometry.append(aReducedLoops); |
198 | | |
199 | | // to create vertical edges at non-C1/C2 steady loops, use maCorrectedPolyPolygon |
200 | | // directly since the 3D Polygons do not support this. |
201 | | // |
202 | | // Unfortunately there is no bezier polygon provided by the chart module; one reason is |
203 | | // that the API for extrude wants a 3D polygon geometry (for historical reasons, i guess) |
204 | | // and those have no beziers. Another reason is that he chart module uses self-created |
205 | | // stuff to create the 2D geometry (in ShapeFactory::createPieSegment), but this geometry |
206 | | // does not contain bezier infos, either. The only way which is possible for now is to 'detect' |
207 | | // candidates for vertical edges of pie segments by looking for the angles in the polygon. |
208 | | // |
209 | | // This is all not very well designed ATM. Ideally, the ReducedLineGeometry is responsible |
210 | | // for creating the outer geometry edges (createReducedOutlines), but for special edges |
211 | | // like the vertical ones for pie center and both start/end, the incarnation with the |
212 | | // knowledge about that it needs to create those and IS a pie segment -> in this case, |
213 | | // the chart itself. |
214 | 0 | const sal_uInt32 nPolyCount(maCorrectedPolyPolygon.count()); |
215 | |
|
216 | 0 | for(sal_uInt32 c(0); c < nPolyCount; c++) |
217 | 0 | { |
218 | 0 | const basegfx::B2DPolygon aCandidate(maCorrectedPolyPolygon.getB2DPolygon(c)); |
219 | 0 | const sal_uInt32 nPointCount(aCandidate.count()); |
220 | |
|
221 | 0 | if(nPointCount > 2) |
222 | 0 | { |
223 | 0 | sal_uInt32 nIndexA(nPointCount); |
224 | 0 | sal_uInt32 nIndexB(nPointCount); |
225 | 0 | sal_uInt32 nIndexC(nPointCount); |
226 | |
|
227 | 0 | for(sal_uInt32 d(0); d < nPointCount; d++) |
228 | 0 | { |
229 | 0 | const sal_uInt32 nPrevInd((d + nPointCount - 1) % nPointCount); |
230 | 0 | const sal_uInt32 nNextInd((d + 1) % nPointCount); |
231 | 0 | const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(d)); |
232 | 0 | const basegfx::B2DVector aPrev(aCandidate.getB2DPoint(nPrevInd) - aPoint); |
233 | 0 | const basegfx::B2DVector aNext(aCandidate.getB2DPoint(nNextInd) - aPoint); |
234 | 0 | const double fAngle(aPrev.angle(aNext)); |
235 | | |
236 | | // take each angle which deviates more than 10% from going straight as |
237 | | // special edge. This will detect the two outer edges of pie segments, |
238 | | // but not always the center one (think about a near 180 degree pie) |
239 | 0 | if(M_PI - fabs(fAngle) > M_PI * 0.1) |
240 | 0 | { |
241 | 0 | if(nPointCount == nIndexA) |
242 | 0 | { |
243 | 0 | nIndexA = d; |
244 | 0 | } |
245 | 0 | else if(nPointCount == nIndexB) |
246 | 0 | { |
247 | 0 | nIndexB = d; |
248 | 0 | } |
249 | 0 | else if(nPointCount == nIndexC) |
250 | 0 | { |
251 | 0 | nIndexC = d; |
252 | 0 | d = nPointCount; |
253 | 0 | } |
254 | 0 | } |
255 | 0 | } |
256 | |
|
257 | 0 | const bool bIndexAUsed(nIndexA != nPointCount); |
258 | 0 | const bool bIndexBUsed(nIndexB != nPointCount); |
259 | 0 | bool bIndexCUsed(nIndexC != nPointCount); |
260 | |
|
261 | 0 | if(bIndexCUsed) |
262 | 0 | { |
263 | | // already three special edges found, so the center one was already detected |
264 | | // and does not need to be searched |
265 | 0 | } |
266 | 0 | else if(bIndexAUsed && bIndexBUsed) |
267 | 0 | { |
268 | | // outer edges detected (they are approx. 90 degrees), but center one not. |
269 | | // Look with the knowledge that it's in-between the two found ones |
270 | 0 | if(((nIndexA + 2) % nPointCount) == nIndexB) |
271 | 0 | { |
272 | 0 | nIndexC = (nIndexA + 1) % nPointCount; |
273 | 0 | } |
274 | 0 | else if(((nIndexA + nPointCount - 2) % nPointCount) == nIndexB) |
275 | 0 | { |
276 | 0 | nIndexC = (nIndexA + nPointCount - 1) % nPointCount; |
277 | 0 | } |
278 | |
|
279 | 0 | bIndexCUsed = (nIndexC != nPointCount); |
280 | 0 | } |
281 | |
|
282 | 0 | if(bIndexAUsed) |
283 | 0 | { |
284 | 0 | const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexA)); |
285 | 0 | const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0); |
286 | 0 | const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth()); |
287 | 0 | basegfx::B3DPolygon aToBeAdded; |
288 | |
|
289 | 0 | aToBeAdded.append(aStart); |
290 | 0 | aToBeAdded.append(aEnd); |
291 | 0 | aNewLineGeometry.append(aToBeAdded); |
292 | 0 | } |
293 | |
|
294 | 0 | if(bIndexBUsed) |
295 | 0 | { |
296 | 0 | const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexB)); |
297 | 0 | const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0); |
298 | 0 | const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth()); |
299 | 0 | basegfx::B3DPolygon aToBeAdded; |
300 | |
|
301 | 0 | aToBeAdded.append(aStart); |
302 | 0 | aToBeAdded.append(aEnd); |
303 | 0 | aNewLineGeometry.append(aToBeAdded); |
304 | 0 | } |
305 | |
|
306 | 0 | if(bIndexCUsed) |
307 | 0 | { |
308 | 0 | const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexC)); |
309 | 0 | const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0); |
310 | 0 | const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth()); |
311 | 0 | basegfx::B3DPolygon aToBeAdded; |
312 | |
|
313 | 0 | aToBeAdded.append(aStart); |
314 | 0 | aToBeAdded.append(aEnd); |
315 | 0 | aNewLineGeometry.append(aToBeAdded); |
316 | 0 | } |
317 | 0 | } |
318 | 0 | } |
319 | | |
320 | | // append loops themselves |
321 | 0 | aNewLineGeometry.append(aReducedLoops); |
322 | |
|
323 | 0 | if(aNewLineGeometry.count()) |
324 | 0 | { |
325 | 0 | const Primitive3DContainer aLines(create3DPolyPolygonLinePrimitives( |
326 | 0 | aNewLineGeometry, getTransform(), getSdrLFSAttribute().getLine())); |
327 | 0 | aRetval.append(aLines); |
328 | 0 | } |
329 | 0 | } |
330 | 0 | else |
331 | 0 | { |
332 | | // extract line geometry from slices |
333 | 0 | const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, false)); |
334 | 0 | const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector)); |
335 | | |
336 | | // add horizontal lines |
337 | 0 | const Primitive3DContainer aHorLines(create3DPolyPolygonLinePrimitives( |
338 | 0 | aHorLine, getTransform(), getSdrLFSAttribute().getLine())); |
339 | 0 | aRetval.append(aHorLines); |
340 | | |
341 | | // add vertical lines |
342 | 0 | const Primitive3DContainer aVerLines(create3DPolyPolygonLinePrimitives( |
343 | 0 | aVerLine, getTransform(), getSdrLFSAttribute().getLine())); |
344 | 0 | aRetval.append(aVerLines); |
345 | 0 | } |
346 | 0 | } |
347 | | |
348 | | // add shadow |
349 | 0 | if(!getSdrLFSAttribute().getShadow().isDefault() && !aRetval.empty()) |
350 | 0 | { |
351 | 0 | const Primitive3DContainer aShadow(createShadowPrimitive3D( |
352 | 0 | aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D())); |
353 | 0 | aRetval.append(aShadow); |
354 | 0 | } |
355 | 0 | } |
356 | |
|
357 | 0 | return aRetval; |
358 | 0 | } |
359 | | |
360 | | void SdrExtrudePrimitive3D::impCreateSlices() |
361 | 0 | { |
362 | | // prepare the polygon. No double points, correct orientations and a correct |
363 | | // outmost polygon are needed |
364 | | // Also important: subdivide here to ensure equal point count for all slices (!) |
365 | 0 | maCorrectedPolyPolygon = basegfx::utils::adaptiveSubdivideByAngle(getPolyPolygon()); |
366 | 0 | maCorrectedPolyPolygon.removeDoublePoints(); |
367 | 0 | maCorrectedPolyPolygon = basegfx::utils::correctOrientations(maCorrectedPolyPolygon); |
368 | 0 | maCorrectedPolyPolygon = basegfx::utils::correctOutmostPolygon(maCorrectedPolyPolygon); |
369 | | |
370 | | // prepare slices as geometry |
371 | 0 | createExtrudeSlices(maSlices, maCorrectedPolyPolygon, getBackScale(), getDiagonal(), getDepth(), getCharacterMode(), getCloseFront(), getCloseBack()); |
372 | 0 | } |
373 | | |
374 | | const Slice3DVector& SdrExtrudePrimitive3D::getSlices() const |
375 | 0 | { |
376 | | // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine() |
377 | | // again when no longer geometry is needed for non-visible 3D objects as it is now for chart |
378 | 0 | if(getPolyPolygon().count() && maSlices.empty()) |
379 | 0 | { |
380 | 0 | std::unique_lock aGuard( m_aMutex ); |
381 | |
|
382 | 0 | const_cast< SdrExtrudePrimitive3D& >(*this).impCreateSlices(); |
383 | 0 | } |
384 | |
|
385 | 0 | return maSlices; |
386 | 0 | } |
387 | | |
388 | | SdrExtrudePrimitive3D::SdrExtrudePrimitive3D( |
389 | | const basegfx::B3DHomMatrix& rTransform, |
390 | | const basegfx::B2DVector& rTextureSize, |
391 | | const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute, |
392 | | const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute, |
393 | | basegfx::B2DPolyPolygon aPolyPolygon, |
394 | | double fDepth, |
395 | | double fDiagonal, |
396 | | double fBackScale, |
397 | | bool bSmoothNormals, |
398 | | bool bSmoothLids, |
399 | | bool bCharacterMode, |
400 | | bool bCloseFront, |
401 | | bool bCloseBack) |
402 | 0 | : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute), |
403 | 0 | maPolyPolygon(std::move(aPolyPolygon)), |
404 | 0 | mfDepth(fDepth), |
405 | 0 | mfDiagonal(fDiagonal), |
406 | 0 | mfBackScale(fBackScale), |
407 | 0 | mbSmoothNormals(bSmoothNormals), |
408 | 0 | mbSmoothLids(bSmoothLids), |
409 | 0 | mbCharacterMode(bCharacterMode), |
410 | 0 | mbCloseFront(bCloseFront), |
411 | 0 | mbCloseBack(bCloseBack) |
412 | 0 | { |
413 | | // make sure depth is positive |
414 | 0 | if(getDepth() <= 0.0) |
415 | 0 | { |
416 | 0 | mfDepth = 0.0; |
417 | 0 | } |
418 | | |
419 | | // make sure the percentage value getDiagonal() is between 0.0 and 1.0 |
420 | 0 | if(getDiagonal() <= 0.0) |
421 | 0 | { |
422 | 0 | mfDiagonal = 0.0; |
423 | 0 | } |
424 | 0 | else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0)) |
425 | 0 | { |
426 | 0 | mfDiagonal = 1.0; |
427 | 0 | } |
428 | | |
429 | | // no close front/back when polygon is not closed |
430 | 0 | if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0).isClosed()) |
431 | 0 | { |
432 | 0 | mbCloseFront = mbCloseBack = false; |
433 | 0 | } |
434 | | |
435 | | // no edge rounding when not closing |
436 | 0 | if(!getCloseFront() && !getCloseBack()) |
437 | 0 | { |
438 | 0 | mfDiagonal = 0.0; |
439 | 0 | } |
440 | 0 | } Unexecuted instantiation: drawinglayer::primitive3d::SdrExtrudePrimitive3D::SdrExtrudePrimitive3D(basegfx::B3DHomMatrix const&, basegfx::B2DVector const&, drawinglayer::attribute::SdrLineFillShadowAttribute3D const&, drawinglayer::attribute::Sdr3DObjectAttribute const&, basegfx::B2DPolyPolygon, double, double, double, bool, bool, bool, bool, bool) Unexecuted instantiation: drawinglayer::primitive3d::SdrExtrudePrimitive3D::SdrExtrudePrimitive3D(basegfx::B3DHomMatrix const&, basegfx::B2DVector const&, drawinglayer::attribute::SdrLineFillShadowAttribute3D const&, drawinglayer::attribute::Sdr3DObjectAttribute const&, basegfx::B2DPolyPolygon, double, double, double, bool, bool, bool, bool, bool) |
441 | | |
442 | | SdrExtrudePrimitive3D::~SdrExtrudePrimitive3D() |
443 | 0 | { |
444 | 0 | } |
445 | | |
446 | | bool SdrExtrudePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const |
447 | 0 | { |
448 | 0 | if(SdrPrimitive3D::operator==(rPrimitive)) |
449 | 0 | { |
450 | 0 | const SdrExtrudePrimitive3D& rCompare = static_cast< const SdrExtrudePrimitive3D& >(rPrimitive); |
451 | |
|
452 | 0 | return (getPolyPolygon() == rCompare.getPolyPolygon() |
453 | 0 | && getDepth() == rCompare.getDepth() |
454 | 0 | && getDiagonal() == rCompare.getDiagonal() |
455 | 0 | && getBackScale() == rCompare.getBackScale() |
456 | 0 | && getSmoothNormals() == rCompare.getSmoothNormals() |
457 | 0 | && getSmoothLids() == rCompare.getSmoothLids() |
458 | 0 | && getCharacterMode() == rCompare.getCharacterMode() |
459 | 0 | && getCloseFront() == rCompare.getCloseFront() |
460 | 0 | && getCloseBack() == rCompare.getCloseBack()); |
461 | 0 | } |
462 | | |
463 | 0 | return false; |
464 | 0 | } |
465 | | |
466 | | basegfx::B3DRange SdrExtrudePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const |
467 | 0 | { |
468 | | // use default from sdrPrimitive3D which uses transformation expanded by line width/2 |
469 | | // The parent implementation which uses the ranges of the decomposition would be more |
470 | | // correct, but for historical reasons it is necessary to do the old method: To get |
471 | | // the range of the non-transformed geometry and transform it then. This leads to different |
472 | | // ranges where the new method is more correct, but the need to keep the old behaviour |
473 | | // has priority here. |
474 | 0 | return get3DRangeFromSlices(getSlices()); |
475 | 0 | } |
476 | | |
477 | | Primitive3DContainer SdrExtrudePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const |
478 | 0 | { |
479 | 0 | if(getSdr3DObjectAttribute().getReducedLineGeometry()) |
480 | 0 | { |
481 | 0 | if(!mpLastRLGViewInformation || |
482 | 0 | (!getBuffered3DDecomposition().empty() |
483 | 0 | && *mpLastRLGViewInformation != rViewInformation)) |
484 | 0 | { |
485 | 0 | std::unique_lock aGuard( m_aMutex ); |
486 | | |
487 | | // conditions of last local decomposition with reduced lines have changed. Remember |
488 | | // new one and clear current decompositiopn |
489 | 0 | SdrExtrudePrimitive3D* pThat = const_cast< SdrExtrudePrimitive3D* >(this); |
490 | 0 | pThat->setBuffered3DDecomposition(Primitive3DContainer()); |
491 | 0 | pThat->mpLastRLGViewInformation = rViewInformation; |
492 | 0 | } |
493 | 0 | } |
494 | | |
495 | | // no test for buffering needed, call parent |
496 | 0 | return SdrPrimitive3D::get3DDecomposition(rViewInformation); |
497 | 0 | } |
498 | | |
499 | | // provide unique ID |
500 | | ImplPrimitive3DIDBlock(SdrExtrudePrimitive3D, PRIMITIVE3D_ID_SDREXTRUDEPRIMITIVE3D) |
501 | | |
502 | | } // end of namespace |
503 | | |
504 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |