xref: /AOO41X/main/basegfx/source/polygon/b3dpolygon.cxx (revision 09dbbe930366fe6f99ae3b8ae1cf8690b638dbda)
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 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basegfx.hxx"
26 #include <osl/diagnose.h>
27 #include <basegfx/polygon/b3dpolygon.hxx>
28 #include <basegfx/point/b3dpoint.hxx>
29 #include <basegfx/matrix/b3dhommatrix.hxx>
30 #include <rtl/instance.hxx>
31 #include <basegfx/point/b2dpoint.hxx>
32 #include <basegfx/color/bcolor.hxx>
33 #include <basegfx/matrix/b2dhommatrix.hxx>
34 #include <vector>
35 #include <algorithm>
36 
37 //////////////////////////////////////////////////////////////////////////////
38 
39 class CoordinateData3D
40 {
41     basegfx::B3DPoint                               maPoint;
42 
43 public:
CoordinateData3D()44     CoordinateData3D()
45     :   maPoint()
46     {
47     }
48 
CoordinateData3D(const basegfx::B3DPoint & rData)49     explicit CoordinateData3D(const basegfx::B3DPoint& rData)
50     :   maPoint(rData)
51     {
52     }
53 
getCoordinate() const54     const basegfx::B3DPoint& getCoordinate() const
55     {
56         return maPoint;
57     }
58 
setCoordinate(const basegfx::B3DPoint & rValue)59     void setCoordinate(const basegfx::B3DPoint& rValue)
60     {
61         if(rValue != maPoint)
62             maPoint = rValue;
63     }
64 
operator ==(const CoordinateData3D & rData) const65     bool operator==(const CoordinateData3D& rData) const
66     {
67         return (maPoint == rData.getCoordinate());
68     }
69 
transform(const basegfx::B3DHomMatrix & rMatrix)70     void transform(const basegfx::B3DHomMatrix& rMatrix)
71     {
72         maPoint *= rMatrix;
73     }
74 };
75 
76 //////////////////////////////////////////////////////////////////////////////
77 
78 class CoordinateDataArray3D
79 {
80     typedef ::std::vector< CoordinateData3D > CoordinateData3DVector;
81 
82     CoordinateData3DVector                          maVector;
83 
84 public:
CoordinateDataArray3D(sal_uInt32 nCount)85     explicit CoordinateDataArray3D(sal_uInt32 nCount)
86     :   maVector(nCount)
87     {
88     }
89 
CoordinateDataArray3D(const CoordinateDataArray3D & rOriginal)90     explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal)
91     :   maVector(rOriginal.maVector)
92     {
93     }
94 
CoordinateDataArray3D(const CoordinateDataArray3D & rOriginal,sal_uInt32 nIndex,sal_uInt32 nCount)95     CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
96     :   maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
97     {
98     }
99 
~CoordinateDataArray3D()100     ~CoordinateDataArray3D()
101     {
102     }
103 
getNormal() const104     ::basegfx::B3DVector getNormal() const
105     {
106         ::basegfx::B3DVector aRetval;
107         const sal_uInt32 nPointCount(maVector.size());
108 
109         if(nPointCount > 2)
110         {
111             sal_uInt32 nISmallest(0);
112             sal_uInt32 a(0);
113             const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate());
114             const basegfx::B3DPoint* pNext(0);
115             const basegfx::B3DPoint* pPrev(0);
116 
117             // To guarantee a correctly oriented point, choose an outmost one
118             // which then cannot be concave
119             for(a = 1; a < nPointCount; a++)
120             {
121                 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
122 
123                 if((rCandidate.getX() < pSmallest->getX())
124                     || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY())
125                     || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ()))
126                 {
127                     nISmallest = a;
128                     pSmallest = &rCandidate;
129                 }
130             }
131 
132             // look for a next point different from minimal one
133             for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount)
134             {
135                 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
136 
137                 if(!rCandidate.equal(*pSmallest))
138                 {
139                     pNext = &rCandidate;
140                     break;
141                 }
142             }
143 
144             // look for a previous point different from minimal one
145             for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount)
146             {
147                 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
148 
149                 if(!rCandidate.equal(*pSmallest))
150                 {
151                     pPrev = &rCandidate;
152                     break;
153                 }
154             }
155 
156             // we always have a minimal point. If we also have a different next and previous,
157             // we can calculate the normal
158             if(pNext && pPrev)
159             {
160                 const basegfx::B3DVector aPrev(*pPrev - *pSmallest);
161                 const basegfx::B3DVector aNext(*pNext - *pSmallest);
162 
163                 aRetval = cross(aPrev, aNext);
164                 aRetval.normalize();
165             }
166         }
167 
168         return aRetval;
169     }
170 
count() const171     sal_uInt32 count() const
172     {
173         return maVector.size();
174     }
175 
operator ==(const CoordinateDataArray3D & rCandidate) const176     bool operator==(const CoordinateDataArray3D& rCandidate) const
177     {
178         return (maVector == rCandidate.maVector);
179     }
180 
getCoordinate(sal_uInt32 nIndex) const181     const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const
182     {
183         return maVector[nIndex].getCoordinate();
184     }
185 
setCoordinate(sal_uInt32 nIndex,const basegfx::B3DPoint & rValue)186     void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
187     {
188         maVector[nIndex].setCoordinate(rValue);
189     }
190 
insert(sal_uInt32 nIndex,const CoordinateData3D & rValue,sal_uInt32 nCount)191     void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount)
192     {
193         if(nCount)
194         {
195             // add nCount copies of rValue
196             CoordinateData3DVector::iterator aIndex(maVector.begin());
197             aIndex += nIndex;
198             maVector.insert(aIndex, nCount, rValue);
199         }
200     }
201 
insert(sal_uInt32 nIndex,const CoordinateDataArray3D & rSource)202     void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource)
203     {
204         const sal_uInt32 nCount(rSource.maVector.size());
205 
206         if(nCount)
207         {
208             // insert data
209             CoordinateData3DVector::iterator aIndex(maVector.begin());
210             aIndex += nIndex;
211             CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin());
212             CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end());
213             maVector.insert(aIndex, aStart, aEnd);
214         }
215     }
216 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)217     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
218     {
219         if(nCount)
220         {
221             // remove point data
222             CoordinateData3DVector::iterator aStart(maVector.begin());
223             aStart += nIndex;
224             const CoordinateData3DVector::iterator aEnd(aStart + nCount);
225             maVector.erase(aStart, aEnd);
226         }
227     }
228 
flip()229     void flip()
230     {
231         if(maVector.size() > 1)
232         {
233             const sal_uInt32 nHalfSize(maVector.size() >> 1L);
234             CoordinateData3DVector::iterator aStart(maVector.begin());
235             CoordinateData3DVector::iterator aEnd(maVector.end() - 1L);
236 
237             for(sal_uInt32 a(0); a < nHalfSize; a++)
238             {
239                 ::std::swap(*aStart, *aEnd);
240                 aStart++;
241                 aEnd--;
242             }
243         }
244     }
245 
transform(const::basegfx::B3DHomMatrix & rMatrix)246     void transform(const ::basegfx::B3DHomMatrix& rMatrix)
247     {
248         CoordinateData3DVector::iterator aStart(maVector.begin());
249         CoordinateData3DVector::iterator aEnd(maVector.end());
250 
251         for(; aStart != aEnd; aStart++)
252         {
253             aStart->transform(rMatrix);
254         }
255     }
256 };
257 
258 //////////////////////////////////////////////////////////////////////////////
259 
260 class BColorArray
261 {
262     typedef ::std::vector< ::basegfx::BColor > BColorDataVector;
263 
264     BColorDataVector                                    maVector;
265     sal_uInt32                                          mnUsedEntries;
266 
267 public:
BColorArray(sal_uInt32 nCount)268     explicit BColorArray(sal_uInt32 nCount)
269     :   maVector(nCount),
270         mnUsedEntries(0L)
271     {
272     }
273 
BColorArray(const BColorArray & rOriginal)274     explicit BColorArray(const BColorArray& rOriginal)
275     :   maVector(rOriginal.maVector),
276         mnUsedEntries(rOriginal.mnUsedEntries)
277     {
278     }
279 
BColorArray(const BColorArray & rOriginal,sal_uInt32 nIndex,sal_uInt32 nCount)280     BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
281     :   maVector(),
282         mnUsedEntries(0L)
283     {
284         BColorDataVector::const_iterator aStart(rOriginal.maVector.begin());
285         aStart += nIndex;
286         BColorDataVector::const_iterator aEnd(aStart);
287         aEnd += nCount;
288         maVector.reserve(nCount);
289 
290         for(; aStart != aEnd; aStart++)
291         {
292             if(!aStart->equalZero())
293                 mnUsedEntries++;
294 
295             maVector.push_back(*aStart);
296         }
297     }
298 
~BColorArray()299     ~BColorArray()
300     {
301     }
302 
count() const303     sal_uInt32 count() const
304     {
305         return maVector.size();
306     }
307 
operator ==(const BColorArray & rCandidate) const308     bool operator==(const BColorArray& rCandidate) const
309     {
310         return (maVector == rCandidate.maVector);
311     }
312 
isUsed() const313     bool isUsed() const
314     {
315         return (0L != mnUsedEntries);
316     }
317 
getBColor(sal_uInt32 nIndex) const318     const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
319     {
320         return maVector[nIndex];
321     }
322 
setBColor(sal_uInt32 nIndex,const::basegfx::BColor & rValue)323     void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
324     {
325         bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
326         bool bIsUsed(!rValue.equalZero());
327 
328         if(bWasUsed)
329         {
330             if(bIsUsed)
331             {
332                 maVector[nIndex] = rValue;
333             }
334             else
335             {
336                 maVector[nIndex] = ::basegfx::BColor::getEmptyBColor();
337                 mnUsedEntries--;
338             }
339         }
340         else
341         {
342             if(bIsUsed)
343             {
344                 maVector[nIndex] = rValue;
345                 mnUsedEntries++;
346             }
347         }
348     }
349 
insert(sal_uInt32 nIndex,const::basegfx::BColor & rValue,sal_uInt32 nCount)350     void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount)
351     {
352         if(nCount)
353         {
354             // add nCount copies of rValue
355             BColorDataVector::iterator aIndex(maVector.begin());
356             aIndex += nIndex;
357             maVector.insert(aIndex, nCount, rValue);
358 
359             if(!rValue.equalZero())
360                 mnUsedEntries += nCount;
361         }
362     }
363 
insert(sal_uInt32 nIndex,const BColorArray & rSource)364     void insert(sal_uInt32 nIndex, const BColorArray& rSource)
365     {
366         const sal_uInt32 nCount(rSource.maVector.size());
367 
368         if(nCount)
369         {
370             // insert data
371             BColorDataVector::iterator aIndex(maVector.begin());
372             aIndex += nIndex;
373             BColorDataVector::const_iterator aStart(rSource.maVector.begin());
374             BColorDataVector::const_iterator aEnd(rSource.maVector.end());
375             maVector.insert(aIndex, aStart, aEnd);
376 
377             for(; aStart != aEnd; aStart++)
378             {
379                 if(!aStart->equalZero())
380                     mnUsedEntries++;
381             }
382         }
383     }
384 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)385     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
386     {
387         if(nCount)
388         {
389             const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex);
390             const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount);
391             BColorDataVector::const_iterator aStart(aDeleteStart);
392 
393             for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
394             {
395                 if(!aStart->equalZero())
396                     mnUsedEntries--;
397             }
398 
399             // remove point data
400             maVector.erase(aDeleteStart, aDeleteEnd);
401         }
402     }
403 
flip()404     void flip()
405     {
406         if(maVector.size() > 1)
407         {
408             const sal_uInt32 nHalfSize(maVector.size() >> 1L);
409             BColorDataVector::iterator aStart(maVector.begin());
410             BColorDataVector::iterator aEnd(maVector.end() - 1L);
411 
412             for(sal_uInt32 a(0); a < nHalfSize; a++)
413             {
414                 ::std::swap(*aStart, *aEnd);
415                 aStart++;
416                 aEnd--;
417             }
418         }
419     }
420 };
421 
422 //////////////////////////////////////////////////////////////////////////////
423 
424 class NormalsArray3D
425 {
426     typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector;
427 
428     NormalsData3DVector                                 maVector;
429     sal_uInt32                                          mnUsedEntries;
430 
431 public:
NormalsArray3D(sal_uInt32 nCount)432     explicit NormalsArray3D(sal_uInt32 nCount)
433     :   maVector(nCount),
434         mnUsedEntries(0L)
435     {
436     }
437 
NormalsArray3D(const NormalsArray3D & rOriginal)438     explicit NormalsArray3D(const NormalsArray3D& rOriginal)
439     :   maVector(rOriginal.maVector),
440         mnUsedEntries(rOriginal.mnUsedEntries)
441     {
442     }
443 
NormalsArray3D(const NormalsArray3D & rOriginal,sal_uInt32 nIndex,sal_uInt32 nCount)444     NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
445     :   maVector(),
446         mnUsedEntries(0L)
447     {
448         NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin());
449         aStart += nIndex;
450         NormalsData3DVector::const_iterator aEnd(aStart);
451         aEnd += nCount;
452         maVector.reserve(nCount);
453 
454         for(; aStart != aEnd; aStart++)
455         {
456             if(!aStart->equalZero())
457                 mnUsedEntries++;
458 
459             maVector.push_back(*aStart);
460         }
461     }
462 
~NormalsArray3D()463     ~NormalsArray3D()
464     {
465     }
466 
count() const467     sal_uInt32 count() const
468     {
469         return maVector.size();
470     }
471 
operator ==(const NormalsArray3D & rCandidate) const472     bool operator==(const NormalsArray3D& rCandidate) const
473     {
474         return (maVector == rCandidate.maVector);
475     }
476 
isUsed() const477     bool isUsed() const
478     {
479         return (0L != mnUsedEntries);
480     }
481 
getNormal(sal_uInt32 nIndex) const482     const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
483     {
484         return maVector[nIndex];
485     }
486 
setNormal(sal_uInt32 nIndex,const::basegfx::B3DVector & rValue)487     void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
488     {
489         bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
490         bool bIsUsed(!rValue.equalZero());
491 
492         if(bWasUsed)
493         {
494             if(bIsUsed)
495             {
496                 maVector[nIndex] = rValue;
497             }
498             else
499             {
500                 maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector();
501                 mnUsedEntries--;
502             }
503         }
504         else
505         {
506             if(bIsUsed)
507             {
508                 maVector[nIndex] = rValue;
509                 mnUsedEntries++;
510             }
511         }
512     }
513 
insert(sal_uInt32 nIndex,const::basegfx::B3DVector & rValue,sal_uInt32 nCount)514     void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount)
515     {
516         if(nCount)
517         {
518             // add nCount copies of rValue
519             NormalsData3DVector::iterator aIndex(maVector.begin());
520             aIndex += nIndex;
521             maVector.insert(aIndex, nCount, rValue);
522 
523             if(!rValue.equalZero())
524                 mnUsedEntries += nCount;
525         }
526     }
527 
insert(sal_uInt32 nIndex,const NormalsArray3D & rSource)528     void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource)
529     {
530         const sal_uInt32 nCount(rSource.maVector.size());
531 
532         if(nCount)
533         {
534             // insert data
535             NormalsData3DVector::iterator aIndex(maVector.begin());
536             aIndex += nIndex;
537             NormalsData3DVector::const_iterator aStart(rSource.maVector.begin());
538             NormalsData3DVector::const_iterator aEnd(rSource.maVector.end());
539             maVector.insert(aIndex, aStart, aEnd);
540 
541             for(; aStart != aEnd; aStart++)
542             {
543                 if(!aStart->equalZero())
544                     mnUsedEntries++;
545             }
546         }
547     }
548 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)549     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
550     {
551         if(nCount)
552         {
553             const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex);
554             const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount);
555             NormalsData3DVector::const_iterator aStart(aDeleteStart);
556 
557             for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
558             {
559                 if(!aStart->equalZero())
560                     mnUsedEntries--;
561             }
562 
563             // remove point data
564             maVector.erase(aDeleteStart, aDeleteEnd);
565         }
566     }
567 
flip()568     void flip()
569     {
570         if(maVector.size() > 1)
571         {
572             const sal_uInt32 nHalfSize(maVector.size() >> 1L);
573             NormalsData3DVector::iterator aStart(maVector.begin());
574             NormalsData3DVector::iterator aEnd(maVector.end() - 1L);
575 
576             for(sal_uInt32 a(0); a < nHalfSize; a++)
577             {
578                 ::std::swap(*aStart, *aEnd);
579                 aStart++;
580                 aEnd--;
581             }
582         }
583     }
584 
transform(const basegfx::B3DHomMatrix & rMatrix)585     void transform(const basegfx::B3DHomMatrix& rMatrix)
586     {
587         NormalsData3DVector::iterator aStart(maVector.begin());
588         NormalsData3DVector::iterator aEnd(maVector.end());
589 
590         for(; aStart != aEnd; aStart++)
591         {
592             (*aStart) *= rMatrix;
593         }
594     }
595 };
596 
597 //////////////////////////////////////////////////////////////////////////////
598 
599 class TextureCoordinate2D
600 {
601     typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector;
602 
603     TextureData2DVector                                 maVector;
604     sal_uInt32                                          mnUsedEntries;
605 
606 public:
TextureCoordinate2D(sal_uInt32 nCount)607     explicit TextureCoordinate2D(sal_uInt32 nCount)
608     :   maVector(nCount),
609         mnUsedEntries(0L)
610     {
611     }
612 
TextureCoordinate2D(const TextureCoordinate2D & rOriginal)613     explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal)
614     :   maVector(rOriginal.maVector),
615         mnUsedEntries(rOriginal.mnUsedEntries)
616     {
617     }
618 
TextureCoordinate2D(const TextureCoordinate2D & rOriginal,sal_uInt32 nIndex,sal_uInt32 nCount)619     TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
620     :   maVector(),
621         mnUsedEntries(0L)
622     {
623         TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin());
624         aStart += nIndex;
625         TextureData2DVector::const_iterator aEnd(aStart);
626         aEnd += nCount;
627         maVector.reserve(nCount);
628 
629         for(; aStart != aEnd; aStart++)
630         {
631             if(!aStart->equalZero())
632                 mnUsedEntries++;
633 
634             maVector.push_back(*aStart);
635         }
636     }
637 
~TextureCoordinate2D()638     ~TextureCoordinate2D()
639     {
640     }
641 
count() const642     sal_uInt32 count() const
643     {
644         return maVector.size();
645     }
646 
operator ==(const TextureCoordinate2D & rCandidate) const647     bool operator==(const TextureCoordinate2D& rCandidate) const
648     {
649         return (maVector == rCandidate.maVector);
650     }
651 
isUsed() const652     bool isUsed() const
653     {
654         return (0L != mnUsedEntries);
655     }
656 
getTextureCoordinate(sal_uInt32 nIndex) const657     const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
658     {
659         return maVector[nIndex];
660     }
661 
setTextureCoordinate(sal_uInt32 nIndex,const::basegfx::B2DPoint & rValue)662     void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
663     {
664         bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
665         bool bIsUsed(!rValue.equalZero());
666 
667         if(bWasUsed)
668         {
669             if(bIsUsed)
670             {
671                 maVector[nIndex] = rValue;
672             }
673             else
674             {
675                 maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint();
676                 mnUsedEntries--;
677             }
678         }
679         else
680         {
681             if(bIsUsed)
682             {
683                 maVector[nIndex] = rValue;
684                 mnUsedEntries++;
685             }
686         }
687     }
688 
insert(sal_uInt32 nIndex,const::basegfx::B2DPoint & rValue,sal_uInt32 nCount)689     void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount)
690     {
691         if(nCount)
692         {
693             // add nCount copies of rValue
694             TextureData2DVector::iterator aIndex(maVector.begin());
695             aIndex += nIndex;
696             maVector.insert(aIndex, nCount, rValue);
697 
698             if(!rValue.equalZero())
699                 mnUsedEntries += nCount;
700         }
701     }
702 
insert(sal_uInt32 nIndex,const TextureCoordinate2D & rSource)703     void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource)
704     {
705         const sal_uInt32 nCount(rSource.maVector.size());
706 
707         if(nCount)
708         {
709             // insert data
710             TextureData2DVector::iterator aIndex(maVector.begin());
711             aIndex += nIndex;
712             TextureData2DVector::const_iterator aStart(rSource.maVector.begin());
713             TextureData2DVector::const_iterator aEnd(rSource.maVector.end());
714             maVector.insert(aIndex, aStart, aEnd);
715 
716             for(; aStart != aEnd; aStart++)
717             {
718                 if(!aStart->equalZero())
719                     mnUsedEntries++;
720             }
721         }
722     }
723 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)724     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
725     {
726         if(nCount)
727         {
728             const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
729             const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
730             TextureData2DVector::const_iterator aStart(aDeleteStart);
731 
732             for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
733             {
734                 if(!aStart->equalZero())
735                     mnUsedEntries--;
736             }
737 
738             // remove point data
739             maVector.erase(aDeleteStart, aDeleteEnd);
740         }
741     }
742 
flip()743     void flip()
744     {
745         if(maVector.size() > 1)
746         {
747             const sal_uInt32 nHalfSize(maVector.size() >> 1L);
748             TextureData2DVector::iterator aStart(maVector.begin());
749             TextureData2DVector::iterator aEnd(maVector.end() - 1L);
750 
751             for(sal_uInt32 a(0); a < nHalfSize; a++)
752             {
753                 ::std::swap(*aStart, *aEnd);
754                 aStart++;
755                 aEnd--;
756             }
757         }
758     }
759 
transform(const::basegfx::B2DHomMatrix & rMatrix)760     void transform(const ::basegfx::B2DHomMatrix& rMatrix)
761     {
762         TextureData2DVector::iterator aStart(maVector.begin());
763         TextureData2DVector::iterator aEnd(maVector.end());
764 
765         for(; aStart != aEnd; aStart++)
766         {
767             (*aStart) *= rMatrix;
768         }
769     }
770 };
771 
772 //////////////////////////////////////////////////////////////////////////////
773 
774 class ImplB3DPolygon
775 {
776     // The point vector. This vector exists always and defines the
777     // count of members.
778     CoordinateDataArray3D                           maPoints;
779 
780     // The BColor vector. This vectors are created on demand
781     // and may be zero.
782     BColorArray*                                    mpBColors;
783 
784     // The Normals vector. This vectors are created on demand
785     // and may be zero.
786     NormalsArray3D*                                 mpNormals;
787 
788     // The TextureCoordinates vector. This vectors are created on demand
789     // and may be zero.
790     TextureCoordinate2D*                            mpTextureCoordiantes;
791 
792     // The calculated plane normal. mbPlaneNormalValid says if it's valid.
793     ::basegfx::B3DVector                            maPlaneNormal;
794 
795     // bitfield
796     // flag which decides if this polygon is opened or closed
797     unsigned                                        mbIsClosed : 1;
798 
799     // flag which says if maPlaneNormal is up-to-date
800     unsigned                                        mbPlaneNormalValid : 1;
801 
802 protected:
invalidatePlaneNormal()803     void invalidatePlaneNormal()
804     {
805         if(mbPlaneNormalValid)
806         {
807             mbPlaneNormalValid = false;
808         }
809     }
810 
811 public:
812     // This constructor is only used from the static identity polygon, thus
813     // the RefCount is set to 1 to never 'delete' this static incarnation.
ImplB3DPolygon()814     ImplB3DPolygon()
815     :   maPoints(0L),
816         mpBColors(0L),
817         mpNormals(0L),
818         mpTextureCoordiantes(0L),
819         maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
820         mbIsClosed(false),
821         mbPlaneNormalValid(true)
822     {
823         // complete initialization with defaults
824     }
825 
ImplB3DPolygon(const ImplB3DPolygon & rToBeCopied)826     ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied)
827     :   maPoints(rToBeCopied.maPoints),
828         mpBColors(0L),
829         mpNormals(0L),
830         mpTextureCoordiantes(0L),
831         maPlaneNormal(rToBeCopied.maPlaneNormal),
832         mbIsClosed(rToBeCopied.mbIsClosed),
833         mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid)
834     {
835         // complete initialization using copy
836         if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
837         {
838             mpBColors = new BColorArray(*rToBeCopied.mpBColors);
839         }
840 
841         if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
842         {
843             mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals);
844         }
845 
846         if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
847         {
848             mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes);
849         }
850     }
851 
ImplB3DPolygon(const ImplB3DPolygon & rToBeCopied,sal_uInt32 nIndex,sal_uInt32 nCount)852     ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
853     :   maPoints(rToBeCopied.maPoints, nIndex, nCount),
854         mpBColors(0L),
855         mpNormals(0L),
856         mpTextureCoordiantes(0L),
857         maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
858         mbIsClosed(rToBeCopied.mbIsClosed),
859         mbPlaneNormalValid(false)
860     {
861         // complete initialization using partly copy
862         if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
863         {
864             mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount);
865 
866             if(!mpBColors->isUsed())
867             {
868                 delete mpBColors;
869                 mpBColors = 0L;
870             }
871         }
872 
873         if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
874         {
875             mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount);
876 
877             if(!mpNormals->isUsed())
878             {
879                 delete mpNormals;
880                 mpNormals = 0L;
881             }
882         }
883 
884         if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
885         {
886             mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount);
887 
888             if(!mpTextureCoordiantes->isUsed())
889             {
890                 delete mpTextureCoordiantes;
891                 mpTextureCoordiantes = 0L;
892             }
893         }
894     }
895 
~ImplB3DPolygon()896     ~ImplB3DPolygon()
897     {
898         if(mpBColors)
899         {
900             delete mpBColors;
901             mpBColors = 0L;
902         }
903 
904         if(mpNormals)
905         {
906             delete mpNormals;
907             mpNormals = 0L;
908         }
909 
910         if(mpTextureCoordiantes)
911         {
912             delete mpTextureCoordiantes;
913             mpTextureCoordiantes = 0L;
914         }
915     }
916 
count() const917     sal_uInt32 count() const
918     {
919         return maPoints.count();
920     }
921 
isClosed() const922     bool isClosed() const
923     {
924         return mbIsClosed;
925     }
926 
setClosed(bool bNew)927     void setClosed(bool bNew)
928     {
929         if(bNew != (bool)mbIsClosed)
930         {
931             mbIsClosed = bNew;
932         }
933     }
934 
impBColorsAreEqual(const ImplB3DPolygon & rCandidate) const935     inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const
936     {
937         bool bBColorsAreEqual(true);
938 
939         if(mpBColors)
940         {
941             if(rCandidate.mpBColors)
942             {
943                 bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors);
944             }
945             else
946             {
947                 // candidate has no BColors, so it's assumed all unused.
948                 bBColorsAreEqual = !mpBColors->isUsed();
949             }
950         }
951         else
952         {
953             if(rCandidate.mpBColors)
954             {
955                 // we have no TextureCoordiantes, so it's assumed all unused.
956                 bBColorsAreEqual = !rCandidate.mpBColors->isUsed();
957             }
958         }
959 
960         return bBColorsAreEqual;
961     }
962 
impNormalsAreEqual(const ImplB3DPolygon & rCandidate) const963     inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const
964     {
965         bool bNormalsAreEqual(true);
966 
967         if(mpNormals)
968         {
969             if(rCandidate.mpNormals)
970             {
971                 bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals);
972             }
973             else
974             {
975                 // candidate has no normals, so it's assumed all unused.
976                 bNormalsAreEqual = !mpNormals->isUsed();
977             }
978         }
979         else
980         {
981             if(rCandidate.mpNormals)
982             {
983                 // we have no normals, so it's assumed all unused.
984                 bNormalsAreEqual = !rCandidate.mpNormals->isUsed();
985             }
986         }
987 
988         return bNormalsAreEqual;
989     }
990 
impTextureCoordinatesAreEqual(const ImplB3DPolygon & rCandidate) const991     inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const
992     {
993         bool bTextureCoordinatesAreEqual(true);
994 
995         if(mpTextureCoordiantes)
996         {
997             if(rCandidate.mpTextureCoordiantes)
998             {
999                 bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes);
1000             }
1001             else
1002             {
1003                 // candidate has no TextureCoordinates, so it's assumed all unused.
1004                 bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed();
1005             }
1006         }
1007         else
1008         {
1009             if(rCandidate.mpTextureCoordiantes)
1010             {
1011                 // we have no TextureCoordiantes, so it's assumed all unused.
1012                 bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed();
1013             }
1014         }
1015 
1016         return bTextureCoordinatesAreEqual;
1017     }
1018 
operator ==(const ImplB3DPolygon & rCandidate) const1019     bool operator==(const ImplB3DPolygon& rCandidate) const
1020     {
1021         if(mbIsClosed == rCandidate.mbIsClosed)
1022         {
1023             if(maPoints == rCandidate.maPoints)
1024             {
1025                 if(impBColorsAreEqual(rCandidate))
1026                 {
1027                     if(impNormalsAreEqual(rCandidate))
1028                     {
1029                         if(impTextureCoordinatesAreEqual(rCandidate))
1030                         {
1031                             return true;
1032                         }
1033                     }
1034                 }
1035             }
1036         }
1037 
1038         return false;
1039     }
1040 
getPoint(sal_uInt32 nIndex) const1041     const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const
1042     {
1043         return maPoints.getCoordinate(nIndex);
1044     }
1045 
setPoint(sal_uInt32 nIndex,const::basegfx::B3DPoint & rValue)1046     void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue)
1047     {
1048         maPoints.setCoordinate(nIndex, rValue);
1049         invalidatePlaneNormal();
1050     }
1051 
insert(sal_uInt32 nIndex,const::basegfx::B3DPoint & rPoint,sal_uInt32 nCount)1052     void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1053     {
1054         if(nCount)
1055         {
1056             CoordinateData3D aCoordinate(rPoint);
1057             maPoints.insert(nIndex, aCoordinate, nCount);
1058             invalidatePlaneNormal();
1059 
1060             if(mpBColors)
1061             {
1062                 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1063             }
1064 
1065             if(mpNormals)
1066             {
1067                 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1068             }
1069 
1070             if(mpTextureCoordiantes)
1071             {
1072                 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1073             }
1074         }
1075     }
1076 
getBColor(sal_uInt32 nIndex) const1077     const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
1078     {
1079         if(mpBColors)
1080         {
1081             return mpBColors->getBColor(nIndex);
1082         }
1083         else
1084         {
1085             return ::basegfx::BColor::getEmptyBColor();
1086         }
1087     }
1088 
setBColor(sal_uInt32 nIndex,const::basegfx::BColor & rValue)1089     void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
1090     {
1091         if(!mpBColors)
1092         {
1093             if(!rValue.equalZero())
1094             {
1095                 mpBColors = new BColorArray(maPoints.count());
1096                 mpBColors->setBColor(nIndex, rValue);
1097             }
1098         }
1099         else
1100         {
1101             mpBColors->setBColor(nIndex, rValue);
1102 
1103             if(!mpBColors->isUsed())
1104             {
1105                 delete mpBColors;
1106                 mpBColors = 0L;
1107             }
1108         }
1109     }
1110 
areBColorsUsed() const1111     bool areBColorsUsed() const
1112     {
1113         return (mpBColors && mpBColors->isUsed());
1114     }
1115 
clearBColors()1116     void clearBColors()
1117     {
1118         if(mpBColors)
1119         {
1120             delete mpBColors;
1121             mpBColors = 0L;
1122         }
1123     }
1124 
getNormal() const1125     const ::basegfx::B3DVector& getNormal() const
1126     {
1127         if(!mbPlaneNormalValid)
1128         {
1129             const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal();
1130             const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true;
1131         }
1132 
1133         return maPlaneNormal;
1134     }
1135 
getNormal(sal_uInt32 nIndex) const1136     const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
1137     {
1138         if(mpNormals)
1139         {
1140             return mpNormals->getNormal(nIndex);
1141         }
1142         else
1143         {
1144             return ::basegfx::B3DVector::getEmptyVector();
1145         }
1146     }
1147 
setNormal(sal_uInt32 nIndex,const::basegfx::B3DVector & rValue)1148     void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
1149     {
1150         if(!mpNormals)
1151         {
1152             if(!rValue.equalZero())
1153             {
1154                 mpNormals = new NormalsArray3D(maPoints.count());
1155                 mpNormals->setNormal(nIndex, rValue);
1156             }
1157         }
1158         else
1159         {
1160             mpNormals->setNormal(nIndex, rValue);
1161 
1162             if(!mpNormals->isUsed())
1163             {
1164                 delete mpNormals;
1165                 mpNormals = 0L;
1166             }
1167         }
1168     }
1169 
transformNormals(const::basegfx::B3DHomMatrix & rMatrix)1170     void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
1171     {
1172         if(mpNormals)
1173         {
1174             mpNormals->transform(rMatrix);
1175         }
1176     }
1177 
areNormalsUsed() const1178     bool areNormalsUsed() const
1179     {
1180         return (mpNormals && mpNormals->isUsed());
1181     }
1182 
clearNormals()1183     void clearNormals()
1184     {
1185         if(mpNormals)
1186         {
1187             delete mpNormals;
1188             mpNormals = 0L;
1189         }
1190     }
1191 
getTextureCoordinate(sal_uInt32 nIndex) const1192     const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
1193     {
1194         if(mpTextureCoordiantes)
1195         {
1196             return mpTextureCoordiantes->getTextureCoordinate(nIndex);
1197         }
1198         else
1199         {
1200             return ::basegfx::B2DPoint::getEmptyPoint();
1201         }
1202     }
1203 
setTextureCoordinate(sal_uInt32 nIndex,const::basegfx::B2DPoint & rValue)1204     void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
1205     {
1206         if(!mpTextureCoordiantes)
1207         {
1208             if(!rValue.equalZero())
1209             {
1210                 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1211                 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1212             }
1213         }
1214         else
1215         {
1216             mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1217 
1218             if(!mpTextureCoordiantes->isUsed())
1219             {
1220                 delete mpTextureCoordiantes;
1221                 mpTextureCoordiantes = 0L;
1222             }
1223         }
1224     }
1225 
areTextureCoordinatesUsed() const1226     bool areTextureCoordinatesUsed() const
1227     {
1228         return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed());
1229     }
1230 
clearTextureCoordinates()1231     void clearTextureCoordinates()
1232     {
1233         if(mpTextureCoordiantes)
1234         {
1235             delete mpTextureCoordiantes;
1236             mpTextureCoordiantes = 0L;
1237         }
1238     }
1239 
transformTextureCoordinates(const::basegfx::B2DHomMatrix & rMatrix)1240     void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
1241     {
1242         if(mpTextureCoordiantes)
1243         {
1244             mpTextureCoordiantes->transform(rMatrix);
1245         }
1246     }
1247 
insert(sal_uInt32 nIndex,const ImplB3DPolygon & rSource)1248     void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource)
1249     {
1250         const sal_uInt32 nCount(rSource.maPoints.count());
1251 
1252         if(nCount)
1253         {
1254             maPoints.insert(nIndex, rSource.maPoints);
1255             invalidatePlaneNormal();
1256 
1257             if(rSource.mpBColors && rSource.mpBColors->isUsed())
1258             {
1259                 if(!mpBColors)
1260                 {
1261                     mpBColors = new BColorArray(maPoints.count());
1262                 }
1263 
1264                 mpBColors->insert(nIndex, *rSource.mpBColors);
1265             }
1266             else
1267             {
1268                 if(mpBColors)
1269                 {
1270                     mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1271                 }
1272             }
1273 
1274             if(rSource.mpNormals && rSource.mpNormals->isUsed())
1275             {
1276                 if(!mpNormals)
1277                 {
1278                     mpNormals = new NormalsArray3D(maPoints.count());
1279                 }
1280 
1281                 mpNormals->insert(nIndex, *rSource.mpNormals);
1282             }
1283             else
1284             {
1285                 if(mpNormals)
1286                 {
1287                     mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1288                 }
1289             }
1290 
1291             if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed())
1292             {
1293                 if(!mpTextureCoordiantes)
1294                 {
1295                     mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1296                 }
1297 
1298                 mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes);
1299             }
1300             else
1301             {
1302                 if(mpTextureCoordiantes)
1303                 {
1304                     mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1305                 }
1306             }
1307         }
1308     }
1309 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)1310     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1311     {
1312         if(nCount)
1313         {
1314             maPoints.remove(nIndex, nCount);
1315             invalidatePlaneNormal();
1316 
1317             if(mpBColors)
1318             {
1319                 mpBColors->remove(nIndex, nCount);
1320 
1321                 if(!mpBColors->isUsed())
1322                 {
1323                     delete mpBColors;
1324                     mpBColors = 0L;
1325                 }
1326             }
1327 
1328             if(mpNormals)
1329             {
1330                 mpNormals->remove(nIndex, nCount);
1331 
1332                 if(!mpNormals->isUsed())
1333                 {
1334                     delete mpNormals;
1335                     mpNormals = 0L;
1336                 }
1337             }
1338 
1339             if(mpTextureCoordiantes)
1340             {
1341                 mpTextureCoordiantes->remove(nIndex, nCount);
1342 
1343                 if(!mpTextureCoordiantes->isUsed())
1344                 {
1345                     delete mpTextureCoordiantes;
1346                     mpTextureCoordiantes = 0L;
1347                 }
1348             }
1349         }
1350     }
1351 
flip()1352     void flip()
1353     {
1354         if(maPoints.count() > 1)
1355         {
1356             maPoints.flip();
1357 
1358             if(mbPlaneNormalValid)
1359             {
1360                 // mirror plane normal
1361                 maPlaneNormal = -maPlaneNormal;
1362             }
1363 
1364             if(mpBColors)
1365             {
1366                 mpBColors->flip();
1367             }
1368 
1369             if(mpNormals)
1370             {
1371                 mpNormals->flip();
1372             }
1373 
1374             if(mpTextureCoordiantes)
1375             {
1376                 mpTextureCoordiantes->flip();
1377             }
1378         }
1379     }
1380 
hasDoublePoints() const1381     bool hasDoublePoints() const
1382     {
1383         if(mbIsClosed)
1384         {
1385             // check for same start and end point
1386             const sal_uInt32 nIndex(maPoints.count() - 1L);
1387 
1388             if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex))
1389             {
1390                 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)));
1391 
1392                 if(bBColorEqual)
1393                 {
1394                     const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)));
1395 
1396                     if(bNormalsEqual)
1397                     {
1398                         const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)));
1399 
1400                         if(bTextureCoordinatesEqual)
1401                         {
1402                             return true;
1403                         }
1404                     }
1405                 }
1406             }
1407         }
1408 
1409         // test for range
1410         for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++)
1411         {
1412             if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L))
1413             {
1414                 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L)));
1415 
1416                 if(bBColorEqual)
1417                 {
1418                     const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L)));
1419 
1420                     if(bNormalsEqual)
1421                     {
1422                         const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L)));
1423 
1424                         if(bTextureCoordinatesEqual)
1425                         {
1426                             return true;
1427                         }
1428                     }
1429                 }
1430             }
1431         }
1432 
1433         return false;
1434     }
1435 
removeDoublePointsAtBeginEnd()1436     void removeDoublePointsAtBeginEnd()
1437     {
1438         // Only remove DoublePoints at Begin and End when poly is closed
1439         if(mbIsClosed)
1440         {
1441             bool bRemove;
1442 
1443             do
1444             {
1445                 bRemove = false;
1446 
1447                 if(maPoints.count() > 1L)
1448                 {
1449                     const sal_uInt32 nIndex(maPoints.count() - 1L);
1450                     bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex));
1451 
1452                     if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)))
1453                     {
1454                         bRemove = false;
1455                     }
1456 
1457                     if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)))
1458                     {
1459                         bRemove = false;
1460                     }
1461 
1462                     if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)))
1463                     {
1464                         bRemove = false;
1465                     }
1466                 }
1467 
1468                 if(bRemove)
1469                 {
1470                     const sal_uInt32 nIndex(maPoints.count() - 1L);
1471                     remove(nIndex, 1L);
1472                 }
1473             } while(bRemove);
1474         }
1475     }
1476 
removeDoublePointsWholeTrack()1477     void removeDoublePointsWholeTrack()
1478     {
1479         sal_uInt32 nIndex(0L);
1480 
1481         // test as long as there are at least two points and as long as the index
1482         // is smaller or equal second last point
1483         while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L))
1484         {
1485             const sal_uInt32 nNextIndex(nIndex + 1L);
1486             bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex));
1487 
1488             if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex)))
1489             {
1490                 bRemove = false;
1491             }
1492 
1493             if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex)))
1494             {
1495                 bRemove = false;
1496             }
1497 
1498             if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex)))
1499             {
1500                 bRemove = false;
1501             }
1502 
1503             if(bRemove)
1504             {
1505                 // if next is same as index and the control vectors are unused, delete index
1506                 remove(nIndex, 1L);
1507             }
1508             else
1509             {
1510                 // if different, step forward
1511                 nIndex++;
1512             }
1513         }
1514     }
1515 
transform(const::basegfx::B3DHomMatrix & rMatrix)1516     void transform(const ::basegfx::B3DHomMatrix& rMatrix)
1517     {
1518         maPoints.transform(rMatrix);
1519 
1520         // Here, it seems to be possible to transform a valid plane normal and to avoid
1521         // invalidation, but it's not true. If the transformation contains shears or e.g.
1522         // perspective projection, the orthogonality to the transformed plane will not
1523         // be preserved. It may be possible to test that at the matrix to not invalidate in
1524         // all cases or to extract a matrix which does not 'shear' the vector which is
1525         // a normal in this case. As long as this is not sure, i will just invalidate.
1526         invalidatePlaneNormal();
1527     }
1528 };
1529 
1530 //////////////////////////////////////////////////////////////////////////////
1531 
1532 namespace basegfx
1533 {
1534     namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType,
1535                                                             DefaultPolygon > {}; }
1536 
B3DPolygon()1537     B3DPolygon::B3DPolygon() :
1538         mpPolygon(DefaultPolygon::get())
1539     {
1540     }
1541 
B3DPolygon(const B3DPolygon & rPolygon)1542     B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) :
1543         mpPolygon(rPolygon.mpPolygon)
1544     {
1545     }
1546 
B3DPolygon(const B3DPolygon & rPolygon,sal_uInt32 nIndex,sal_uInt32 nCount)1547     B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount) :
1548         mpPolygon(ImplB3DPolygon(*rPolygon.mpPolygon, nIndex, nCount))
1549     {
1550         // TODO(P2): one extra temporary here (cow_wrapper copies
1551         // given ImplB3DPolygon into its internal impl_t wrapper type)
1552         OSL_ENSURE(nIndex + nCount > rPolygon.mpPolygon->count(), "B3DPolygon constructor outside range (!)");
1553     }
1554 
~B3DPolygon()1555     B3DPolygon::~B3DPolygon()
1556     {
1557     }
1558 
operator =(const B3DPolygon & rPolygon)1559     B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon)
1560     {
1561         mpPolygon = rPolygon.mpPolygon;
1562         return *this;
1563     }
1564 
makeUnique()1565     void B3DPolygon::makeUnique()
1566     {
1567         mpPolygon.make_unique();
1568     }
1569 
operator ==(const B3DPolygon & rPolygon) const1570     bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const
1571     {
1572         if(mpPolygon.same_object(rPolygon.mpPolygon))
1573             return true;
1574 
1575         return (*mpPolygon == *rPolygon.mpPolygon);
1576     }
1577 
operator !=(const B3DPolygon & rPolygon) const1578     bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const
1579     {
1580         return !(*this == rPolygon);
1581     }
1582 
count() const1583     sal_uInt32 B3DPolygon::count() const
1584     {
1585         return mpPolygon->count();
1586     }
1587 
getB3DPoint(sal_uInt32 nIndex) const1588     basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const
1589     {
1590         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1591 
1592         return mpPolygon->getPoint(nIndex);
1593     }
1594 
setB3DPoint(sal_uInt32 nIndex,const basegfx::B3DPoint & rValue)1595     void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
1596     {
1597         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1598 
1599         if(getB3DPoint(nIndex) != rValue)
1600             mpPolygon->setPoint(nIndex, rValue);
1601     }
1602 
getBColor(sal_uInt32 nIndex) const1603     BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const
1604     {
1605         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1606 
1607         return mpPolygon->getBColor(nIndex);
1608     }
1609 
setBColor(sal_uInt32 nIndex,const BColor & rValue)1610     void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue)
1611     {
1612         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1613 
1614         if(mpPolygon->getBColor(nIndex) != rValue)
1615             mpPolygon->setBColor(nIndex, rValue);
1616     }
1617 
areBColorsUsed() const1618     bool B3DPolygon::areBColorsUsed() const
1619     {
1620         return mpPolygon->areBColorsUsed();
1621     }
1622 
clearBColors()1623     void B3DPolygon::clearBColors()
1624     {
1625         if(mpPolygon->areBColorsUsed())
1626             mpPolygon->clearBColors();
1627     }
1628 
getNormal() const1629     B3DVector B3DPolygon::getNormal() const
1630     {
1631         return mpPolygon->getNormal();
1632     }
1633 
getNormal(sal_uInt32 nIndex) const1634     B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const
1635     {
1636         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1637 
1638         return mpPolygon->getNormal(nIndex);
1639     }
1640 
setNormal(sal_uInt32 nIndex,const B3DVector & rValue)1641     void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue)
1642     {
1643         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1644 
1645         if(mpPolygon->getNormal(nIndex) != rValue)
1646             mpPolygon->setNormal(nIndex, rValue);
1647     }
1648 
transformNormals(const B3DHomMatrix & rMatrix)1649     void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix)
1650     {
1651         if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity())
1652             mpPolygon->transformNormals(rMatrix);
1653     }
1654 
areNormalsUsed() const1655     bool B3DPolygon::areNormalsUsed() const
1656     {
1657         return mpPolygon->areNormalsUsed();
1658     }
1659 
clearNormals()1660     void B3DPolygon::clearNormals()
1661     {
1662         if(mpPolygon->areNormalsUsed())
1663             mpPolygon->clearNormals();
1664     }
1665 
getTextureCoordinate(sal_uInt32 nIndex) const1666     B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const
1667     {
1668         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1669 
1670         return mpPolygon->getTextureCoordinate(nIndex);
1671     }
1672 
setTextureCoordinate(sal_uInt32 nIndex,const B2DPoint & rValue)1673     void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue)
1674     {
1675         OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1676 
1677         if(mpPolygon->getTextureCoordinate(nIndex) != rValue)
1678             mpPolygon->setTextureCoordinate(nIndex, rValue);
1679     }
1680 
transformTextureCoordiantes(const B2DHomMatrix & rMatrix)1681     void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
1682     {
1683         if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity())
1684             mpPolygon->transformTextureCoordinates(rMatrix);
1685     }
1686 
areTextureCoordinatesUsed() const1687     bool B3DPolygon::areTextureCoordinatesUsed() const
1688     {
1689         return mpPolygon->areTextureCoordinatesUsed();
1690     }
1691 
clearTextureCoordinates()1692     void B3DPolygon::clearTextureCoordinates()
1693     {
1694         if(mpPolygon->areTextureCoordinatesUsed())
1695             mpPolygon->clearTextureCoordinates();
1696     }
1697 
insert(sal_uInt32 nIndex,const::basegfx::B3DPoint & rPoint,sal_uInt32 nCount)1698     void B3DPolygon::insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1699     {
1700         OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1701 
1702         if(nCount)
1703             mpPolygon->insert(nIndex, rPoint, nCount);
1704     }
1705 
append(const basegfx::B3DPoint & rPoint,sal_uInt32 nCount)1706     void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1707     {
1708         if(nCount)
1709             mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1710     }
1711 
insert(sal_uInt32 nIndex,const B3DPolygon & rPoly,sal_uInt32 nIndex2,sal_uInt32 nCount)1712     void B3DPolygon::insert(sal_uInt32 nIndex, const B3DPolygon& rPoly, sal_uInt32 nIndex2, sal_uInt32 nCount)
1713     {
1714         OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1715 
1716         if(rPoly.count())
1717         {
1718             if(!nCount)
1719             {
1720                 nCount = rPoly.count();
1721             }
1722 
1723             if(0L == nIndex2 && nCount == rPoly.count())
1724             {
1725                 mpPolygon->insert(nIndex, *rPoly.mpPolygon);
1726             }
1727             else
1728             {
1729                 OSL_ENSURE(nIndex2 + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1730                 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex2, nCount);
1731                 mpPolygon->insert(nIndex, aTempPoly);
1732             }
1733         }
1734     }
1735 
append(const B3DPolygon & rPoly,sal_uInt32 nIndex,sal_uInt32 nCount)1736     void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
1737     {
1738         if(rPoly.count())
1739         {
1740             if(!nCount)
1741             {
1742                 nCount = rPoly.count();
1743             }
1744 
1745             if(0L == nIndex && nCount == rPoly.count())
1746             {
1747                 mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
1748             }
1749             else
1750             {
1751                 OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)");
1752                 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
1753                 mpPolygon->insert(mpPolygon->count(), aTempPoly);
1754             }
1755         }
1756     }
1757 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)1758     void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1759     {
1760         OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)");
1761 
1762         if(nCount)
1763             mpPolygon->remove(nIndex, nCount);
1764     }
1765 
clear()1766     void B3DPolygon::clear()
1767     {
1768         mpPolygon = DefaultPolygon::get();
1769     }
1770 
isClosed() const1771     bool B3DPolygon::isClosed() const
1772     {
1773         return mpPolygon->isClosed();
1774     }
1775 
setClosed(bool bNew)1776     void B3DPolygon::setClosed(bool bNew)
1777     {
1778         if(isClosed() != bNew)
1779             mpPolygon->setClosed(bNew);
1780     }
1781 
flip()1782     void B3DPolygon::flip()
1783     {
1784         if(count() > 1)
1785             mpPolygon->flip();
1786     }
1787 
hasDoublePoints() const1788     bool B3DPolygon::hasDoublePoints() const
1789     {
1790         return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints());
1791     }
1792 
removeDoublePoints()1793     void B3DPolygon::removeDoublePoints()
1794     {
1795         if(hasDoublePoints())
1796         {
1797             mpPolygon->removeDoublePointsAtBeginEnd();
1798             mpPolygon->removeDoublePointsWholeTrack();
1799         }
1800     }
1801 
transform(const basegfx::B3DHomMatrix & rMatrix)1802     void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix)
1803     {
1804         if(mpPolygon->count() && !rMatrix.isIdentity())
1805         {
1806             mpPolygon->transform(rMatrix);
1807         }
1808     }
1809 } // end of namespace basegfx
1810 
1811 //////////////////////////////////////////////////////////////////////////////
1812 // eof
1813