xref: /trunk/main/basegfx/source/polygon/b3dpolypolygontools.cxx (revision ffd38472365e95f6a578737bc9a5eb0fac624a86)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_basegfx.hxx"
24 
25 #include <basegfx/polygon/b3dpolypolygontools.hxx>
26 #include <basegfx/range/b3drange.hxx>
27 #include <basegfx/polygon/b3dpolypolygon.hxx>
28 #include <basegfx/polygon/b3dpolygon.hxx>
29 #include <basegfx/polygon/b3dpolygontools.hxx>
30 #include <numeric>
31 #include <basegfx/matrix/b3dhommatrix.hxx>
32 #include <basegfx/numeric/ftools.hxx>
33 #include <osl/mutex.hxx>
34 #include <com/sun/star/drawing/DoubleSequence.hpp>
35 
36 // predefines
37 #define nMinSegments sal_uInt32(1)
38 #define nMaxSegments sal_uInt32(512)
39 
40 namespace basegfx
41 {
42     namespace tools
43     {
44         // B3DPolyPolygon tools
45         B3DRange getRange(const B3DPolyPolygon& rCandidate)
46         {
47             B3DRange aRetval;
48             const sal_uInt32 nPolygonCount(rCandidate.count());
49 
50             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
51             {
52                 B3DPolygon aCandidate = rCandidate.getB3DPolygon(a);
53                 aRetval.expand(getRange(aCandidate));
54             }
55 
56             return aRetval;
57         }
58 
59         void applyLineDashing(const B3DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B3DPolyPolygon* pLineTarget, B3DPolyPolygon* pGapTarget, double fFullDashDotLen)
60         {
61             if(0.0 == fFullDashDotLen && rDotDashArray.size())
62             {
63                 // calculate fFullDashDotLen from rDotDashArray
64                 fFullDashDotLen = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
65             }
66 
67             if(rCandidate.count() && fFullDashDotLen > 0.0)
68             {
69                 B3DPolyPolygon aLineTarget, aGapTarget;
70 
71                 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
72                 {
73                     const B3DPolygon aCandidate(rCandidate.getB3DPolygon(a));
74 
75                     applyLineDashing(
76                         aCandidate,
77                         rDotDashArray,
78                         pLineTarget ? &aLineTarget : 0,
79                         pGapTarget ? &aGapTarget : 0,
80                         fFullDashDotLen);
81 
82                     if(pLineTarget)
83                     {
84                         pLineTarget->append(aLineTarget);
85                     }
86 
87                     if(pGapTarget)
88                     {
89                         pGapTarget->append(aGapTarget);
90                     }
91                 }
92             }
93         }
94 
95         B3DPolyPolygon createUnitCubePolyPolygon()
96         {
97             static B3DPolyPolygon aRetval;
98             ::osl::Mutex m_mutex;
99 
100             if(!aRetval.count())
101             {
102                 B3DPolygon aTemp;
103                 aTemp.append(B3DPoint(0.0, 0.0, 1.0));
104                 aTemp.append(B3DPoint(0.0, 1.0, 1.0));
105                 aTemp.append(B3DPoint(1.0, 1.0, 1.0));
106                 aTemp.append(B3DPoint(1.0, 0.0, 1.0));
107                 aTemp.setClosed(true);
108                 aRetval.append(aTemp);
109 
110                 aTemp.clear();
111                 aTemp.append(B3DPoint(0.0, 0.0, 0.0));
112                 aTemp.append(B3DPoint(0.0, 1.0, 0.0));
113                 aTemp.append(B3DPoint(1.0, 1.0, 0.0));
114                 aTemp.append(B3DPoint(1.0, 0.0, 0.0));
115                 aTemp.setClosed(true);
116                 aRetval.append(aTemp);
117 
118                 aTemp.clear();
119                 aTemp.append(B3DPoint(0.0, 0.0, 0.0));
120                 aTemp.append(B3DPoint(0.0, 0.0, 1.0));
121                 aRetval.append(aTemp);
122 
123                 aTemp.clear();
124                 aTemp.append(B3DPoint(0.0, 1.0, 0.0));
125                 aTemp.append(B3DPoint(0.0, 1.0, 1.0));
126                 aRetval.append(aTemp);
127 
128                 aTemp.clear();
129                 aTemp.append(B3DPoint(1.0, 1.0, 0.0));
130                 aTemp.append(B3DPoint(1.0, 1.0, 1.0));
131                 aRetval.append(aTemp);
132 
133                 aTemp.clear();
134                 aTemp.append(B3DPoint(1.0, 0.0, 0.0));
135                 aTemp.append(B3DPoint(1.0, 0.0, 1.0));
136                 aRetval.append(aTemp);
137             }
138 
139             return aRetval;
140         }
141 
142         B3DPolyPolygon createUnitCubeFillPolyPolygon()
143         {
144             static B3DPolyPolygon aRetval;
145             ::osl::Mutex m_mutex;
146 
147             if(!aRetval.count())
148             {
149                 B3DPolygon aTemp;
150 
151                 // all points
152                 const B3DPoint A(0.0, 0.0, 0.0);
153                 const B3DPoint B(0.0, 1.0, 0.0);
154                 const B3DPoint C(1.0, 1.0, 0.0);
155                 const B3DPoint D(1.0, 0.0, 0.0);
156                 const B3DPoint E(0.0, 0.0, 1.0);
157                 const B3DPoint F(0.0, 1.0, 1.0);
158                 const B3DPoint G(1.0, 1.0, 1.0);
159                 const B3DPoint H(1.0, 0.0, 1.0);
160 
161                 // create bottom
162                 aTemp.append(D);
163                 aTemp.append(A);
164                 aTemp.append(E);
165                 aTemp.append(H);
166                 aTemp.setClosed(true);
167                 aRetval.append(aTemp);
168 
169                 // create front
170                 aTemp.clear();
171                 aTemp.append(B);
172                 aTemp.append(A);
173                 aTemp.append(D);
174                 aTemp.append(C);
175                 aTemp.setClosed(true);
176                 aRetval.append(aTemp);
177 
178                 // create left
179                 aTemp.clear();
180                 aTemp.append(E);
181                 aTemp.append(A);
182                 aTemp.append(B);
183                 aTemp.append(F);
184                 aTemp.setClosed(true);
185                 aRetval.append(aTemp);
186 
187                 // create top
188                 aTemp.clear();
189                 aTemp.append(C);
190                 aTemp.append(G);
191                 aTemp.append(F);
192                 aTemp.append(B);
193                 aTemp.setClosed(true);
194                 aRetval.append(aTemp);
195 
196                 // create right
197                 aTemp.clear();
198                 aTemp.append(H);
199                 aTemp.append(G);
200                 aTemp.append(C);
201                 aTemp.append(D);
202                 aTemp.setClosed(true);
203                 aRetval.append(aTemp);
204 
205                 // create back
206                 aTemp.clear();
207                 aTemp.append(F);
208                 aTemp.append(G);
209                 aTemp.append(H);
210                 aTemp.append(E);
211                 aTemp.setClosed(true);
212                 aRetval.append(aTemp);
213             }
214 
215             return aRetval;
216         }
217 
218         B3DPolyPolygon createCubePolyPolygonFromB3DRange( const B3DRange& rRange)
219         {
220             B3DPolyPolygon aRetval;
221 
222             if(!rRange.isEmpty())
223             {
224                 aRetval = createUnitCubePolyPolygon();
225                 B3DHomMatrix aTrans;
226                 aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
227                 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
228                 aRetval.transform(aTrans);
229                 aRetval.removeDoublePoints();
230             }
231 
232             return aRetval;
233         }
234 
235         B3DPolyPolygon createCubeFillPolyPolygonFromB3DRange( const B3DRange& rRange)
236         {
237             B3DPolyPolygon aRetval;
238 
239             if(!rRange.isEmpty())
240             {
241                 aRetval = createUnitCubeFillPolyPolygon();
242                 B3DHomMatrix aTrans;
243                 aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
244                 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
245                 aRetval.transform(aTrans);
246                 aRetval.removeDoublePoints();
247             }
248 
249             return aRetval;
250         }
251 
252         // helper for getting the 3D Point from given cartesian coordinates. fVer is defined from
253         // [F_PI2 .. -F_PI2], fHor from [0.0 .. F_2PI]
254         inline B3DPoint getPointFromCartesian(double fVer, double fHor)
255         {
256             const double fCosHor(cos(fHor));
257             return B3DPoint(fCosHor * cos(fVer), sin(fHor), fCosHor * -sin(fVer));
258         }
259 
260         B3DPolyPolygon createUnitSpherePolyPolygon(
261             sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
262             double fVerStart, double fVerStop,
263             double fHorStart, double fHorStop)
264         {
265             B3DPolyPolygon aRetval;
266             sal_uInt32 a, b;
267 
268             if(!nHorSeg)
269             {
270                 nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
271             }
272 
273             // min/max limitations
274             nHorSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nHorSeg));
275 
276             if(!nVerSeg)
277             {
278                 nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
279             }
280 
281             // min/max limitations
282             nVerSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nVerSeg));
283 
284             // create constants
285             const double fVerDiffPerStep((fVerStop - fVerStart) / (double)nVerSeg);
286             const double fHorDiffPerStep((fHorStop - fHorStart) / (double)nHorSeg);
287             bool bHorClosed(fTools::equal(fHorStop - fHorStart, F_2PI));
288             bool bVerFromTop(fTools::equal(fVerStart, F_PI2));
289             bool bVerToBottom(fTools::equal(fVerStop, -F_PI2));
290 
291             // create horizontal rings
292             const sal_uInt32 nLoopVerInit(bVerFromTop ? 1L : 0L);
293             const sal_uInt32 nLoopVerLimit(bVerToBottom ? nVerSeg : nVerSeg + 1L);
294             const sal_uInt32 nLoopHorLimit(bHorClosed ? nHorSeg : nHorSeg + 1L);
295 
296             for(a = nLoopVerInit; a < nLoopVerLimit; a++)
297             {
298                 const double fVer(fVerStart + ((double)(a) * fVerDiffPerStep));
299                 B3DPolygon aNew;
300 
301                 for(b = 0L; b < nLoopHorLimit; b++)
302                 {
303                     const double fHor(fHorStart + ((double)(b) * fHorDiffPerStep));
304                     aNew.append(getPointFromCartesian(fHor, fVer));
305                 }
306 
307                 aNew.setClosed(bHorClosed);
308                 aRetval.append(aNew);
309             }
310 
311             // create vertical half-rings
312             for(a = 0L; a < nLoopHorLimit; a++)
313             {
314                 const double fHor(fHorStart + ((double)(a) * fHorDiffPerStep));
315                 B3DPolygon aNew;
316 
317                 if(bVerFromTop)
318                 {
319                     aNew.append(B3DPoint(0.0, 1.0, 0.0));
320                 }
321 
322                 for(b = nLoopVerInit; b < nLoopVerLimit; b++)
323                 {
324                     const double fVer(fVerStart + ((double)(b) * fVerDiffPerStep));
325                     aNew.append(getPointFromCartesian(fHor, fVer));
326                 }
327 
328                 if(bVerToBottom)
329                 {
330                     aNew.append(B3DPoint(0.0, -1.0, 0.0));
331                 }
332 
333                 aRetval.append(aNew);
334             }
335 
336             return aRetval;
337         }
338 
339         B3DPolyPolygon createSpherePolyPolygonFromB3DRange( const B3DRange& rRange,
340             sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
341             double fVerStart, double fVerStop,
342             double fHorStart, double fHorStop)
343         {
344             B3DPolyPolygon aRetval(createUnitSpherePolyPolygon(nHorSeg, nVerSeg, fVerStart, fVerStop, fHorStart, fHorStop));
345 
346             if(aRetval.count())
347             {
348                 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
349                 B3DHomMatrix aTrans;
350                 aTrans.translate(1.0, 1.0, 1.0);
351                 aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
352                 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
353                 aRetval.transform(aTrans);
354             }
355 
356             return aRetval;
357         }
358 
359         B3DPolyPolygon createUnitSphereFillPolyPolygon(
360             sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
361             bool bNormals,
362             double fVerStart, double fVerStop,
363             double fHorStart, double fHorStop)
364         {
365             B3DPolyPolygon aRetval;
366 
367             if(!nHorSeg)
368             {
369                 nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
370             }
371 
372             // min/max limitations
373             nHorSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nHorSeg));
374 
375             if(!nVerSeg)
376             {
377                 nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
378             }
379 
380             // min/max limitations
381             nVerSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nVerSeg));
382 
383             // vertical loop
384             for(sal_uInt32 a(0L); a < nVerSeg; a++)
385             {
386                 const double fVer(fVerStart + (((fVerStop - fVerStart) * a) / nVerSeg));
387                 const double fVer2(fVerStart + (((fVerStop - fVerStart) * (a + 1)) / nVerSeg));
388 
389                 // horizontal loop
390                 for(sal_uInt32 b(0L); b < nHorSeg; b++)
391                 {
392                     const double fHor(fHorStart + (((fHorStop - fHorStart) * b) / nHorSeg));
393                     const double fHor2(fHorStart + (((fHorStop - fHorStart) * (b + 1)) / nHorSeg));
394                     B3DPolygon aNew;
395 
396                     aNew.append(getPointFromCartesian(fHor, fVer));
397                     aNew.append(getPointFromCartesian(fHor2, fVer));
398                     aNew.append(getPointFromCartesian(fHor2, fVer2));
399                     aNew.append(getPointFromCartesian(fHor, fVer2));
400 
401                     if(bNormals)
402                     {
403                         for(sal_uInt32 c(0L); c < aNew.count(); c++)
404                         {
405                             aNew.setNormal(c, ::basegfx::B3DVector(aNew.getB3DPoint(c)));
406                         }
407                     }
408 
409                     aNew.setClosed(true);
410                     aRetval.append(aNew);
411                 }
412             }
413 
414             return aRetval;
415         }
416 
417         B3DPolyPolygon createSphereFillPolyPolygonFromB3DRange( const B3DRange& rRange,
418             sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
419             bool bNormals,
420             double fVerStart, double fVerStop,
421             double fHorStart, double fHorStop)
422         {
423             B3DPolyPolygon aRetval(createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, bNormals, fVerStart, fVerStop, fHorStart, fHorStop));
424 
425             if(aRetval.count())
426             {
427                 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
428                 B3DHomMatrix aTrans;
429                 aTrans.translate(1.0, 1.0, 1.0);
430                 aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
431                 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
432                 aRetval.transform(aTrans);
433             }
434 
435             return aRetval;
436         }
437 
438         B3DPolyPolygon applyDefaultNormalsSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter)
439         {
440             B3DPolyPolygon aRetval;
441 
442             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
443             {
444                 aRetval.append(applyDefaultNormalsSphere(rCandidate.getB3DPolygon(a), rCenter));
445             }
446 
447             return aRetval;
448         }
449 
450         B3DPolyPolygon invertNormals( const B3DPolyPolygon& rCandidate)
451         {
452             B3DPolyPolygon aRetval;
453 
454             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
455             {
456                 aRetval.append(invertNormals(rCandidate.getB3DPolygon(a)));
457             }
458 
459             return aRetval;
460         }
461 
462         B3DPolyPolygon applyDefaultTextureCoordinatesParallel( const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bChangeX, bool bChangeY)
463         {
464             B3DPolyPolygon aRetval;
465 
466             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
467             {
468                 aRetval.append(applyDefaultTextureCoordinatesParallel(rCandidate.getB3DPolygon(a), rRange, bChangeX, bChangeY));
469             }
470 
471             return aRetval;
472         }
473 
474         B3DPolyPolygon applyDefaultTextureCoordinatesSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX, bool bChangeY)
475         {
476             B3DPolyPolygon aRetval;
477 
478             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
479             {
480                 aRetval.append(applyDefaultTextureCoordinatesSphere(rCandidate.getB3DPolygon(a), rCenter, bChangeX, bChangeY));
481             }
482 
483             return aRetval;
484         }
485 
486         bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder)
487         {
488             const sal_uInt32 nPolygonCount(rCandidate.count());
489 
490             if(1L == nPolygonCount)
491             {
492                 return isInside(rCandidate.getB3DPolygon(0), rPoint, bWithBorder);
493             }
494             else
495             {
496                 sal_Int32 nInsideCount(0);
497 
498                 for(sal_uInt32 a(0); a < nPolygonCount; a++)
499                 {
500                     const B3DPolygon aPolygon(rCandidate.getB3DPolygon(a));
501                     const bool bInside(isInside(aPolygon, rPoint, bWithBorder));
502 
503                     if(bInside)
504                     {
505                         nInsideCount++;
506                     }
507                 }
508 
509                 return (nInsideCount % 2L);
510             }
511         }
512 
513         // comparators with tolerance for 3D PolyPolygons
514 
515         bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB, const double& rfSmallValue)
516         {
517             const sal_uInt32 nPolygonCount(rCandidateA.count());
518 
519             if(nPolygonCount != rCandidateB.count())
520                 return false;
521 
522             for(sal_uInt32 a(0); a < nPolygonCount; a++)
523             {
524                 const B3DPolygon aCandidate(rCandidateA.getB3DPolygon(a));
525 
526                 if(!equal(aCandidate, rCandidateB.getB3DPolygon(a), rfSmallValue))
527                     return false;
528             }
529 
530             return true;
531         }
532 
533         bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB)
534         {
535             const double fSmallValue(fTools::getSmallValue());
536 
537             return equal(rCandidateA, rCandidateB, fSmallValue);
538         }
539 
540 // converters for com::sun::star::drawing::PolyPolygonShape3D
541         B3DPolyPolygon UnoPolyPolygonShape3DToB3DPolyPolygon(
542             const com::sun::star::drawing::PolyPolygonShape3D& rPolyPolygonShape3DSource,
543             bool bCheckClosed)
544         {
545             B3DPolyPolygon aRetval;
546             const sal_Int32 nOuterSequenceCount(rPolyPolygonShape3DSource.SequenceX.getLength());
547 
548             if(nOuterSequenceCount)
549             {
550                 OSL_ENSURE(nOuterSequenceCount == rPolyPolygonShape3DSource.SequenceY.getLength()
551                     && nOuterSequenceCount == rPolyPolygonShape3DSource.SequenceZ.getLength(),
552                     "UnoPolyPolygonShape3DToB3DPolygon: Not all double sequences have the same length (!)");
553 
554                 const com::sun::star::drawing::DoubleSequence* pInnerSequenceX = rPolyPolygonShape3DSource.SequenceX.getConstArray();
555                 const com::sun::star::drawing::DoubleSequence* pInnerSequenceY = rPolyPolygonShape3DSource.SequenceY.getConstArray();
556                 const com::sun::star::drawing::DoubleSequence* pInnerSequenceZ = rPolyPolygonShape3DSource.SequenceZ.getConstArray();
557 
558                 for(sal_Int32 a(0); a < nOuterSequenceCount; a++)
559                 {
560                     basegfx::B3DPolygon aNewPolygon;
561                     const sal_Int32 nInnerSequenceCount(pInnerSequenceX->getLength());
562                     OSL_ENSURE(nInnerSequenceCount == pInnerSequenceY->getLength()
563                         && nInnerSequenceCount == pInnerSequenceZ->getLength(),
564                         "UnoPolyPolygonShape3DToB3DPolygon: Not all double sequences have the same length (!)");
565 
566                     const double* pArrayX = pInnerSequenceX->getConstArray();
567                     const double* pArrayY = pInnerSequenceY->getConstArray();
568                     const double* pArrayZ = pInnerSequenceZ->getConstArray();
569 
570                     for(sal_Int32 b(0); b < nInnerSequenceCount; b++)
571                     {
572                         aNewPolygon.append(basegfx::B3DPoint(*pArrayX++,*pArrayY++,*pArrayZ++));
573                     }
574 
575                     pInnerSequenceX++;
576                     pInnerSequenceY++;
577                     pInnerSequenceZ++;
578 
579                     // #i101520# correction is needed for imported polygons of old format,
580                     // see callers
581                     if(bCheckClosed)
582                     {
583                         basegfx::tools::checkClosed(aNewPolygon);
584                     }
585 
586                     aRetval.append(aNewPolygon);
587                 }
588             }
589 
590             return aRetval;
591         }
592 
593         void B3DPolyPolygonToUnoPolyPolygonShape3D(
594             const B3DPolyPolygon& rPolyPolygonSource,
595             com::sun::star::drawing::PolyPolygonShape3D& rPolyPolygonShape3DRetval)
596         {
597             const sal_uInt32 nPolygonCount(rPolyPolygonSource.count());
598 
599             if(nPolygonCount)
600             {
601                 rPolyPolygonShape3DRetval.SequenceX.realloc(nPolygonCount);
602                 rPolyPolygonShape3DRetval.SequenceY.realloc(nPolygonCount);
603                 rPolyPolygonShape3DRetval.SequenceZ.realloc(nPolygonCount);
604 
605                 com::sun::star::drawing::DoubleSequence* pOuterSequenceX = rPolyPolygonShape3DRetval.SequenceX.getArray();
606                 com::sun::star::drawing::DoubleSequence* pOuterSequenceY = rPolyPolygonShape3DRetval.SequenceY.getArray();
607                 com::sun::star::drawing::DoubleSequence* pOuterSequenceZ = rPolyPolygonShape3DRetval.SequenceZ.getArray();
608 
609                 for(sal_uInt32 a(0); a < nPolygonCount; a++)
610                 {
611                     const basegfx::B3DPolygon aPoly(rPolyPolygonSource.getB3DPolygon(a));
612                     const sal_uInt32 nPointCount(aPoly.count());
613 
614                     if(nPointCount)
615                     {
616                         const bool bIsClosed(aPoly.isClosed());
617                         const sal_uInt32 nTargetCount(bIsClosed ? nPointCount + 1 : nPointCount);
618                         pOuterSequenceX->realloc(nTargetCount);
619                         pOuterSequenceY->realloc(nTargetCount);
620                         pOuterSequenceZ->realloc(nTargetCount);
621 
622                         double* pInnerSequenceX = pOuterSequenceX->getArray();
623                         double* pInnerSequenceY = pOuterSequenceY->getArray();
624                         double* pInnerSequenceZ = pOuterSequenceZ->getArray();
625 
626                         for(sal_uInt32 b(0); b < nPointCount; b++)
627                         {
628                             const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(b));
629 
630                             *pInnerSequenceX++ = aPoint.getX();
631                             *pInnerSequenceY++ = aPoint.getY();
632                             *pInnerSequenceZ++ = aPoint.getZ();
633                         }
634 
635                         if(bIsClosed)
636                         {
637                             const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(0));
638 
639                             *pInnerSequenceX++ = aPoint.getX();
640                             *pInnerSequenceY++ = aPoint.getY();
641                             *pInnerSequenceZ++ = aPoint.getZ();
642                         }
643                     }
644                     else
645                     {
646                         pOuterSequenceX->realloc(0);
647                         pOuterSequenceY->realloc(0);
648                         pOuterSequenceZ->realloc(0);
649                     }
650 
651                     pOuterSequenceX++;
652                     pOuterSequenceY++;
653                     pOuterSequenceZ++;
654                 }
655             }
656             else
657             {
658                 rPolyPolygonShape3DRetval.SequenceX.realloc(0);
659                 rPolyPolygonShape3DRetval.SequenceY.realloc(0);
660                 rPolyPolygonShape3DRetval.SequenceZ.realloc(0);
661             }
662         }
663 
664     } // end of namespace tools
665 } // end of namespace basegfx
666 
667 /* vim: set noet sw=4 ts=4: */
668