Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <drawinglayer/primitive3d/sdrextrudelathetools3d.hxx>
30 : : #include <basegfx/polygon/b2dpolypolygon.hxx>
31 : : #include <basegfx/range/b2drange.hxx>
32 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
33 : : #include <basegfx/matrix/b2dhommatrix.hxx>
34 : : #include <basegfx/point/b3dpoint.hxx>
35 : : #include <basegfx/polygon/b3dpolygon.hxx>
36 : : #include <basegfx/polygon/b3dpolygontools.hxx>
37 : : #include <basegfx/polygon/b3dpolypolygontools.hxx>
38 : : #include <basegfx/range/b3drange.hxx>
39 : : #include <basegfx/matrix/b3dhommatrix.hxx>
40 : : #include <basegfx/polygon/b2dpolygontools.hxx>
41 : : #include <drawinglayer/geometry/viewinformation3d.hxx>
42 : : #include <numeric>
43 : :
44 : : //////////////////////////////////////////////////////////////////////////////
45 : : // decompositon helpers for extrude/lathe (rotation) objects
46 : :
47 : : namespace
48 : : {
49 : : //////////////////////////////////////////////////////////////////////////////
50 : : // common helpers
51 : :
52 : 0 : basegfx::B2DPolyPolygon impScalePolyPolygonOnCenter(
53 : : const basegfx::B2DPolyPolygon& rSource,
54 : : double fScale)
55 : : {
56 : 0 : basegfx::B2DPolyPolygon aRetval(rSource);
57 : :
58 [ # # ]: 0 : if(!basegfx::fTools::equalZero(fScale))
59 : : {
60 [ # # ]: 0 : const basegfx::B2DRange aRange(basegfx::tools::getRange(rSource));
61 [ # # ]: 0 : const basegfx::B2DPoint aCenter(aRange.getCenter());
62 [ # # ]: 0 : basegfx::B2DHomMatrix aTrans;
63 : :
64 [ # # ]: 0 : aTrans.translate(-aCenter.getX(), -aCenter.getY());
65 [ # # ]: 0 : aTrans.scale(fScale, fScale);
66 [ # # ]: 0 : aTrans.translate(aCenter.getX(), aCenter.getY());
67 [ # # ][ # # ]: 0 : aRetval.transform(aTrans);
68 : : }
69 : :
70 : 0 : return aRetval;
71 : : }
72 : :
73 : 6002 : void impGetOuterPolyPolygon(
74 : : basegfx::B2DPolyPolygon& rPolygon,
75 : : basegfx::B2DPolyPolygon& rOuterPolyPolygon,
76 : : double fOffset,
77 : : bool bCharacterMode)
78 : : {
79 : 6002 : rOuterPolyPolygon = rPolygon;
80 : :
81 [ + + ]: 6002 : if(basegfx::fTools::more(fOffset, 0.0))
82 : : {
83 [ + - ]: 3002 : if(bCharacterMode)
84 : : {
85 : : // grow the outside polygon and scale all polygons to original size. This is done
86 : : // to avoid a shrink which potentially would lead to self-intersections, but changes
87 : : // the original polygon -> not a precision step, so e.g. not usable for charts
88 [ + - ]: 3002 : const basegfx::B2DRange aRange(basegfx::tools::getRange(rPolygon));
89 [ + - ][ + - ]: 3002 : rPolygon = basegfx::tools::growInNormalDirection(rPolygon, fOffset);
[ + - ]
90 [ + - ]: 3002 : const basegfx::B2DRange aGrownRange(basegfx::tools::getRange(rPolygon));
91 [ + - ][ - + ]: 3002 : const double fScaleX(basegfx::fTools::equalZero(aGrownRange.getWidth()) ? 1.0 : aRange.getWidth() / aGrownRange.getWidth());
[ + - ][ + - ]
92 [ + - ][ - + ]: 3002 : const double fScaleY(basegfx::fTools::equalZero(aGrownRange.getHeight())? 1.0 : aRange.getHeight() / aGrownRange.getHeight());
[ + - ][ + - ]
93 [ + - ]: 3002 : basegfx::B2DHomMatrix aScaleTrans;
94 : :
95 [ + - ][ + - ]: 3002 : aScaleTrans.translate(-aGrownRange.getMinX(), -aGrownRange.getMinY());
[ + - ]
96 [ + - ]: 3002 : aScaleTrans.scale(fScaleX, fScaleY);
97 [ + - ][ + - ]: 3002 : aScaleTrans.translate(aRange.getMinX(), aRange.getMinY());
[ + - ]
98 [ + - ]: 3002 : rPolygon.transform(aScaleTrans);
99 [ + - ][ + - ]: 3002 : rOuterPolyPolygon.transform(aScaleTrans);
100 : : }
101 : : else
102 : : {
103 : : // use more precision, shrink the outer polygons. Since this may lead to self-intersections,
104 : : // some kind of correction should be applied here after that step
105 [ # # ]: 0 : rOuterPolyPolygon = basegfx::tools::growInNormalDirection(rPolygon, -fOffset);
106 : 0 : basegfx::tools::correctGrowShrinkPolygonPair(rPolygon, rOuterPolyPolygon);
107 : : }
108 : : }
109 : 6002 : }
110 : :
111 : 24 : void impAddInBetweenFill(
112 : : basegfx::B3DPolyPolygon& rTarget,
113 : : const basegfx::B3DPolyPolygon& rPolA,
114 : : const basegfx::B3DPolyPolygon& rPolB,
115 : : double fTexVerStart,
116 : : double fTexVerStop,
117 : : bool bCreateNormals,
118 : : bool bCreateTextureCoordinates)
119 : : {
120 : : OSL_ENSURE(rPolA.count() == rPolB.count(), "impAddInBetweenFill: unequally sized polygons (!)");
121 : 24 : const sal_uInt32 nPolygonCount(rPolA.count());
122 : :
123 [ + + ]: 48 : for(sal_uInt32 a(0L); a < nPolygonCount; a++)
124 : : {
125 [ + - ]: 24 : const basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
126 [ + - ]: 24 : const basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
127 : : OSL_ENSURE(aSubA.count() == aSubB.count(), "impAddInBetweenFill: unequally sized polygons (!)");
128 [ + - ]: 24 : const sal_uInt32 nPointCount(aSubA.count());
129 : :
130 [ + - ]: 24 : if(nPointCount)
131 : : {
132 [ + - ][ + - ]: 24 : const sal_uInt32 nEdgeCount(aSubA.isClosed() ? nPointCount : nPointCount - 1L);
133 : 24 : double fTexHorMultiplicatorA(0.0), fTexHorMultiplicatorB(0.0);
134 : 24 : double fPolygonPosA(0.0), fPolygonPosB(0.0);
135 : :
136 [ - + ]: 24 : if(bCreateTextureCoordinates)
137 : : {
138 [ # # ]: 0 : const double fPolygonLengthA(basegfx::tools::getLength(aSubA));
139 [ # # ]: 0 : fTexHorMultiplicatorA = basegfx::fTools::equalZero(fPolygonLengthA) ? 1.0 : 1.0 / fPolygonLengthA;
140 : :
141 [ # # ]: 0 : const double fPolygonLengthB(basegfx::tools::getLength(aSubB));
142 [ # # ]: 0 : fTexHorMultiplicatorB = basegfx::fTools::equalZero(fPolygonLengthB) ? 1.0 : 1.0 / fPolygonLengthB;
143 : : }
144 : :
145 [ + + ]: 120 : for(sal_uInt32 b(0L); b < nEdgeCount; b++)
146 : : {
147 : 96 : const sal_uInt32 nIndexA(b);
148 : 96 : const sal_uInt32 nIndexB((b + 1L) % nPointCount);
149 : :
150 [ + - ]: 96 : const basegfx::B3DPoint aStartA(aSubA.getB3DPoint(nIndexA));
151 [ + - ]: 96 : const basegfx::B3DPoint aEndA(aSubA.getB3DPoint(nIndexB));
152 [ + - ]: 96 : const basegfx::B3DPoint aStartB(aSubB.getB3DPoint(nIndexA));
153 [ + - ]: 96 : const basegfx::B3DPoint aEndB(aSubB.getB3DPoint(nIndexB));
154 : :
155 [ + - ]: 96 : basegfx::B3DPolygon aNew;
156 [ + - ]: 96 : aNew.setClosed(true);
157 : :
158 [ + - ]: 96 : aNew.append(aStartA);
159 [ + - ]: 96 : aNew.append(aStartB);
160 [ + - ]: 96 : aNew.append(aEndB);
161 [ + - ]: 96 : aNew.append(aEndA);
162 : :
163 [ + - ]: 96 : if(bCreateNormals)
164 : : {
165 [ + - ][ + - ]: 96 : aNew.setNormal(0L, aSubA.getNormal(nIndexA));
166 [ + - ][ + - ]: 96 : aNew.setNormal(1L, aSubB.getNormal(nIndexA));
167 [ + - ][ + - ]: 96 : aNew.setNormal(2L, aSubB.getNormal(nIndexB));
168 [ + - ][ + - ]: 96 : aNew.setNormal(3L, aSubA.getNormal(nIndexB));
169 : : }
170 : :
171 [ - + ]: 96 : if(bCreateTextureCoordinates)
172 : : {
173 : 0 : const double fRelTexAL(fPolygonPosA * fTexHorMultiplicatorA);
174 [ # # ]: 0 : const double fEdgeLengthA(basegfx::B3DVector(aEndA - aStartA).getLength());
175 : 0 : fPolygonPosA += fEdgeLengthA;
176 : 0 : const double fRelTexAR(fPolygonPosA * fTexHorMultiplicatorA);
177 : :
178 : 0 : const double fRelTexBL(fPolygonPosB * fTexHorMultiplicatorB);
179 [ # # ]: 0 : const double fEdgeLengthB(basegfx::B3DVector(aEndB - aStartB).getLength());
180 : 0 : fPolygonPosB += fEdgeLengthB;
181 : 0 : const double fRelTexBR(fPolygonPosB * fTexHorMultiplicatorB);
182 : :
183 [ # # ]: 0 : aNew.setTextureCoordinate(0L, basegfx::B2DPoint(fRelTexAL, fTexVerStart));
184 [ # # ]: 0 : aNew.setTextureCoordinate(1L, basegfx::B2DPoint(fRelTexBL, fTexVerStop));
185 [ # # ]: 0 : aNew.setTextureCoordinate(2L, basegfx::B2DPoint(fRelTexBR, fTexVerStop));
186 [ # # ]: 0 : aNew.setTextureCoordinate(3L, basegfx::B2DPoint(fRelTexAR, fTexVerStart));
187 : : }
188 : :
189 [ + - ]: 96 : rTarget.append(aNew);
190 [ + - ]: 96 : }
191 : : }
192 [ + - ][ + - ]: 24 : }
193 : 24 : }
194 : :
195 : 48 : void impSetNormal(
196 : : basegfx::B3DPolyPolygon& rCandidate,
197 : : const basegfx::B3DVector& rNormal)
198 : : {
199 [ + + ]: 96 : for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
200 : : {
201 [ + - ]: 48 : basegfx::B3DPolygon aSub(rCandidate.getB3DPolygon(a));
202 : :
203 [ + - ][ + + ]: 240 : for(sal_uInt32 b(0L); b < aSub.count(); b++)
204 : : {
205 [ + - ]: 192 : aSub.setNormal(b, rNormal);
206 : : }
207 : :
208 [ + - ]: 48 : rCandidate.setB3DPolygon(a, aSub);
209 [ + - ]: 48 : }
210 : 48 : }
211 : :
212 : 24 : void impCreateInBetweenNormals(
213 : : basegfx::B3DPolyPolygon& rPolA,
214 : : basegfx::B3DPolyPolygon& rPolB,
215 : : bool bSmoothHorizontalNormals)
216 : : {
217 : : OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
218 : :
219 [ + + ]: 48 : for(sal_uInt32 a(0L); a < rPolA.count(); a++)
220 : : {
221 [ + - ]: 24 : basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
222 [ + - ]: 24 : basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
223 : : OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
224 [ + - ]: 24 : const sal_uInt32 nPointCount(aSubA.count());
225 : :
226 [ + - ]: 24 : if(nPointCount)
227 : : {
228 [ + - ]: 24 : basegfx::B3DPoint aPrevA(aSubA.getB3DPoint(nPointCount - 1L));
229 [ + - ]: 24 : basegfx::B3DPoint aCurrA(aSubA.getB3DPoint(0L));
230 [ + - ]: 24 : const bool bClosed(aSubA.isClosed());
231 : :
232 [ + + ]: 120 : for(sal_uInt32 b(0L); b < nPointCount; b++)
233 : : {
234 : 96 : const sal_uInt32 nIndNext((b + 1L) % nPointCount);
235 [ + - ]: 96 : const basegfx::B3DPoint aNextA(aSubA.getB3DPoint(nIndNext));
236 [ + - ]: 96 : const basegfx::B3DPoint aCurrB(aSubB.getB3DPoint(b));
237 : :
238 : : // vector to back
239 : 96 : basegfx::B3DVector aDepth(aCurrB - aCurrA);
240 [ + - ]: 96 : aDepth.normalize();
241 : :
242 [ + - ][ - + ]: 96 : if(aDepth.equalZero())
243 : : {
244 : : // no difference, try to get depth from next point
245 [ # # ]: 0 : const basegfx::B3DPoint aNextB(aSubB.getB3DPoint(nIndNext));
246 : 0 : aDepth = aNextB - aNextA;
247 [ # # ]: 0 : aDepth.normalize();
248 : : }
249 : :
250 : : // vector to left (correct for non-closed lines)
251 [ - + ][ # # ]: 96 : const bool bFirstAndNotClosed(!bClosed && 0L == b);
252 [ - + ]: 96 : basegfx::B3DVector aLeft(bFirstAndNotClosed ? aCurrA - aNextA : aPrevA - aCurrA);
253 [ + - ]: 96 : aLeft.normalize();
254 : :
255 : : // create left normal
256 [ + - ]: 96 : const basegfx::B3DVector aNormalLeft(aDepth.getPerpendicular(aLeft));
257 : :
258 [ + - ]: 96 : if(bSmoothHorizontalNormals)
259 : : {
260 : : // vector to right (correct for non-closed lines)
261 [ - + ][ # # ]: 96 : const bool bLastAndNotClosed(!bClosed && b + 1L == nPointCount);
262 [ - + ]: 96 : basegfx::B3DVector aRight(bLastAndNotClosed ? aCurrA - aPrevA : aNextA - aCurrA);
263 [ + - ]: 96 : aRight.normalize();
264 : :
265 : : // create right normal
266 [ + - ]: 96 : const basegfx::B3DVector aNormalRight(aRight.getPerpendicular(aDepth));
267 : :
268 : : // create smoothed in-between normal
269 : 96 : basegfx::B3DVector aNewNormal(aNormalLeft + aNormalRight);
270 [ + - ]: 96 : aNewNormal.normalize();
271 : :
272 : : // set as new normal at polygons
273 [ + - ]: 96 : aSubA.setNormal(b, aNewNormal);
274 [ + - ]: 96 : aSubB.setNormal(b, aNewNormal);
275 : : }
276 : : else
277 : : {
278 : : // set aNormalLeft as new normal at polygons
279 [ # # ]: 0 : aSubA.setNormal(b, aNormalLeft);
280 [ # # ]: 0 : aSubB.setNormal(b, aNormalLeft);
281 : : }
282 : :
283 : : // prepare next step
284 [ + - ]: 96 : aPrevA = aCurrA;
285 [ + - ]: 96 : aCurrA = aNextA;
286 : 96 : }
287 : :
288 [ + - ]: 24 : rPolA.setB3DPolygon(a, aSubA);
289 [ + - ]: 24 : rPolB.setB3DPolygon(a, aSubB);
290 : : }
291 [ + - ][ + - ]: 24 : }
292 : 24 : }
293 : :
294 : 48 : void impMixNormals(
295 : : basegfx::B3DPolyPolygon& rPolA,
296 : : const basegfx::B3DPolyPolygon& rPolB,
297 : : double fWeightA)
298 : : {
299 : 48 : const double fWeightB(1.0 - fWeightA);
300 : : OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
301 : :
302 [ + + ]: 96 : for(sal_uInt32 a(0L); a < rPolA.count(); a++)
303 : : {
304 [ + - ]: 48 : basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
305 [ + - ]: 48 : const basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
306 : : OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
307 [ + - ]: 48 : const sal_uInt32 nPointCount(aSubA.count());
308 : :
309 [ + + ]: 240 : for(sal_uInt32 b(0L); b < nPointCount; b++)
310 : : {
311 [ + - ]: 192 : const basegfx::B3DVector aVA(aSubA.getNormal(b) * fWeightA);
312 [ + - ]: 192 : const basegfx::B3DVector aVB(aSubB.getNormal(b) * fWeightB);
313 : 192 : basegfx::B3DVector aVNew(aVA + aVB);
314 [ + - ]: 192 : aVNew.normalize();
315 [ + - ]: 192 : aSubA.setNormal(b, aVNew);
316 : 192 : }
317 : :
318 [ + - ]: 48 : rPolA.setB3DPolygon(a, aSubA);
319 [ + - ][ + - ]: 48 : }
320 : 48 : }
321 : :
322 : 0 : bool impHasCutWith(const basegfx::B2DPolygon& rPoly, const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd)
323 : : {
324 : : // polygon is closed, one of the points is a member
325 : 0 : const sal_uInt32 nPointCount(rPoly.count());
326 : :
327 [ # # ]: 0 : if(nPointCount)
328 : : {
329 [ # # ]: 0 : basegfx::B2DPoint aCurrent(rPoly.getB2DPoint(0));
330 : 0 : const basegfx::B2DVector aVector(rEnd - rStart);
331 : :
332 [ # # ]: 0 : for(sal_uInt32 a(0); a < nPointCount; a++)
333 : : {
334 : 0 : const sal_uInt32 nNextIndex((a + 1) % nPointCount);
335 [ # # ]: 0 : const basegfx::B2DPoint aNext(rPoly.getB2DPoint(nNextIndex));
336 : 0 : const basegfx::B2DVector aEdgeVector(aNext - aCurrent);
337 : :
338 [ # # ]: 0 : if(basegfx::tools::findCut(
339 : : rStart, aVector,
340 [ # # ]: 0 : aCurrent, aEdgeVector))
341 : : {
342 : 0 : return true;
343 : : }
344 : :
345 [ # # ]: 0 : aCurrent = aNext;
346 [ # # ][ # # ]: 0 : }
[ # # ]
347 : : }
348 : :
349 : 0 : return false;
350 : : }
351 : : } // end of anonymous namespace
352 : :
353 : : //////////////////////////////////////////////////////////////////////////////
354 : :
355 : : namespace drawinglayer
356 : : {
357 : : namespace primitive3d
358 : : {
359 : 0 : void createLatheSlices(
360 : : Slice3DVector& rSliceVector,
361 : : const basegfx::B2DPolyPolygon& rSource,
362 : : double fBackScale,
363 : : double fDiagonal,
364 : : double fRotation,
365 : : sal_uInt32 nSteps,
366 : : bool bCharacterMode,
367 : : bool bCloseFront,
368 : : bool bCloseBack)
369 : : {
370 [ # # ][ # # ]: 0 : if(basegfx::fTools::equalZero(fRotation) || 0L == nSteps)
[ # # ]
371 : : {
372 : : // no rotation or no steps, just one plane
373 [ # # ][ # # ]: 0 : rSliceVector.push_back(Slice3D(rSource, basegfx::B3DHomMatrix()));
[ # # ]
374 : : }
375 : : else
376 : : {
377 : 0 : const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
378 [ # # ][ # # ]: 0 : const bool bClosedRotation(!bBackScale && basegfx::fTools::equal(fRotation, F_2PI));
[ # # ]
379 [ # # ]: 0 : basegfx::B2DPolyPolygon aFront(rSource);
380 [ # # ]: 0 : basegfx::B2DPolyPolygon aBack(rSource);
381 [ # # ]: 0 : basegfx::B3DHomMatrix aTransformBack;
382 [ # # ]: 0 : basegfx::B2DPolyPolygon aOuterBack;
383 : :
384 [ # # ]: 0 : if(bClosedRotation)
385 : : {
386 : 0 : bCloseFront = bCloseBack = false;
387 : : }
388 : :
389 [ # # ]: 0 : if(bBackScale)
390 : : {
391 : : // avoid null zoom
392 [ # # ]: 0 : if(basegfx::fTools::equalZero(fBackScale))
393 : : {
394 : 0 : fBackScale = 0.000001;
395 : : }
396 : :
397 : : // back is scaled compared to front, create scaled version
398 [ # # ][ # # ]: 0 : aBack = impScalePolyPolygonOnCenter(aBack, fBackScale);
[ # # ]
399 : : }
400 : :
401 [ # # ][ # # ]: 0 : if(bCloseFront || bCloseBack)
402 : : {
403 [ # # ]: 0 : const basegfx::B2DRange aBaseRange(basegfx::tools::getRange(aFront));
404 [ # # ]: 0 : const double fOuterLength(aBaseRange.getMaxX() * fRotation);
405 [ # # ]: 0 : const double fInnerLength(aBaseRange.getMinX() * fRotation);
406 : 0 : const double fAverageLength((fOuterLength + fInnerLength) * 0.5);
407 : :
408 [ # # ]: 0 : if(bCloseFront)
409 : : {
410 : 0 : const double fOffsetLen((fAverageLength / 12.0) * fDiagonal);
411 [ # # ]: 0 : basegfx::B2DPolyPolygon aOuterFront;
412 [ # # ]: 0 : impGetOuterPolyPolygon(aFront, aOuterFront, fOffsetLen, bCharacterMode);
413 [ # # ]: 0 : basegfx::B3DHomMatrix aTransform;
414 [ # # ]: 0 : aTransform.translate(0.0, 0.0, fOffsetLen);
415 [ # # ][ # # ]: 0 : rSliceVector.push_back(Slice3D(aOuterFront, aTransform, SLICETYPE3D_FRONTCAP));
[ # # ][ # # ]
[ # # ]
416 : : }
417 : :
418 [ # # ]: 0 : if(bCloseBack)
419 : : {
420 : 0 : const double fOffsetLen((fAverageLength / 12.0) * fDiagonal);
421 [ # # ]: 0 : impGetOuterPolyPolygon(aBack, aOuterBack, fOffsetLen, bCharacterMode);
422 [ # # ]: 0 : aTransformBack.translate(0.0, 0.0, -fOffsetLen);
423 [ # # ]: 0 : aTransformBack.rotate(0.0, fRotation, 0.0);
424 : : }
425 : : }
426 : :
427 : : // add start polygon (a = 0L)
428 [ # # ]: 0 : if(!bClosedRotation)
429 : : {
430 [ # # ][ # # ]: 0 : rSliceVector.push_back(Slice3D(aFront, basegfx::B3DHomMatrix()));
[ # # ][ # # ]
[ # # ]
431 : : }
432 : :
433 : : // create segments (a + 1 .. nSteps)
434 : 0 : const double fStepSize(1.0 / (double)nSteps);
435 : :
436 [ # # ]: 0 : for(sal_uInt32 a(0L); a < nSteps; a++)
437 : : {
438 : 0 : const double fStep((double)(a + 1L) * fStepSize);
439 [ # # ][ # # ]: 0 : basegfx::B2DPolyPolygon aNewPoly(bBackScale ? basegfx::tools::interpolate(aFront, aBack, fStep) : aFront);
[ # # ]
440 [ # # ]: 0 : basegfx::B3DHomMatrix aNewMat;
441 [ # # ]: 0 : aNewMat.rotate(0.0, fRotation * fStep, 0.0);
442 [ # # ][ # # ]: 0 : rSliceVector.push_back(Slice3D(aNewPoly, aNewMat));
[ # # ]
443 [ # # ][ # # ]: 0 : }
444 : :
445 [ # # ]: 0 : if(bCloseBack)
446 : : {
447 [ # # ][ # # ]: 0 : rSliceVector.push_back(Slice3D(aOuterBack, aTransformBack, SLICETYPE3D_BACKCAP));
[ # # ]
448 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
449 : : }
450 : 0 : }
451 : :
452 : 3001 : void createExtrudeSlices(
453 : : Slice3DVector& rSliceVector,
454 : : const basegfx::B2DPolyPolygon& rSource,
455 : : double fBackScale,
456 : : double fDiagonal,
457 : : double fDepth,
458 : : bool bCharacterMode,
459 : : bool bCloseFront,
460 : : bool bCloseBack)
461 : : {
462 [ - + ]: 3001 : if(basegfx::fTools::equalZero(fDepth))
463 : : {
464 : : // no depth, just one plane
465 [ # # ][ # # ]: 0 : rSliceVector.push_back(Slice3D(rSource, basegfx::B3DHomMatrix()));
[ # # ]
466 : : }
467 : : else
468 : : {
469 : : // there is depth, create Polygons for front,back and their default depth positions
470 [ + - ]: 3001 : basegfx::B2DPolyPolygon aFront(rSource);
471 [ + - ]: 3001 : basegfx::B2DPolyPolygon aBack(rSource);
472 : 3001 : const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
473 : 3001 : double fZFront(fDepth); // default depth for aFront
474 : 3001 : double fZBack(0.0); // default depth for aBack
475 [ + - ]: 3001 : basegfx::B2DPolyPolygon aOuterBack;
476 : :
477 [ - + ]: 3001 : if(bBackScale)
478 : : {
479 : : // avoid null zoom
480 [ # # ]: 0 : if(basegfx::fTools::equalZero(fBackScale))
481 : : {
482 : 0 : fBackScale = 0.000001;
483 : : }
484 : :
485 : : // aFront is scaled compared to aBack, create scaled version
486 [ # # ][ # # ]: 0 : aFront = impScalePolyPolygonOnCenter(aFront, fBackScale);
[ # # ]
487 : : }
488 : :
489 [ + - ]: 3001 : if(bCloseFront)
490 : : {
491 : 3001 : const double fOffset(fDepth * fDiagonal * 0.5);
492 : 3001 : fZFront = fDepth - fOffset;
493 [ + - ]: 3001 : basegfx::B2DPolyPolygon aOuterFront;
494 [ + - ]: 3001 : impGetOuterPolyPolygon(aFront, aOuterFront, fOffset, bCharacterMode);
495 [ + - ]: 3001 : basegfx::B3DHomMatrix aTransformFront;
496 [ + - ]: 3001 : aTransformFront.translate(0.0, 0.0, fDepth);
497 [ + - ][ + - ]: 3001 : rSliceVector.push_back(Slice3D(aOuterFront, aTransformFront, SLICETYPE3D_FRONTCAP));
[ + - ][ + - ]
[ + - ]
498 : : }
499 : :
500 [ + - ]: 3001 : if(bCloseBack)
501 : : {
502 : 3001 : const double fOffset(fDepth * fDiagonal * 0.5);
503 : 3001 : fZBack = fOffset;
504 [ + - ]: 3001 : impGetOuterPolyPolygon(aBack, aOuterBack, fOffset, bCharacterMode);
505 : : }
506 : :
507 : : // add front and back polygons at evtl. changed depths
508 : : {
509 [ + - ][ + - ]: 3001 : basegfx::B3DHomMatrix aTransformA, aTransformB;
510 : :
511 [ + - ]: 3001 : aTransformA.translate(0.0, 0.0, fZFront);
512 [ + - ][ + - ]: 3001 : rSliceVector.push_back(Slice3D(aFront, aTransformA));
[ + - ]
513 : :
514 [ + - ]: 3001 : aTransformB.translate(0.0, 0.0, fZBack);
515 [ + - ][ + - ]: 3001 : rSliceVector.push_back(Slice3D(aBack, aTransformB));
[ + - ][ + - ]
[ + - ]
516 : : }
517 : :
518 [ + - ]: 3001 : if(bCloseBack)
519 : : {
520 [ + - ][ + - ]: 3001 : rSliceVector.push_back(Slice3D(aOuterBack, basegfx::B3DHomMatrix(), SLICETYPE3D_BACKCAP));
[ + - ][ + - ]
[ + - ]
521 [ + - ][ + - ]: 3001 : }
[ + - ]
522 : : }
523 : 3001 : }
524 : :
525 : 0 : basegfx::B3DPolyPolygon extractHorizontalLinesFromSlice(const Slice3DVector& rSliceVector, bool bCloseHorLines)
526 : : {
527 : 0 : basegfx::B3DPolyPolygon aRetval;
528 : 0 : const sal_uInt32 nNumSlices(rSliceVector.size());
529 : :
530 [ # # ]: 0 : if(nNumSlices)
531 : : {
532 [ # # ][ # # ]: 0 : const sal_uInt32 nSlideSubPolygonCount(rSliceVector[0].getB3DPolyPolygon().count());
533 : :
534 [ # # ]: 0 : for(sal_uInt32 b(0); b < nSlideSubPolygonCount; b++)
535 : : {
536 [ # # ][ # # ]: 0 : const sal_uInt32 nSubPolygonPointCount(rSliceVector[0].getB3DPolyPolygon().getB3DPolygon(b).count());
[ # # ][ # # ]
537 : :
538 [ # # ]: 0 : for(sal_uInt32 c(0); c < nSubPolygonPointCount; c++)
539 : : {
540 [ # # ]: 0 : basegfx::B3DPolygon aNew;
541 : :
542 [ # # ]: 0 : for(sal_uInt32 d(0); d < nNumSlices; d++)
543 : : {
544 : : OSL_ENSURE(nSlideSubPolygonCount == rSliceVector[d].getB3DPolyPolygon().count(),
545 : : "Slice PolyPolygon with different Polygon count (!)");
546 : : OSL_ENSURE(nSubPolygonPointCount == rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).count(),
547 : : "Slice Polygon with different point count (!)");
548 [ # # ][ # # ]: 0 : aNew.append(rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).getB3DPoint(c));
[ # # ][ # # ]
[ # # ]
549 : : }
550 : :
551 [ # # ]: 0 : aNew.setClosed(bCloseHorLines);
552 [ # # ]: 0 : aRetval.append(aNew);
553 [ # # ]: 0 : }
554 : : }
555 : : }
556 : :
557 : 0 : return aRetval;
558 : : }
559 : :
560 : 0 : basegfx::B3DPolyPolygon extractVerticalLinesFromSlice(const Slice3DVector& rSliceVector)
561 : : {
562 : 0 : basegfx::B3DPolyPolygon aRetval;
563 : 0 : const sal_uInt32 nNumSlices(rSliceVector.size());
564 : :
565 [ # # ]: 0 : for(sal_uInt32 a(0L); a < nNumSlices; a++)
566 : : {
567 [ # # ][ # # ]: 0 : aRetval.append(rSliceVector[a].getB3DPolyPolygon());
568 : : }
569 : :
570 : 0 : return aRetval;
571 : : }
572 : :
573 : 24 : void extractPlanesFromSlice(
574 : : ::std::vector< basegfx::B3DPolyPolygon >& rFill,
575 : : const Slice3DVector& rSliceVector,
576 : : bool bCreateNormals,
577 : : bool bSmoothHorizontalNormals,
578 : : bool bSmoothNormals,
579 : : bool bSmoothLids,
580 : : bool bClosed,
581 : : double fSmoothNormalsMix,
582 : : double fSmoothLidsMix,
583 : : bool bCreateTextureCoordinates,
584 : : const basegfx::B2DHomMatrix& rTexTransform)
585 : : {
586 : 24 : const sal_uInt32 nNumSlices(rSliceVector.size());
587 : :
588 [ + - ]: 24 : if(nNumSlices)
589 : : {
590 : : // common parameters
591 [ - + ]: 24 : const sal_uInt32 nLoopCount(bClosed ? nNumSlices : nNumSlices - 1L);
592 [ + - ]: 24 : basegfx::B3DPolyPolygon aEdgeRounding;
593 : : sal_uInt32 a;
594 : :
595 : : // tetxture parameters
596 : 24 : double fInvTexHeight(1.0);
597 : 24 : double fTexHeightPos(0.0);
598 : 24 : double fTexStart(0.0);
599 : 24 : double fTexStop(1.0);
600 [ + - ]: 24 : ::std::vector<double> aTexHeightArray;
601 [ + - ]: 24 : basegfx::B3DRange aTexRangeFront;
602 [ + - ]: 24 : basegfx::B3DRange aTexRangeBack;
603 : :
604 [ - + ]: 24 : if(bCreateTextureCoordinates)
605 : : {
606 [ # # ][ # # ]: 0 : aTexRangeFront = basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon());
607 [ # # ][ # # ]: 0 : aTexRangeBack = basegfx::tools::getRange(rSliceVector[nNumSlices - 1L].getB3DPolyPolygon());
608 : :
609 [ # # ][ # # ]: 0 : if(aTexRangeBack.getDepth() > aTexRangeBack.getWidth())
[ # # ]
610 : : {
611 : : // last polygon is rotated so that depth is bigger than width, exchange X and Z
612 : : // for making applyDefaultTextureCoordinatesParallel use Z instead of X for
613 : : // horizontal texture coordinate
614 : : aTexRangeBack = basegfx::B3DRange(
615 : : aTexRangeBack.getMinZ(), aTexRangeBack.getMinY(), aTexRangeBack.getMinX(),
616 [ # # ][ # # ]: 0 : aTexRangeBack.getMaxZ(), aTexRangeBack.getMaxY(), aTexRangeBack.getMaxX());
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
617 : : }
618 : :
619 [ # # ][ # # ]: 0 : basegfx::B3DPoint aCenter(basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon()).getCenter());
[ # # ]
620 : :
621 [ # # ]: 0 : for(a = 0L; a < nLoopCount; a++)
622 : : {
623 [ # # ][ # # ]: 0 : const basegfx::B3DPoint aNextCenter(basegfx::tools::getRange(rSliceVector[(a + 1L) % nNumSlices].getB3DPolyPolygon()).getCenter());
[ # # ]
624 [ # # ]: 0 : const double fLength(basegfx::B3DVector(aNextCenter - aCenter).getLength());
625 [ # # ]: 0 : aTexHeightArray.push_back(fLength);
626 [ # # ]: 0 : aCenter = aNextCenter;
627 : 0 : }
628 : :
629 [ # # ]: 0 : const double fTexHeight(::std::accumulate(aTexHeightArray.begin(), aTexHeightArray.end(), 0.0));
630 : :
631 [ # # ]: 0 : if(!basegfx::fTools::equalZero(fTexHeight))
632 : : {
633 : 0 : fInvTexHeight = 1.0 / fTexHeight;
634 : 0 : }
635 : : }
636 : :
637 [ + - ]: 24 : if(nLoopCount)
638 : : {
639 [ + + ]: 96 : for(a = 0L; a < nLoopCount; a++)
640 : : {
641 [ + - ]: 72 : const Slice3D& rSliceA(rSliceVector[a]);
642 [ + - ]: 72 : const Slice3D& rSliceB(rSliceVector[(a + 1L) % nNumSlices]);
643 [ + + ][ + + ]: 72 : const bool bAcceptPair(SLICETYPE3D_REGULAR == rSliceA.getSliceType() && SLICETYPE3D_REGULAR == rSliceB.getSliceType());
644 [ + - ]: 72 : basegfx::B3DPolyPolygon aPolA(rSliceA.getB3DPolyPolygon());
645 [ + - ]: 72 : basegfx::B3DPolyPolygon aPolB(rSliceB.getB3DPolyPolygon());
646 : :
647 [ + + ]: 72 : if(bAcceptPair)
648 : : {
649 [ + - ]: 24 : if(bCreateNormals)
650 : : {
651 [ + - ]: 24 : impCreateInBetweenNormals(aPolB, aPolA, bSmoothHorizontalNormals);
652 : : }
653 : :
654 : : {
655 : 24 : const sal_uInt32 nIndPrev((a + nNumSlices - 1L) % nNumSlices);
656 [ + - ]: 24 : const Slice3D& rSlicePrev(rSliceVector[nIndPrev]);
657 [ + - ]: 24 : basegfx::B3DPolyPolygon aPrev(rSlicePrev.getB3DPolyPolygon());
658 [ + - ]: 24 : basegfx::B3DPolyPolygon aPolAA(rSliceA.getB3DPolyPolygon());
659 : :
660 [ + - ]: 24 : if(SLICETYPE3D_FRONTCAP == rSlicePrev.getSliceType())
661 : : {
662 [ + - ]: 24 : basegfx::B3DPolyPolygon aFront(rSlicePrev.getB3DPolyPolygon());
663 [ + - ]: 24 : const bool bHasSlant(aPolAA != aPrev);
664 : :
665 [ - + ]: 24 : if(bCreateTextureCoordinates)
666 : : {
667 [ # # ][ # # ]: 0 : aFront = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront);
[ # # ]
668 : : }
669 : :
670 [ + - ]: 24 : if(bCreateNormals)
671 : : {
672 : 24 : basegfx::B3DVector aNormal(0.0, 0.0, -1.0);
673 : :
674 [ + - ][ + - ]: 24 : if(aFront.count())
675 : : {
676 [ + - ][ + - ]: 24 : aNormal = -aFront.getB3DPolygon(0L).getNormal();
[ + - ]
677 : : }
678 : :
679 [ + - ]: 24 : impSetNormal(aFront, aNormal);
680 : :
681 [ - + ]: 24 : if(bHasSlant)
682 : : {
683 [ # # ]: 0 : impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals);
684 : :
685 [ # # ]: 0 : if(bSmoothNormals)
686 : : {
687 : : // smooth and copy
688 [ # # ]: 0 : impMixNormals(aPolA, aPolAA, fSmoothNormalsMix);
689 [ # # ]: 0 : aPolAA = aPolA;
690 : : }
691 : : else
692 : : {
693 : : // take over from surface
694 [ # # ]: 0 : aPolAA = aPolA;
695 : : }
696 : :
697 [ # # ]: 0 : if(bSmoothLids)
698 : : {
699 : : // smooth and copy
700 [ # # ]: 0 : impMixNormals(aFront, aPrev, fSmoothLidsMix);
701 [ # # ]: 0 : aPrev = aFront;
702 : : }
703 : : else
704 : : {
705 : : // take over from front
706 [ # # ]: 0 : aPrev = aFront;
707 : : }
708 : : }
709 : : else
710 : : {
711 [ + - ]: 24 : if(bSmoothNormals)
712 : : {
713 : : // smooth
714 [ + - ]: 24 : impMixNormals(aPolA, aFront, fSmoothNormalsMix);
715 : : }
716 : :
717 [ - + ]: 24 : if(bSmoothLids)
718 : : {
719 : : // smooth and copy
720 [ # # ]: 0 : impMixNormals(aFront, aPolA, fSmoothLidsMix);
721 [ # # ]: 0 : aPolA = aFront;
722 : : }
723 : 24 : }
724 : : }
725 : :
726 [ - + ]: 24 : if(bHasSlant)
727 : : {
728 [ # # ]: 0 : if(bCreateTextureCoordinates)
729 : : {
730 : 0 : fTexStart = fTexHeightPos * fInvTexHeight;
731 [ # # ]: 0 : fTexStop = (fTexHeightPos - aTexHeightArray[(a + nLoopCount - 1L) % nLoopCount]) * fInvTexHeight;
732 : : }
733 : :
734 [ # # ]: 0 : impAddInBetweenFill(aEdgeRounding, aPolAA, aPrev, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
735 : : }
736 : :
737 [ + - ]: 24 : aFront.flip();
738 [ + - ][ + - ]: 24 : rFill.push_back(aFront);
739 : : }
740 : : else
741 : : {
742 [ # # ][ # # ]: 0 : if(bCreateNormals && bSmoothNormals && (nIndPrev != a + 1L))
[ # # ]
743 : : {
744 [ # # ]: 0 : impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals);
745 [ # # ]: 0 : impMixNormals(aPolA, aPolAA, 0.5);
746 : : }
747 [ + - ][ + - ]: 24 : }
748 : : }
749 : :
750 : : {
751 : 24 : const sal_uInt32 nIndNext((a + 2L) % nNumSlices);
752 [ + - ]: 24 : const Slice3D& rSliceNext(rSliceVector[nIndNext]);
753 [ + - ]: 24 : basegfx::B3DPolyPolygon aNext(rSliceNext.getB3DPolyPolygon());
754 [ + - ]: 24 : basegfx::B3DPolyPolygon aPolBB(rSliceB.getB3DPolyPolygon());
755 : :
756 [ + - ]: 24 : if(SLICETYPE3D_BACKCAP == rSliceNext.getSliceType())
757 : : {
758 [ + - ]: 24 : basegfx::B3DPolyPolygon aBack(rSliceNext.getB3DPolyPolygon());
759 [ + - ]: 24 : const bool bHasSlant(aPolBB != aNext);
760 : :
761 [ - + ]: 24 : if(bCreateTextureCoordinates)
762 : : {
763 [ # # ][ # # ]: 0 : aBack = basegfx::tools::applyDefaultTextureCoordinatesParallel(aBack, aTexRangeBack);
[ # # ]
764 : : }
765 : :
766 [ + - ]: 24 : if(bCreateNormals)
767 : : {
768 [ + - ][ + - ]: 24 : const basegfx::B3DVector aNormal(aBack.count() ? aBack.getB3DPolygon(0L).getNormal() : basegfx::B3DVector(0.0, 0.0, 1.0));
[ + - ][ + - ]
[ + - ][ + - ]
[ # # ]
769 [ + - ]: 24 : impSetNormal(aBack, aNormal);
770 : :
771 [ - + ]: 24 : if(bHasSlant)
772 : : {
773 [ # # ]: 0 : impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals);
774 : :
775 [ # # ]: 0 : if(bSmoothNormals)
776 : : {
777 : : // smooth and copy
778 [ # # ]: 0 : impMixNormals(aPolB, aPolBB, fSmoothNormalsMix);
779 [ # # ]: 0 : aPolBB = aPolB;
780 : : }
781 : : else
782 : : {
783 : : // take over from surface
784 [ # # ]: 0 : aPolBB = aPolB;
785 : : }
786 : :
787 [ # # ]: 0 : if(bSmoothLids)
788 : : {
789 : : // smooth and copy
790 [ # # ]: 0 : impMixNormals(aBack, aNext, fSmoothLidsMix);
791 [ # # ]: 0 : aNext = aBack;
792 : : }
793 : : else
794 : : {
795 : : // take over from back
796 [ # # ]: 0 : aNext = aBack;
797 : : }
798 : : }
799 : : else
800 : : {
801 [ + - ]: 24 : if(bSmoothNormals)
802 : : {
803 : : // smooth
804 [ + - ]: 24 : impMixNormals(aPolB, aBack, fSmoothNormalsMix);
805 : : }
806 : :
807 [ - + ]: 24 : if(bSmoothLids)
808 : : {
809 : : // smooth and copy
810 [ # # ]: 0 : impMixNormals(aBack, aPolB, fSmoothLidsMix);
811 [ # # ]: 0 : aPolB = aBack;
812 : : }
813 : 24 : }
814 : : }
815 : :
816 [ - + ]: 24 : if(bHasSlant)
817 : : {
818 [ # # ]: 0 : if(bCreateTextureCoordinates)
819 : : {
820 [ # # ][ # # ]: 0 : fTexStart = (fTexHeightPos + aTexHeightArray[a] + aTexHeightArray[(a + 1L) % nLoopCount]) * fInvTexHeight;
821 [ # # ]: 0 : fTexStop = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight;
822 : : }
823 : :
824 [ # # ]: 0 : impAddInBetweenFill(aEdgeRounding, aNext, aPolBB, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
825 : : }
826 : :
827 [ + - ][ + - ]: 24 : rFill.push_back(aBack);
828 : : }
829 : : else
830 : : {
831 [ # # ][ # # ]: 0 : if(bCreateNormals && bSmoothNormals && (nIndNext != a))
[ # # ]
832 : : {
833 [ # # ]: 0 : impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals);
834 [ # # ]: 0 : impMixNormals(aPolB, aPolBB, 0.5);
835 : : }
836 [ + - ][ + - ]: 24 : }
837 : : }
838 : :
839 [ - + ]: 24 : if(bCreateTextureCoordinates)
840 : : {
841 [ # # ]: 0 : fTexStart = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight;
842 : 0 : fTexStop = fTexHeightPos * fInvTexHeight;
843 : : }
844 : :
845 [ + - ]: 24 : impAddInBetweenFill(aEdgeRounding, aPolB, aPolA, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
846 : : }
847 : :
848 [ - + ]: 72 : if(bCreateTextureCoordinates)
849 : : {
850 [ # # ]: 0 : fTexHeightPos += aTexHeightArray[a];
851 : : }
852 [ + - ][ + - ]: 72 : }
853 : : }
854 : : else
855 : : {
856 : : // no loop, but a single slice (1 == nNumSlices), create a filling from the single
857 : : // front plane
858 [ # # ]: 0 : const Slice3D& rSlice(rSliceVector[0]);
859 [ # # ]: 0 : basegfx::B3DPolyPolygon aFront(rSlice.getB3DPolyPolygon());
860 : :
861 [ # # ]: 0 : if(bCreateTextureCoordinates)
862 : : {
863 [ # # ][ # # ]: 0 : aFront = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront);
[ # # ]
864 : : }
865 : :
866 [ # # ]: 0 : if(bCreateNormals)
867 : : {
868 : 0 : basegfx::B3DVector aNormal(0.0, 0.0, -1.0);
869 : :
870 [ # # ][ # # ]: 0 : if(aFront.count())
871 : : {
872 [ # # ][ # # ]: 0 : aNormal = -aFront.getB3DPolygon(0L).getNormal();
[ # # ]
873 : : }
874 : :
875 [ # # ]: 0 : impSetNormal(aFront, aNormal);
876 : : }
877 : :
878 [ # # ]: 0 : aFront.flip();
879 [ # # ][ # # ]: 0 : rFill.push_back(aFront);
880 : : }
881 : :
882 [ - + ]: 24 : if(bCreateTextureCoordinates)
883 : : {
884 [ # # ]: 0 : aEdgeRounding.transformTextureCoordiantes(rTexTransform);
885 : : }
886 : :
887 [ + - ][ + + ]: 120 : for(a = 0L; a < aEdgeRounding.count(); a++)
888 : : {
889 [ + - ][ + - ]: 96 : rFill.push_back(basegfx::B3DPolyPolygon(aEdgeRounding.getB3DPolygon(a)));
[ + - ][ + - ]
[ + - ]
890 [ + - ]: 24 : }
891 : : }
892 : 24 : }
893 : :
894 : 0 : void createReducedOutlines(
895 : : const geometry::ViewInformation3D& rViewInformation,
896 : : const basegfx::B3DHomMatrix& rObjectTransform,
897 : : const basegfx::B3DPolygon& rLoopA,
898 : : const basegfx::B3DPolygon& rLoopB,
899 : : basegfx::B3DPolyPolygon& rTarget)
900 : : {
901 : 0 : const sal_uInt32 nPointCount(rLoopA.count());
902 : :
903 : : // with idetic polygons there are no outlines
904 [ # # ]: 0 : if(rLoopA != rLoopB)
905 : : {
906 [ # # ][ # # ]: 0 : if(nPointCount && nPointCount == rLoopB.count())
[ # # ]
907 : : {
908 [ # # ][ # # ]: 0 : const basegfx::B3DHomMatrix aObjectTransform(rViewInformation.getObjectToView() * rObjectTransform);
909 [ # # ]: 0 : const basegfx::B2DPolygon a2DLoopA(basegfx::tools::createB2DPolygonFromB3DPolygon(rLoopA, aObjectTransform));
910 [ # # ]: 0 : const basegfx::B2DPolygon a2DLoopB(basegfx::tools::createB2DPolygonFromB3DPolygon(rLoopB, aObjectTransform));
911 [ # # ][ # # ]: 0 : const basegfx::B2DPoint a2DCenterA(a2DLoopA.getB2DRange().getCenter());
912 [ # # ][ # # ]: 0 : const basegfx::B2DPoint a2DCenterB(a2DLoopB.getB2DRange().getCenter());
913 : :
914 : : // without detectable Y-Axis there are no outlines
915 [ # # ]: 0 : if(!a2DCenterA.equal(a2DCenterB))
916 : : {
917 : : // search for outmost left and right inter-loop-edges which do not cut the loops
918 : 0 : const basegfx::B2DPoint aCommonCenter(basegfx::average(a2DCenterA, a2DCenterB));
919 : 0 : const basegfx::B2DVector aAxisVector(a2DCenterA - a2DCenterB);
920 : 0 : double fMaxLeft(0.0);
921 : 0 : double fMaxRight(0.0);
922 : 0 : sal_uInt32 nIndexLeft(0);
923 : 0 : sal_uInt32 nIndexRight(0);
924 : :
925 [ # # ]: 0 : for(sal_uInt32 a(0); a < nPointCount; a++)
926 : : {
927 [ # # ]: 0 : const basegfx::B2DPoint aStart(a2DLoopA.getB2DPoint(a));
928 [ # # ]: 0 : const basegfx::B2DPoint aEnd(a2DLoopB.getB2DPoint(a));
929 : 0 : const basegfx::B2DPoint aMiddle(basegfx::average(aStart, aEnd));
930 : :
931 [ # # ][ # # ]: 0 : if(!basegfx::tools::isInside(a2DLoopA, aMiddle))
932 : : {
933 [ # # ][ # # ]: 0 : if(!basegfx::tools::isInside(a2DLoopB, aMiddle))
934 : : {
935 [ # # ][ # # ]: 0 : if(!impHasCutWith(a2DLoopA, aStart, aEnd))
936 : : {
937 [ # # ][ # # ]: 0 : if(!impHasCutWith(a2DLoopB, aStart, aEnd))
938 : : {
939 : 0 : const basegfx::B2DVector aCandidateVector(aMiddle - aCommonCenter);
940 [ # # ]: 0 : const double fCross(aCandidateVector.cross(aAxisVector));
941 [ # # ]: 0 : const double fDistance(aCandidateVector.getLength());
942 : :
943 [ # # ]: 0 : if(fCross > 0.0)
944 : : {
945 [ # # ]: 0 : if(fDistance > fMaxLeft)
946 : : {
947 : 0 : fMaxLeft = fDistance;
948 : 0 : nIndexLeft = a;
949 : : }
950 : : }
951 [ # # ]: 0 : else if(fCross < 0.0)
952 : : {
953 [ # # ]: 0 : if(fDistance > fMaxRight)
954 : : {
955 : 0 : fMaxRight = fDistance;
956 : 0 : nIndexRight = a;
957 : : }
958 : 0 : }
959 : : }
960 : : }
961 : : }
962 : : }
963 : 0 : }
964 : :
965 [ # # ]: 0 : if(fMaxLeft != 0.0)
966 : : {
967 [ # # ]: 0 : basegfx::B3DPolygon aToBeAdded;
968 [ # # ][ # # ]: 0 : aToBeAdded.append(rLoopA.getB3DPoint(nIndexLeft));
969 [ # # ][ # # ]: 0 : aToBeAdded.append(rLoopB.getB3DPoint(nIndexLeft));
970 [ # # ][ # # ]: 0 : rTarget.append(aToBeAdded);
971 : : }
972 : :
973 [ # # ]: 0 : if(fMaxRight != 0.0)
974 : : {
975 [ # # ]: 0 : basegfx::B3DPolygon aToBeAdded;
976 [ # # ][ # # ]: 0 : aToBeAdded.append(rLoopA.getB3DPoint(nIndexRight));
977 [ # # ][ # # ]: 0 : aToBeAdded.append(rLoopB.getB3DPoint(nIndexRight));
978 [ # # ][ # # ]: 0 : rTarget.append(aToBeAdded);
979 : 0 : }
980 [ # # ][ # # ]: 0 : }
[ # # ]
981 : : }
982 : : }
983 : 0 : }
984 : :
985 : : } // end of namespace primitive3d
986 : : } // end of namespace drawinglayer
987 : :
988 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|