update emoji autocorrect entries from po-files
[LibreOffice.git] / basegfx / source / polygon / b3dpolygon.cxx
blob345877004836c0d5c3c91d98f5c5cc9c5904cee8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/diagnose.h>
21 #include <basegfx/polygon/b3dpolygon.hxx>
22 #include <basegfx/point/b3dpoint.hxx>
23 #include <basegfx/matrix/b3dhommatrix.hxx>
24 #include <rtl/instance.hxx>
25 #include <basegfx/point/b2dpoint.hxx>
26 #include <basegfx/color/bcolor.hxx>
27 #include <basegfx/matrix/b2dhommatrix.hxx>
28 #include <vector>
29 #include <algorithm>
31 class CoordinateData3D
33 basegfx::B3DPoint maPoint;
35 public:
36 CoordinateData3D()
37 : maPoint()
41 explicit CoordinateData3D(const basegfx::B3DPoint& rData)
42 : maPoint(rData)
46 const basegfx::B3DPoint& getCoordinate() const
48 return maPoint;
51 void setCoordinate(const basegfx::B3DPoint& rValue)
53 if(rValue != maPoint)
54 maPoint = rValue;
57 bool operator==(const CoordinateData3D& rData) const
59 return (maPoint == rData.getCoordinate());
62 void transform(const basegfx::B3DHomMatrix& rMatrix)
64 maPoint *= rMatrix;
68 class CoordinateDataArray3D
70 typedef ::std::vector< CoordinateData3D > CoordinateData3DVector;
72 CoordinateData3DVector maVector;
74 public:
75 explicit CoordinateDataArray3D(sal_uInt32 nCount)
76 : maVector(nCount)
80 explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal)
81 : maVector(rOriginal.maVector)
85 CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
86 : maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
90 ~CoordinateDataArray3D()
94 ::basegfx::B3DVector getNormal() const
96 ::basegfx::B3DVector aRetval;
97 const sal_uInt32 nPointCount(maVector.size());
99 if(nPointCount > 2)
101 sal_uInt32 nISmallest(0);
102 sal_uInt32 a(0);
103 const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate());
104 const basegfx::B3DPoint* pNext(0);
105 const basegfx::B3DPoint* pPrev(0);
107 // To guarantee a correctly oriented point, choose an outmost one
108 // which then cannot be concave
109 for(a = 1; a < nPointCount; a++)
111 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
113 if((rCandidate.getX() < pSmallest->getX())
114 || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY())
115 || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ()))
117 nISmallest = a;
118 pSmallest = &rCandidate;
122 // look for a next point different from minimal one
123 for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount)
125 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
127 if(!rCandidate.equal(*pSmallest))
129 pNext = &rCandidate;
130 break;
134 // look for a previous point different from minimal one
135 for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount)
137 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
139 if(!rCandidate.equal(*pSmallest))
141 pPrev = &rCandidate;
142 break;
146 // we always have a minimal point. If we also have a different next and previous,
147 // we can calculate the normal
148 if(pNext && pPrev)
150 const basegfx::B3DVector aPrev(*pPrev - *pSmallest);
151 const basegfx::B3DVector aNext(*pNext - *pSmallest);
153 aRetval = cross(aPrev, aNext);
154 aRetval.normalize();
158 return aRetval;
161 sal_uInt32 count() const
163 return maVector.size();
166 bool operator==(const CoordinateDataArray3D& rCandidate) const
168 return (maVector == rCandidate.maVector);
171 const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const
173 return maVector[nIndex].getCoordinate();
176 void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
178 maVector[nIndex].setCoordinate(rValue);
181 void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount)
183 if(nCount)
185 // add nCount copies of rValue
186 CoordinateData3DVector::iterator aIndex(maVector.begin());
187 aIndex += nIndex;
188 maVector.insert(aIndex, nCount, rValue);
192 void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource)
194 const sal_uInt32 nCount(rSource.maVector.size());
196 if(nCount)
198 // insert data
199 CoordinateData3DVector::iterator aIndex(maVector.begin());
200 aIndex += nIndex;
201 CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin());
202 CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end());
203 maVector.insert(aIndex, aStart, aEnd);
207 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
209 if(nCount)
211 // remove point data
212 CoordinateData3DVector::iterator aStart(maVector.begin());
213 aStart += nIndex;
214 const CoordinateData3DVector::iterator aEnd(aStart + nCount);
215 maVector.erase(aStart, aEnd);
219 void flip()
221 if(maVector.size() > 1)
223 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
224 CoordinateData3DVector::iterator aStart(maVector.begin());
225 CoordinateData3DVector::iterator aEnd(maVector.end() - 1L);
227 for(sal_uInt32 a(0); a < nHalfSize; a++)
229 ::std::swap(*aStart, *aEnd);
230 ++aStart;
231 --aEnd;
236 void transform(const ::basegfx::B3DHomMatrix& rMatrix)
238 CoordinateData3DVector::iterator aStart(maVector.begin());
239 CoordinateData3DVector::iterator aEnd(maVector.end());
241 for(; aStart != aEnd; ++aStart)
243 aStart->transform(rMatrix);
248 class BColorArray
250 typedef ::std::vector< ::basegfx::BColor > BColorDataVector;
252 BColorDataVector maVector;
253 sal_uInt32 mnUsedEntries;
255 public:
256 explicit BColorArray(sal_uInt32 nCount)
257 : maVector(nCount),
258 mnUsedEntries(0L)
262 explicit BColorArray(const BColorArray& rOriginal)
263 : maVector(rOriginal.maVector),
264 mnUsedEntries(rOriginal.mnUsedEntries)
268 BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
269 : maVector(),
270 mnUsedEntries(0L)
272 BColorDataVector::const_iterator aStart(rOriginal.maVector.begin());
273 aStart += nIndex;
274 BColorDataVector::const_iterator aEnd(aStart);
275 assert(nCount <= rOriginal.maVector.size());
276 aEnd += nCount;
277 maVector.reserve(nCount);
279 for(; aStart != aEnd; ++aStart)
281 if(!aStart->equalZero())
282 mnUsedEntries++;
284 maVector.push_back(*aStart);
288 ~BColorArray()
292 bool operator==(const BColorArray& rCandidate) const
294 return (maVector == rCandidate.maVector);
297 bool isUsed() const
299 return (0L != mnUsedEntries);
302 const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
304 return maVector[nIndex];
307 void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
309 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
310 bool bIsUsed(!rValue.equalZero());
312 if(bWasUsed)
314 if(bIsUsed)
316 maVector[nIndex] = rValue;
318 else
320 maVector[nIndex] = ::basegfx::BColor::getEmptyBColor();
321 mnUsedEntries--;
324 else
326 if(bIsUsed)
328 maVector[nIndex] = rValue;
329 mnUsedEntries++;
334 void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount)
336 if(nCount)
338 // add nCount copies of rValue
339 BColorDataVector::iterator aIndex(maVector.begin());
340 aIndex += nIndex;
341 maVector.insert(aIndex, nCount, rValue);
343 if(!rValue.equalZero())
344 mnUsedEntries += nCount;
348 void insert(sal_uInt32 nIndex, const BColorArray& rSource)
350 const sal_uInt32 nCount(rSource.maVector.size());
352 if(nCount)
354 // insert data
355 BColorDataVector::iterator aIndex(maVector.begin());
356 aIndex += nIndex;
357 BColorDataVector::const_iterator aStart(rSource.maVector.begin());
358 BColorDataVector::const_iterator aEnd(rSource.maVector.end());
359 maVector.insert(aIndex, aStart, aEnd);
361 for(; aStart != aEnd; ++aStart)
363 if(!aStart->equalZero())
364 mnUsedEntries++;
369 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
371 if(nCount)
373 const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex);
374 const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount);
375 BColorDataVector::const_iterator aStart(aDeleteStart);
377 for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
379 if(!aStart->equalZero())
380 mnUsedEntries--;
383 // remove point data
384 maVector.erase(aDeleteStart, aDeleteEnd);
388 void flip()
390 if(maVector.size() > 1)
392 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
393 BColorDataVector::iterator aStart(maVector.begin());
394 BColorDataVector::iterator aEnd(maVector.end() - 1L);
396 for(sal_uInt32 a(0); a < nHalfSize; a++)
398 ::std::swap(*aStart, *aEnd);
399 ++aStart;
400 --aEnd;
406 class NormalsArray3D
408 typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector;
410 NormalsData3DVector maVector;
411 sal_uInt32 mnUsedEntries;
413 public:
414 explicit NormalsArray3D(sal_uInt32 nCount)
415 : maVector(nCount),
416 mnUsedEntries(0L)
420 explicit NormalsArray3D(const NormalsArray3D& rOriginal)
421 : maVector(rOriginal.maVector),
422 mnUsedEntries(rOriginal.mnUsedEntries)
426 NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
427 : maVector(),
428 mnUsedEntries(0L)
430 NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin());
431 aStart += nIndex;
432 NormalsData3DVector::const_iterator aEnd(aStart);
433 aEnd += nCount;
434 maVector.reserve(nCount);
436 for(; aStart != aEnd; ++aStart)
438 if(!aStart->equalZero())
439 mnUsedEntries++;
441 maVector.push_back(*aStart);
445 ~NormalsArray3D()
449 bool operator==(const NormalsArray3D& rCandidate) const
451 return (maVector == rCandidate.maVector);
454 bool isUsed() const
456 return (0L != mnUsedEntries);
459 const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
461 return maVector[nIndex];
464 void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
466 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
467 bool bIsUsed(!rValue.equalZero());
469 if(bWasUsed)
471 if(bIsUsed)
473 maVector[nIndex] = rValue;
475 else
477 maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector();
478 mnUsedEntries--;
481 else
483 if(bIsUsed)
485 maVector[nIndex] = rValue;
486 mnUsedEntries++;
491 void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount)
493 if(nCount)
495 // add nCount copies of rValue
496 NormalsData3DVector::iterator aIndex(maVector.begin());
497 aIndex += nIndex;
498 maVector.insert(aIndex, nCount, rValue);
500 if(!rValue.equalZero())
501 mnUsedEntries += nCount;
505 void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource)
507 const sal_uInt32 nCount(rSource.maVector.size());
509 if(nCount)
511 // insert data
512 NormalsData3DVector::iterator aIndex(maVector.begin());
513 aIndex += nIndex;
514 NormalsData3DVector::const_iterator aStart(rSource.maVector.begin());
515 NormalsData3DVector::const_iterator aEnd(rSource.maVector.end());
516 maVector.insert(aIndex, aStart, aEnd);
518 for(; aStart != aEnd; ++aStart)
520 if(!aStart->equalZero())
521 mnUsedEntries++;
526 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
528 if(nCount)
530 const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex);
531 const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount);
532 NormalsData3DVector::const_iterator aStart(aDeleteStart);
534 for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
536 if(!aStart->equalZero())
537 mnUsedEntries--;
540 // remove point data
541 maVector.erase(aDeleteStart, aDeleteEnd);
545 void flip()
547 if(maVector.size() > 1)
549 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
550 NormalsData3DVector::iterator aStart(maVector.begin());
551 NormalsData3DVector::iterator aEnd(maVector.end() - 1L);
553 for(sal_uInt32 a(0); a < nHalfSize; a++)
555 ::std::swap(*aStart, *aEnd);
556 ++aStart;
557 --aEnd;
562 void transform(const basegfx::B3DHomMatrix& rMatrix)
564 const NormalsData3DVector::const_iterator aEnd(maVector.end());
566 for(NormalsData3DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
568 (*aStart) *= rMatrix;
573 class TextureCoordinate2D
575 typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector;
577 TextureData2DVector maVector;
578 sal_uInt32 mnUsedEntries;
580 public:
581 explicit TextureCoordinate2D(sal_uInt32 nCount)
582 : maVector(nCount),
583 mnUsedEntries(0L)
587 explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal)
588 : maVector(rOriginal.maVector),
589 mnUsedEntries(rOriginal.mnUsedEntries)
593 TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
594 : maVector(),
595 mnUsedEntries(0L)
597 TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin());
598 aStart += nIndex;
599 TextureData2DVector::const_iterator aEnd(aStart);
600 aEnd += nCount;
601 maVector.reserve(nCount);
603 for(; aStart != aEnd; ++aStart)
605 if(!aStart->equalZero())
606 mnUsedEntries++;
608 maVector.push_back(*aStart);
612 ~TextureCoordinate2D()
616 bool operator==(const TextureCoordinate2D& rCandidate) const
618 return (maVector == rCandidate.maVector);
621 bool isUsed() const
623 return (0L != mnUsedEntries);
626 const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
628 return maVector[nIndex];
631 void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
633 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
634 bool bIsUsed(!rValue.equalZero());
636 if(bWasUsed)
638 if(bIsUsed)
640 maVector[nIndex] = rValue;
642 else
644 maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint();
645 mnUsedEntries--;
648 else
650 if(bIsUsed)
652 maVector[nIndex] = rValue;
653 mnUsedEntries++;
658 void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount)
660 if(nCount)
662 // add nCount copies of rValue
663 TextureData2DVector::iterator aIndex(maVector.begin());
664 aIndex += nIndex;
665 maVector.insert(aIndex, nCount, rValue);
667 if(!rValue.equalZero())
668 mnUsedEntries += nCount;
672 void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource)
674 const sal_uInt32 nCount(rSource.maVector.size());
676 if(nCount)
678 // insert data
679 TextureData2DVector::iterator aIndex(maVector.begin());
680 aIndex += nIndex;
681 TextureData2DVector::const_iterator aStart(rSource.maVector.begin());
682 TextureData2DVector::const_iterator aEnd(rSource.maVector.end());
683 maVector.insert(aIndex, aStart, aEnd);
685 for(; aStart != aEnd; ++aStart)
687 if(!aStart->equalZero())
688 mnUsedEntries++;
693 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
695 if(nCount)
697 const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
698 const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
699 TextureData2DVector::const_iterator aStart(aDeleteStart);
701 for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
703 if(!aStart->equalZero())
704 mnUsedEntries--;
707 // remove point data
708 maVector.erase(aDeleteStart, aDeleteEnd);
712 void flip()
714 if(maVector.size() > 1)
716 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
717 TextureData2DVector::iterator aStart(maVector.begin());
718 TextureData2DVector::iterator aEnd(maVector.end() - 1L);
720 for(sal_uInt32 a(0); a < nHalfSize; a++)
722 ::std::swap(*aStart, *aEnd);
723 ++aStart;
724 --aEnd;
729 void transform(const ::basegfx::B2DHomMatrix& rMatrix)
731 const TextureData2DVector::const_iterator aEnd(maVector.end());
733 for(TextureData2DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
735 (*aStart) *= rMatrix;
740 class ImplB3DPolygon
742 // The point vector. This vector exists always and defines the
743 // count of members.
744 CoordinateDataArray3D maPoints;
746 // The BColor vector. This vectors are created on demand
747 // and may be zero.
748 BColorArray* mpBColors;
750 // The Normals vector. This vectors are created on demand
751 // and may be zero.
752 NormalsArray3D* mpNormals;
754 // The TextureCoordinates vector. This vectors are created on demand
755 // and may be zero.
756 TextureCoordinate2D* mpTextureCoordiantes;
758 // The calculated plane normal. mbPlaneNormalValid says if it's valid.
759 ::basegfx::B3DVector maPlaneNormal;
761 // bitfield
762 // flag which decides if this polygon is opened or closed
763 bool mbIsClosed : 1;
765 // flag which says if maPlaneNormal is up-to-date
766 bool mbPlaneNormalValid : 1;
768 protected:
769 void invalidatePlaneNormal()
771 if(mbPlaneNormalValid)
773 mbPlaneNormalValid = false;
777 public:
778 // This constructor is only used from the static identity polygon, thus
779 // the RefCount is set to 1 to never 'delete' this static incarnation.
780 ImplB3DPolygon()
781 : maPoints(0L),
782 mpBColors(0L),
783 mpNormals(0L),
784 mpTextureCoordiantes(0L),
785 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
786 mbIsClosed(false),
787 mbPlaneNormalValid(true)
789 // complete initialization with defaults
792 ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied)
793 : maPoints(rToBeCopied.maPoints),
794 mpBColors(0L),
795 mpNormals(0L),
796 mpTextureCoordiantes(0L),
797 maPlaneNormal(rToBeCopied.maPlaneNormal),
798 mbIsClosed(rToBeCopied.mbIsClosed),
799 mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid)
801 // complete initialization using copy
802 if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
804 mpBColors = new BColorArray(*rToBeCopied.mpBColors);
807 if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
809 mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals);
812 if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
814 mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes);
818 ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
819 : maPoints(rToBeCopied.maPoints, nIndex, nCount),
820 mpBColors(0L),
821 mpNormals(0L),
822 mpTextureCoordiantes(0L),
823 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
824 mbIsClosed(rToBeCopied.mbIsClosed),
825 mbPlaneNormalValid(false)
827 // complete initialization using partly copy
828 if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
830 mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount);
832 if(!mpBColors->isUsed())
834 delete mpBColors;
835 mpBColors = 0L;
839 if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
841 mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount);
843 if(!mpNormals->isUsed())
845 delete mpNormals;
846 mpNormals = 0L;
850 if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
852 mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount);
854 if(!mpTextureCoordiantes->isUsed())
856 delete mpTextureCoordiantes;
857 mpTextureCoordiantes = 0L;
862 ~ImplB3DPolygon()
864 if(mpBColors)
866 delete mpBColors;
867 mpBColors = 0L;
870 if(mpNormals)
872 delete mpNormals;
873 mpNormals = 0L;
876 if(mpTextureCoordiantes)
878 delete mpTextureCoordiantes;
879 mpTextureCoordiantes = 0L;
883 sal_uInt32 count() const
885 return maPoints.count();
888 bool isClosed() const
890 return mbIsClosed;
893 void setClosed(bool bNew)
895 if(bNew != (bool)mbIsClosed)
897 mbIsClosed = bNew;
901 inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const
903 bool bBColorsAreEqual(true);
905 if(mpBColors)
907 if(rCandidate.mpBColors)
909 bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors);
911 else
913 // candidate has no BColors, so it's assumed all unused.
914 bBColorsAreEqual = !mpBColors->isUsed();
917 else
919 if(rCandidate.mpBColors)
921 // we have no TextureCoordiantes, so it's assumed all unused.
922 bBColorsAreEqual = !rCandidate.mpBColors->isUsed();
926 return bBColorsAreEqual;
929 inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const
931 bool bNormalsAreEqual(true);
933 if(mpNormals)
935 if(rCandidate.mpNormals)
937 bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals);
939 else
941 // candidate has no normals, so it's assumed all unused.
942 bNormalsAreEqual = !mpNormals->isUsed();
945 else
947 if(rCandidate.mpNormals)
949 // we have no normals, so it's assumed all unused.
950 bNormalsAreEqual = !rCandidate.mpNormals->isUsed();
954 return bNormalsAreEqual;
957 inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const
959 bool bTextureCoordinatesAreEqual(true);
961 if(mpTextureCoordiantes)
963 if(rCandidate.mpTextureCoordiantes)
965 bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes);
967 else
969 // candidate has no TextureCoordinates, so it's assumed all unused.
970 bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed();
973 else
975 if(rCandidate.mpTextureCoordiantes)
977 // we have no TextureCoordiantes, so it's assumed all unused.
978 bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed();
982 return bTextureCoordinatesAreEqual;
985 bool operator==(const ImplB3DPolygon& rCandidate) const
987 if(mbIsClosed == rCandidate.mbIsClosed)
989 if(maPoints == rCandidate.maPoints)
991 if(impBColorsAreEqual(rCandidate))
993 if(impNormalsAreEqual(rCandidate))
995 if(impTextureCoordinatesAreEqual(rCandidate))
997 return true;
1004 return false;
1007 const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const
1009 return maPoints.getCoordinate(nIndex);
1012 void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue)
1014 maPoints.setCoordinate(nIndex, rValue);
1015 invalidatePlaneNormal();
1018 void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1020 if(nCount)
1022 CoordinateData3D aCoordinate(rPoint);
1023 maPoints.insert(nIndex, aCoordinate, nCount);
1024 invalidatePlaneNormal();
1026 if(mpBColors)
1028 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1031 if(mpNormals)
1033 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1036 if(mpTextureCoordiantes)
1038 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1043 const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
1045 if(mpBColors)
1047 return mpBColors->getBColor(nIndex);
1049 else
1051 return ::basegfx::BColor::getEmptyBColor();
1055 void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
1057 if(!mpBColors)
1059 if(!rValue.equalZero())
1061 mpBColors = new BColorArray(maPoints.count());
1062 mpBColors->setBColor(nIndex, rValue);
1065 else
1067 mpBColors->setBColor(nIndex, rValue);
1069 if(!mpBColors->isUsed())
1071 delete mpBColors;
1072 mpBColors = 0L;
1077 bool areBColorsUsed() const
1079 return (mpBColors && mpBColors->isUsed());
1082 void clearBColors()
1084 if(mpBColors)
1086 delete mpBColors;
1087 mpBColors = 0L;
1091 const ::basegfx::B3DVector& getNormal() const
1093 if(!mbPlaneNormalValid)
1095 const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal();
1096 const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true;
1099 return maPlaneNormal;
1102 const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
1104 if(mpNormals)
1106 return mpNormals->getNormal(nIndex);
1108 else
1110 return ::basegfx::B3DVector::getEmptyVector();
1114 void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
1116 if(!mpNormals)
1118 if(!rValue.equalZero())
1120 mpNormals = new NormalsArray3D(maPoints.count());
1121 mpNormals->setNormal(nIndex, rValue);
1124 else
1126 mpNormals->setNormal(nIndex, rValue);
1128 if(!mpNormals->isUsed())
1130 delete mpNormals;
1131 mpNormals = 0L;
1136 void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
1138 if(mpNormals)
1140 mpNormals->transform(rMatrix);
1144 bool areNormalsUsed() const
1146 return (mpNormals && mpNormals->isUsed());
1149 void clearNormals()
1151 if(mpNormals)
1153 delete mpNormals;
1154 mpNormals = 0L;
1158 const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
1160 if(mpTextureCoordiantes)
1162 return mpTextureCoordiantes->getTextureCoordinate(nIndex);
1164 else
1166 return ::basegfx::B2DPoint::getEmptyPoint();
1170 void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
1172 if(!mpTextureCoordiantes)
1174 if(!rValue.equalZero())
1176 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1177 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1180 else
1182 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1184 if(!mpTextureCoordiantes->isUsed())
1186 delete mpTextureCoordiantes;
1187 mpTextureCoordiantes = 0L;
1192 bool areTextureCoordinatesUsed() const
1194 return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed());
1197 void clearTextureCoordinates()
1199 if(mpTextureCoordiantes)
1201 delete mpTextureCoordiantes;
1202 mpTextureCoordiantes = 0L;
1206 void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
1208 if(mpTextureCoordiantes)
1210 mpTextureCoordiantes->transform(rMatrix);
1214 void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource)
1216 const sal_uInt32 nCount(rSource.maPoints.count());
1218 if(nCount)
1220 maPoints.insert(nIndex, rSource.maPoints);
1221 invalidatePlaneNormal();
1223 if(rSource.mpBColors && rSource.mpBColors->isUsed())
1225 if(!mpBColors)
1227 mpBColors = new BColorArray(maPoints.count());
1230 mpBColors->insert(nIndex, *rSource.mpBColors);
1232 else
1234 if(mpBColors)
1236 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1240 if(rSource.mpNormals && rSource.mpNormals->isUsed())
1242 if(!mpNormals)
1244 mpNormals = new NormalsArray3D(maPoints.count());
1247 mpNormals->insert(nIndex, *rSource.mpNormals);
1249 else
1251 if(mpNormals)
1253 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1257 if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed())
1259 if(!mpTextureCoordiantes)
1261 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1264 mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes);
1266 else
1268 if(mpTextureCoordiantes)
1270 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1276 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1278 if(nCount)
1280 maPoints.remove(nIndex, nCount);
1281 invalidatePlaneNormal();
1283 if(mpBColors)
1285 mpBColors->remove(nIndex, nCount);
1287 if(!mpBColors->isUsed())
1289 delete mpBColors;
1290 mpBColors = 0L;
1294 if(mpNormals)
1296 mpNormals->remove(nIndex, nCount);
1298 if(!mpNormals->isUsed())
1300 delete mpNormals;
1301 mpNormals = 0L;
1305 if(mpTextureCoordiantes)
1307 mpTextureCoordiantes->remove(nIndex, nCount);
1309 if(!mpTextureCoordiantes->isUsed())
1311 delete mpTextureCoordiantes;
1312 mpTextureCoordiantes = 0L;
1318 void flip()
1320 if(maPoints.count() > 1)
1322 maPoints.flip();
1324 if(mbPlaneNormalValid)
1326 // mirror plane normal
1327 maPlaneNormal = -maPlaneNormal;
1330 if(mpBColors)
1332 mpBColors->flip();
1335 if(mpNormals)
1337 mpNormals->flip();
1340 if(mpTextureCoordiantes)
1342 mpTextureCoordiantes->flip();
1347 bool hasDoublePoints() const
1349 if(mbIsClosed)
1351 // check for same start and end point
1352 const sal_uInt32 nIndex(maPoints.count() - 1L);
1354 if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex))
1356 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)));
1358 if(bBColorEqual)
1360 const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)));
1362 if(bNormalsEqual)
1364 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)));
1366 if(bTextureCoordinatesEqual)
1368 return true;
1375 // test for range
1376 for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++)
1378 if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L))
1380 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L)));
1382 if(bBColorEqual)
1384 const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L)));
1386 if(bNormalsEqual)
1388 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L)));
1390 if(bTextureCoordinatesEqual)
1392 return true;
1399 return false;
1402 void removeDoublePointsAtBeginEnd()
1404 // Only remove DoublePoints at Begin and End when poly is closed
1405 if(mbIsClosed)
1407 bool bRemove;
1411 bRemove = false;
1413 if(maPoints.count() > 1L)
1415 const sal_uInt32 nIndex(maPoints.count() - 1L);
1416 bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex));
1418 if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)))
1420 bRemove = false;
1423 if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)))
1425 bRemove = false;
1428 if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)))
1430 bRemove = false;
1434 if(bRemove)
1436 const sal_uInt32 nIndex(maPoints.count() - 1L);
1437 remove(nIndex, 1L);
1439 } while(bRemove);
1443 void removeDoublePointsWholeTrack()
1445 sal_uInt32 nIndex(0L);
1447 // test as long as there are at least two points and as long as the index
1448 // is smaller or equal second last point
1449 while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L))
1451 const sal_uInt32 nNextIndex(nIndex + 1L);
1452 bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex));
1454 if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex)))
1456 bRemove = false;
1459 if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex)))
1461 bRemove = false;
1464 if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex)))
1466 bRemove = false;
1469 if(bRemove)
1471 // if next is same as index and the control vectors are unused, delete index
1472 remove(nIndex, 1L);
1474 else
1476 // if different, step forward
1477 nIndex++;
1482 void transform(const ::basegfx::B3DHomMatrix& rMatrix)
1484 maPoints.transform(rMatrix);
1486 // Here, it seems to be possible to transform a valid plane normal and to avoid
1487 // invalidation, but it's not true. If the transformation contains shears or e.g.
1488 // perspective projection, the orthogonality to the transformed plane will not
1489 // be preserved. It may be possible to test that at the matrix to not invalidate in
1490 // all cases or to extract a matrix which does not 'shear' the vector which is
1491 // a normal in this case. As long as this is not sure, i will just invalidate.
1492 invalidatePlaneNormal();
1496 namespace basegfx
1498 namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType,
1499 DefaultPolygon > {}; }
1501 B3DPolygon::B3DPolygon() :
1502 mpPolygon(DefaultPolygon::get())
1506 B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) :
1507 mpPolygon(rPolygon.mpPolygon)
1511 B3DPolygon::~B3DPolygon()
1515 B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon)
1517 mpPolygon = rPolygon.mpPolygon;
1518 return *this;
1521 bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const
1523 if(mpPolygon.same_object(rPolygon.mpPolygon))
1524 return true;
1526 return (*mpPolygon == *rPolygon.mpPolygon);
1529 bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const
1531 return !(*this == rPolygon);
1534 sal_uInt32 B3DPolygon::count() const
1536 return mpPolygon->count();
1539 basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const
1541 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1543 return mpPolygon->getPoint(nIndex);
1546 void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
1548 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1550 if(getB3DPoint(nIndex) != rValue)
1551 mpPolygon->setPoint(nIndex, rValue);
1554 BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const
1556 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1558 return mpPolygon->getBColor(nIndex);
1561 void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue)
1563 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1565 if(mpPolygon->getBColor(nIndex) != rValue)
1566 mpPolygon->setBColor(nIndex, rValue);
1569 bool B3DPolygon::areBColorsUsed() const
1571 return mpPolygon->areBColorsUsed();
1574 void B3DPolygon::clearBColors()
1576 if(mpPolygon->areBColorsUsed())
1577 mpPolygon->clearBColors();
1580 B3DVector B3DPolygon::getNormal() const
1582 return mpPolygon->getNormal();
1585 B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const
1587 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1589 return mpPolygon->getNormal(nIndex);
1592 void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue)
1594 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1596 if(mpPolygon->getNormal(nIndex) != rValue)
1597 mpPolygon->setNormal(nIndex, rValue);
1600 void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix)
1602 if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity())
1603 mpPolygon->transformNormals(rMatrix);
1606 bool B3DPolygon::areNormalsUsed() const
1608 return mpPolygon->areNormalsUsed();
1611 void B3DPolygon::clearNormals()
1613 if(mpPolygon->areNormalsUsed())
1614 mpPolygon->clearNormals();
1617 B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const
1619 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1621 return mpPolygon->getTextureCoordinate(nIndex);
1624 void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue)
1626 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1628 if(mpPolygon->getTextureCoordinate(nIndex) != rValue)
1629 mpPolygon->setTextureCoordinate(nIndex, rValue);
1632 void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
1634 if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity())
1635 mpPolygon->transformTextureCoordinates(rMatrix);
1638 bool B3DPolygon::areTextureCoordinatesUsed() const
1640 return mpPolygon->areTextureCoordinatesUsed();
1643 void B3DPolygon::clearTextureCoordinates()
1645 if(mpPolygon->areTextureCoordinatesUsed())
1646 mpPolygon->clearTextureCoordinates();
1649 void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1651 if(nCount)
1652 mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1655 void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
1657 if(rPoly.count())
1659 if(!nCount)
1661 nCount = rPoly.count();
1664 if(0L == nIndex && nCount == rPoly.count())
1666 mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
1668 else
1670 OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)");
1671 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
1672 mpPolygon->insert(mpPolygon->count(), aTempPoly);
1677 void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1679 OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)");
1681 if(nCount)
1682 mpPolygon->remove(nIndex, nCount);
1685 void B3DPolygon::clear()
1687 mpPolygon = DefaultPolygon::get();
1690 bool B3DPolygon::isClosed() const
1692 return mpPolygon->isClosed();
1695 void B3DPolygon::setClosed(bool bNew)
1697 if(isClosed() != bNew)
1698 mpPolygon->setClosed(bNew);
1701 void B3DPolygon::flip()
1703 if(count() > 1)
1704 mpPolygon->flip();
1707 bool B3DPolygon::hasDoublePoints() const
1709 return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints());
1712 void B3DPolygon::removeDoublePoints()
1714 if(hasDoublePoints())
1716 mpPolygon->removeDoublePointsAtBeginEnd();
1717 mpPolygon->removeDoublePointsWholeTrack();
1721 void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix)
1723 if(mpPolygon->count() && !rMatrix.isIdentity())
1725 mpPolygon->transform(rMatrix);
1728 } // end of namespace basegfx
1730 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */