merge the formfield patch from ooo-build
[ooovba.git] / basegfx / source / polygon / b3dpolygon.cxx
blob880264bcac70d2d0de9452bc709e31433cd91a6e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: b3dpolygon.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basegfx.hxx"
33 #include <osl/diagnose.h>
34 #include <basegfx/polygon/b3dpolygon.hxx>
35 #include <basegfx/point/b3dpoint.hxx>
36 #include <basegfx/matrix/b3dhommatrix.hxx>
37 #include <rtl/instance.hxx>
38 #include <basegfx/point/b2dpoint.hxx>
39 #include <basegfx/color/bcolor.hxx>
40 #include <basegfx/matrix/b2dhommatrix.hxx>
41 #include <vector>
42 #include <algorithm>
44 //////////////////////////////////////////////////////////////////////////////
46 class CoordinateData3D
48 basegfx::B3DPoint maPoint;
50 public:
51 CoordinateData3D()
52 : maPoint()
56 explicit CoordinateData3D(const basegfx::B3DPoint& rData)
57 : maPoint(rData)
61 const basegfx::B3DPoint& getCoordinate() const
63 return maPoint;
66 void setCoordinate(const basegfx::B3DPoint& rValue)
68 if(rValue != maPoint)
69 maPoint = rValue;
72 bool operator==(const CoordinateData3D& rData) const
74 return (maPoint == rData.getCoordinate());
77 void transform(const basegfx::B3DHomMatrix& rMatrix)
79 maPoint *= rMatrix;
83 //////////////////////////////////////////////////////////////////////////////
85 class CoordinateDataArray3D
87 typedef ::std::vector< CoordinateData3D > CoordinateData3DVector;
89 CoordinateData3DVector maVector;
91 public:
92 explicit CoordinateDataArray3D(sal_uInt32 nCount)
93 : maVector(nCount)
97 explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal)
98 : maVector(rOriginal.maVector)
102 CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
103 : maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
107 ~CoordinateDataArray3D()
111 ::basegfx::B3DVector getNormal() const
113 ::basegfx::B3DVector aRetval;
114 const sal_uInt32 nPointCount(maVector.size());
116 if(nPointCount > 2)
118 sal_uInt32 nISmallest(0);
119 sal_uInt32 a(0);
120 const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate());
121 const basegfx::B3DPoint* pNext(0);
122 const basegfx::B3DPoint* pPrev(0);
124 // To guarantee a correctly oriented point, choose an outmost one
125 // which then cannot be concave
126 for(a = 1; a < nPointCount; a++)
128 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
130 if((rCandidate.getX() < pSmallest->getX())
131 || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY())
132 || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ()))
134 nISmallest = a;
135 pSmallest = &rCandidate;
139 // look for a next point different from minimal one
140 for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount)
142 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
144 if(!rCandidate.equal(*pSmallest))
146 pNext = &rCandidate;
147 break;
151 // look for a previous point different from minimal one
152 for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount)
154 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
156 if(!rCandidate.equal(*pSmallest))
158 pPrev = &rCandidate;
159 break;
163 // we always have a minimal point. If we also have a different next and previous,
164 // we can calculate the normal
165 if(pNext && pPrev)
167 const basegfx::B3DVector aPrev(*pPrev - *pSmallest);
168 const basegfx::B3DVector aNext(*pNext - *pSmallest);
170 aRetval = cross(aPrev, aNext);
171 aRetval.normalize();
175 return aRetval;
178 sal_uInt32 count() const
180 return maVector.size();
183 bool operator==(const CoordinateDataArray3D& rCandidate) const
185 return (maVector == rCandidate.maVector);
188 const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const
190 return maVector[nIndex].getCoordinate();
193 void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
195 maVector[nIndex].setCoordinate(rValue);
198 void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount)
200 if(nCount)
202 // add nCount copies of rValue
203 CoordinateData3DVector::iterator aIndex(maVector.begin());
204 aIndex += nIndex;
205 maVector.insert(aIndex, nCount, rValue);
209 void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource)
211 const sal_uInt32 nCount(rSource.maVector.size());
213 if(nCount)
215 // insert data
216 CoordinateData3DVector::iterator aIndex(maVector.begin());
217 aIndex += nIndex;
218 CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin());
219 CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end());
220 maVector.insert(aIndex, aStart, aEnd);
224 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
226 if(nCount)
228 // remove point data
229 CoordinateData3DVector::iterator aStart(maVector.begin());
230 aStart += nIndex;
231 const CoordinateData3DVector::iterator aEnd(aStart + nCount);
232 maVector.erase(aStart, aEnd);
236 void flip()
238 if(maVector.size() > 1)
240 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
241 CoordinateData3DVector::iterator aStart(maVector.begin());
242 CoordinateData3DVector::iterator aEnd(maVector.end() - 1L);
244 for(sal_uInt32 a(0); a < nHalfSize; a++)
246 ::std::swap(*aStart, *aEnd);
247 aStart++;
248 aEnd--;
253 void transform(const ::basegfx::B3DHomMatrix& rMatrix)
255 CoordinateData3DVector::iterator aStart(maVector.begin());
256 CoordinateData3DVector::iterator aEnd(maVector.end());
258 for(; aStart != aEnd; aStart++)
260 aStart->transform(rMatrix);
265 //////////////////////////////////////////////////////////////////////////////
267 class BColorArray
269 typedef ::std::vector< ::basegfx::BColor > BColorDataVector;
271 BColorDataVector maVector;
272 sal_uInt32 mnUsedEntries;
274 public:
275 explicit BColorArray(sal_uInt32 nCount)
276 : maVector(nCount),
277 mnUsedEntries(0L)
281 explicit BColorArray(const BColorArray& rOriginal)
282 : maVector(rOriginal.maVector),
283 mnUsedEntries(rOriginal.mnUsedEntries)
287 BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
288 : maVector(),
289 mnUsedEntries(0L)
291 BColorDataVector::const_iterator aStart(rOriginal.maVector.begin());
292 aStart += nIndex;
293 BColorDataVector::const_iterator aEnd(aStart);
294 aEnd += nCount;
295 maVector.reserve(nCount);
297 for(; aStart != aEnd; aStart++)
299 if(!aStart->equalZero())
300 mnUsedEntries++;
302 maVector.push_back(*aStart);
306 ~BColorArray()
310 sal_uInt32 count() const
312 return maVector.size();
315 bool operator==(const BColorArray& rCandidate) const
317 return (maVector == rCandidate.maVector);
320 bool isUsed() const
322 return (0L != mnUsedEntries);
325 const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
327 return maVector[nIndex];
330 void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
332 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
333 bool bIsUsed(!rValue.equalZero());
335 if(bWasUsed)
337 if(bIsUsed)
339 maVector[nIndex] = rValue;
341 else
343 maVector[nIndex] = ::basegfx::BColor::getEmptyBColor();
344 mnUsedEntries--;
347 else
349 if(bIsUsed)
351 maVector[nIndex] = rValue;
352 mnUsedEntries++;
357 void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount)
359 if(nCount)
361 // add nCount copies of rValue
362 BColorDataVector::iterator aIndex(maVector.begin());
363 aIndex += nIndex;
364 maVector.insert(aIndex, nCount, rValue);
366 if(!rValue.equalZero())
367 mnUsedEntries += nCount;
371 void insert(sal_uInt32 nIndex, const BColorArray& rSource)
373 const sal_uInt32 nCount(rSource.maVector.size());
375 if(nCount)
377 // insert data
378 BColorDataVector::iterator aIndex(maVector.begin());
379 aIndex += nIndex;
380 BColorDataVector::const_iterator aStart(rSource.maVector.begin());
381 BColorDataVector::const_iterator aEnd(rSource.maVector.end());
382 maVector.insert(aIndex, aStart, aEnd);
384 for(; aStart != aEnd; aStart++)
386 if(!aStart->equalZero())
387 mnUsedEntries++;
392 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
394 if(nCount)
396 const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex);
397 const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount);
398 BColorDataVector::const_iterator aStart(aDeleteStart);
400 for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
402 if(!aStart->equalZero())
403 mnUsedEntries--;
406 // remove point data
407 maVector.erase(aDeleteStart, aDeleteEnd);
411 void flip()
413 if(maVector.size() > 1)
415 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
416 BColorDataVector::iterator aStart(maVector.begin());
417 BColorDataVector::iterator aEnd(maVector.end() - 1L);
419 for(sal_uInt32 a(0); a < nHalfSize; a++)
421 ::std::swap(*aStart, *aEnd);
422 aStart++;
423 aEnd--;
429 //////////////////////////////////////////////////////////////////////////////
431 class NormalsArray3D
433 typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector;
435 NormalsData3DVector maVector;
436 sal_uInt32 mnUsedEntries;
438 public:
439 explicit NormalsArray3D(sal_uInt32 nCount)
440 : maVector(nCount),
441 mnUsedEntries(0L)
445 explicit NormalsArray3D(const NormalsArray3D& rOriginal)
446 : maVector(rOriginal.maVector),
447 mnUsedEntries(rOriginal.mnUsedEntries)
451 NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
452 : maVector(),
453 mnUsedEntries(0L)
455 NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin());
456 aStart += nIndex;
457 NormalsData3DVector::const_iterator aEnd(aStart);
458 aEnd += nCount;
459 maVector.reserve(nCount);
461 for(; aStart != aEnd; aStart++)
463 if(!aStart->equalZero())
464 mnUsedEntries++;
466 maVector.push_back(*aStart);
470 ~NormalsArray3D()
474 sal_uInt32 count() const
476 return maVector.size();
479 bool operator==(const NormalsArray3D& rCandidate) const
481 return (maVector == rCandidate.maVector);
484 bool isUsed() const
486 return (0L != mnUsedEntries);
489 const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
491 return maVector[nIndex];
494 void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
496 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
497 bool bIsUsed(!rValue.equalZero());
499 if(bWasUsed)
501 if(bIsUsed)
503 maVector[nIndex] = rValue;
505 else
507 maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector();
508 mnUsedEntries--;
511 else
513 if(bIsUsed)
515 maVector[nIndex] = rValue;
516 mnUsedEntries++;
521 void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount)
523 if(nCount)
525 // add nCount copies of rValue
526 NormalsData3DVector::iterator aIndex(maVector.begin());
527 aIndex += nIndex;
528 maVector.insert(aIndex, nCount, rValue);
530 if(!rValue.equalZero())
531 mnUsedEntries += nCount;
535 void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource)
537 const sal_uInt32 nCount(rSource.maVector.size());
539 if(nCount)
541 // insert data
542 NormalsData3DVector::iterator aIndex(maVector.begin());
543 aIndex += nIndex;
544 NormalsData3DVector::const_iterator aStart(rSource.maVector.begin());
545 NormalsData3DVector::const_iterator aEnd(rSource.maVector.end());
546 maVector.insert(aIndex, aStart, aEnd);
548 for(; aStart != aEnd; aStart++)
550 if(!aStart->equalZero())
551 mnUsedEntries++;
556 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
558 if(nCount)
560 const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex);
561 const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount);
562 NormalsData3DVector::const_iterator aStart(aDeleteStart);
564 for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
566 if(!aStart->equalZero())
567 mnUsedEntries--;
570 // remove point data
571 maVector.erase(aDeleteStart, aDeleteEnd);
575 void flip()
577 if(maVector.size() > 1)
579 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
580 NormalsData3DVector::iterator aStart(maVector.begin());
581 NormalsData3DVector::iterator aEnd(maVector.end() - 1L);
583 for(sal_uInt32 a(0); a < nHalfSize; a++)
585 ::std::swap(*aStart, *aEnd);
586 aStart++;
587 aEnd--;
592 void transform(const basegfx::B3DHomMatrix& rMatrix)
594 NormalsData3DVector::iterator aStart(maVector.begin());
595 NormalsData3DVector::iterator aEnd(maVector.end());
597 for(; aStart != aEnd; aStart++)
599 (*aStart) *= rMatrix;
604 //////////////////////////////////////////////////////////////////////////////
606 class TextureCoordinate2D
608 typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector;
610 TextureData2DVector maVector;
611 sal_uInt32 mnUsedEntries;
613 public:
614 explicit TextureCoordinate2D(sal_uInt32 nCount)
615 : maVector(nCount),
616 mnUsedEntries(0L)
620 explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal)
621 : maVector(rOriginal.maVector),
622 mnUsedEntries(rOriginal.mnUsedEntries)
626 TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
627 : maVector(),
628 mnUsedEntries(0L)
630 TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin());
631 aStart += nIndex;
632 TextureData2DVector::const_iterator aEnd(aStart);
633 aEnd += nCount;
634 maVector.reserve(nCount);
636 for(; aStart != aEnd; aStart++)
638 if(!aStart->equalZero())
639 mnUsedEntries++;
641 maVector.push_back(*aStart);
645 ~TextureCoordinate2D()
649 sal_uInt32 count() const
651 return maVector.size();
654 bool operator==(const TextureCoordinate2D& rCandidate) const
656 return (maVector == rCandidate.maVector);
659 bool isUsed() const
661 return (0L != mnUsedEntries);
664 const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
666 return maVector[nIndex];
669 void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
671 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
672 bool bIsUsed(!rValue.equalZero());
674 if(bWasUsed)
676 if(bIsUsed)
678 maVector[nIndex] = rValue;
680 else
682 maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint();
683 mnUsedEntries--;
686 else
688 if(bIsUsed)
690 maVector[nIndex] = rValue;
691 mnUsedEntries++;
696 void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount)
698 if(nCount)
700 // add nCount copies of rValue
701 TextureData2DVector::iterator aIndex(maVector.begin());
702 aIndex += nIndex;
703 maVector.insert(aIndex, nCount, rValue);
705 if(!rValue.equalZero())
706 mnUsedEntries += nCount;
710 void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource)
712 const sal_uInt32 nCount(rSource.maVector.size());
714 if(nCount)
716 // insert data
717 TextureData2DVector::iterator aIndex(maVector.begin());
718 aIndex += nIndex;
719 TextureData2DVector::const_iterator aStart(rSource.maVector.begin());
720 TextureData2DVector::const_iterator aEnd(rSource.maVector.end());
721 maVector.insert(aIndex, aStart, aEnd);
723 for(; aStart != aEnd; aStart++)
725 if(!aStart->equalZero())
726 mnUsedEntries++;
731 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
733 if(nCount)
735 const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
736 const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
737 TextureData2DVector::const_iterator aStart(aDeleteStart);
739 for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
741 if(!aStart->equalZero())
742 mnUsedEntries--;
745 // remove point data
746 maVector.erase(aDeleteStart, aDeleteEnd);
750 void flip()
752 if(maVector.size() > 1)
754 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
755 TextureData2DVector::iterator aStart(maVector.begin());
756 TextureData2DVector::iterator aEnd(maVector.end() - 1L);
758 for(sal_uInt32 a(0); a < nHalfSize; a++)
760 ::std::swap(*aStart, *aEnd);
761 aStart++;
762 aEnd--;
767 void transform(const ::basegfx::B2DHomMatrix& rMatrix)
769 TextureData2DVector::iterator aStart(maVector.begin());
770 TextureData2DVector::iterator aEnd(maVector.end());
772 for(; aStart != aEnd; aStart++)
774 (*aStart) *= rMatrix;
779 //////////////////////////////////////////////////////////////////////////////
781 class ImplB3DPolygon
783 // The point vector. This vector exists always and defines the
784 // count of members.
785 CoordinateDataArray3D maPoints;
787 // The BColor vector. This vectors are created on demand
788 // and may be zero.
789 BColorArray* mpBColors;
791 // The Normals vector. This vectors are created on demand
792 // and may be zero.
793 NormalsArray3D* mpNormals;
795 // The TextureCoordinates vector. This vectors are created on demand
796 // and may be zero.
797 TextureCoordinate2D* mpTextureCoordiantes;
799 // The calculated plane normal. mbPlaneNormalValid says if it's valid.
800 ::basegfx::B3DVector maPlaneNormal;
802 // bitfield
803 // flag which decides if this polygon is opened or closed
804 unsigned mbIsClosed : 1;
806 // flag which says if maPlaneNormal is up-to-date
807 unsigned mbPlaneNormalValid : 1;
809 protected:
810 void invalidatePlaneNormal()
812 if(mbPlaneNormalValid)
814 mbPlaneNormalValid = false;
818 public:
819 // This constructor is only used from the static identity polygon, thus
820 // the RefCount is set to 1 to never 'delete' this static incarnation.
821 ImplB3DPolygon()
822 : maPoints(0L),
823 mpBColors(0L),
824 mpNormals(0L),
825 mpTextureCoordiantes(0L),
826 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
827 mbIsClosed(false),
828 mbPlaneNormalValid(true)
830 // complete initialization with defaults
833 ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied)
834 : maPoints(rToBeCopied.maPoints),
835 mpBColors(0L),
836 mpNormals(0L),
837 mpTextureCoordiantes(0L),
838 maPlaneNormal(rToBeCopied.maPlaneNormal),
839 mbIsClosed(rToBeCopied.mbIsClosed),
840 mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid)
842 // complete initialization using copy
843 if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
845 mpBColors = new BColorArray(*rToBeCopied.mpBColors);
848 if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
850 mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals);
853 if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
855 mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes);
859 ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
860 : maPoints(rToBeCopied.maPoints, nIndex, nCount),
861 mpBColors(0L),
862 mpNormals(0L),
863 mpTextureCoordiantes(0L),
864 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
865 mbIsClosed(rToBeCopied.mbIsClosed),
866 mbPlaneNormalValid(false)
868 // complete initialization using partly copy
869 if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
871 mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount);
873 if(!mpBColors->isUsed())
875 delete mpBColors;
876 mpBColors = 0L;
880 if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
882 mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount);
884 if(!mpNormals->isUsed())
886 delete mpNormals;
887 mpNormals = 0L;
891 if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
893 mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount);
895 if(!mpTextureCoordiantes->isUsed())
897 delete mpTextureCoordiantes;
898 mpTextureCoordiantes = 0L;
903 ~ImplB3DPolygon()
905 if(mpBColors)
907 delete mpBColors;
908 mpBColors = 0L;
911 if(mpNormals)
913 delete mpNormals;
914 mpNormals = 0L;
917 if(mpTextureCoordiantes)
919 delete mpTextureCoordiantes;
920 mpTextureCoordiantes = 0L;
924 sal_uInt32 count() const
926 return maPoints.count();
929 bool isClosed() const
931 return mbIsClosed;
934 void setClosed(bool bNew)
936 if(bNew != (bool)mbIsClosed)
938 mbIsClosed = bNew;
942 inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const
944 bool bBColorsAreEqual(true);
946 if(mpBColors)
948 if(rCandidate.mpBColors)
950 bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors);
952 else
954 // candidate has no BColors, so it's assumed all unused.
955 bBColorsAreEqual = !mpBColors->isUsed();
958 else
960 if(rCandidate.mpBColors)
962 // we have no TextureCoordiantes, so it's assumed all unused.
963 bBColorsAreEqual = !rCandidate.mpBColors->isUsed();
967 return bBColorsAreEqual;
970 inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const
972 bool bNormalsAreEqual(true);
974 if(mpNormals)
976 if(rCandidate.mpNormals)
978 bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals);
980 else
982 // candidate has no normals, so it's assumed all unused.
983 bNormalsAreEqual = !mpNormals->isUsed();
986 else
988 if(rCandidate.mpNormals)
990 // we have no normals, so it's assumed all unused.
991 bNormalsAreEqual = !rCandidate.mpNormals->isUsed();
995 return bNormalsAreEqual;
998 inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const
1000 bool bTextureCoordinatesAreEqual(true);
1002 if(mpTextureCoordiantes)
1004 if(rCandidate.mpTextureCoordiantes)
1006 bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes);
1008 else
1010 // candidate has no TextureCoordinates, so it's assumed all unused.
1011 bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed();
1014 else
1016 if(rCandidate.mpTextureCoordiantes)
1018 // we have no TextureCoordiantes, so it's assumed all unused.
1019 bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed();
1023 return bTextureCoordinatesAreEqual;
1026 bool operator==(const ImplB3DPolygon& rCandidate) const
1028 if(mbIsClosed == rCandidate.mbIsClosed)
1030 if(maPoints == rCandidate.maPoints)
1032 if(impBColorsAreEqual(rCandidate))
1034 if(impNormalsAreEqual(rCandidate))
1036 if(impTextureCoordinatesAreEqual(rCandidate))
1038 return true;
1045 return false;
1048 const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const
1050 return maPoints.getCoordinate(nIndex);
1053 void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue)
1055 maPoints.setCoordinate(nIndex, rValue);
1056 invalidatePlaneNormal();
1059 void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1061 if(nCount)
1063 CoordinateData3D aCoordinate(rPoint);
1064 maPoints.insert(nIndex, aCoordinate, nCount);
1065 invalidatePlaneNormal();
1067 if(mpBColors)
1069 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1072 if(mpNormals)
1074 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1077 if(mpTextureCoordiantes)
1079 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1084 const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
1086 if(mpBColors)
1088 return mpBColors->getBColor(nIndex);
1090 else
1092 return ::basegfx::BColor::getEmptyBColor();
1096 void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
1098 if(!mpBColors)
1100 if(!rValue.equalZero())
1102 mpBColors = new BColorArray(maPoints.count());
1103 mpBColors->setBColor(nIndex, rValue);
1106 else
1108 mpBColors->setBColor(nIndex, rValue);
1110 if(!mpBColors->isUsed())
1112 delete mpBColors;
1113 mpBColors = 0L;
1118 bool areBColorsUsed() const
1120 return (mpBColors && mpBColors->isUsed());
1123 void clearBColors()
1125 if(mpBColors)
1127 delete mpBColors;
1128 mpBColors = 0L;
1132 const ::basegfx::B3DVector& getNormal() const
1134 if(!mbPlaneNormalValid)
1136 const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal();
1137 const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true;
1140 return maPlaneNormal;
1143 const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
1145 if(mpNormals)
1147 return mpNormals->getNormal(nIndex);
1149 else
1151 return ::basegfx::B3DVector::getEmptyVector();
1155 void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
1157 if(!mpNormals)
1159 if(!rValue.equalZero())
1161 mpNormals = new NormalsArray3D(maPoints.count());
1162 mpNormals->setNormal(nIndex, rValue);
1165 else
1167 mpNormals->setNormal(nIndex, rValue);
1169 if(!mpNormals->isUsed())
1171 delete mpNormals;
1172 mpNormals = 0L;
1177 void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
1179 if(mpNormals)
1181 mpNormals->transform(rMatrix);
1185 bool areNormalsUsed() const
1187 return (mpNormals && mpNormals->isUsed());
1190 void clearNormals()
1192 if(mpNormals)
1194 delete mpNormals;
1195 mpNormals = 0L;
1199 const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
1201 if(mpTextureCoordiantes)
1203 return mpTextureCoordiantes->getTextureCoordinate(nIndex);
1205 else
1207 return ::basegfx::B2DPoint::getEmptyPoint();
1211 void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
1213 if(!mpTextureCoordiantes)
1215 if(!rValue.equalZero())
1217 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1218 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1221 else
1223 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1225 if(!mpTextureCoordiantes->isUsed())
1227 delete mpTextureCoordiantes;
1228 mpTextureCoordiantes = 0L;
1233 bool areTextureCoordinatesUsed() const
1235 return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed());
1238 void clearTextureCoordinates()
1240 if(mpTextureCoordiantes)
1242 delete mpTextureCoordiantes;
1243 mpTextureCoordiantes = 0L;
1247 void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
1249 if(mpTextureCoordiantes)
1251 mpTextureCoordiantes->transform(rMatrix);
1255 void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource)
1257 const sal_uInt32 nCount(rSource.maPoints.count());
1259 if(nCount)
1261 maPoints.insert(nIndex, rSource.maPoints);
1262 invalidatePlaneNormal();
1264 if(rSource.mpBColors && rSource.mpBColors->isUsed())
1266 if(!mpBColors)
1268 mpBColors = new BColorArray(maPoints.count());
1271 mpBColors->insert(nIndex, *rSource.mpBColors);
1273 else
1275 if(mpBColors)
1277 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1281 if(rSource.mpNormals && rSource.mpNormals->isUsed())
1283 if(!mpNormals)
1285 mpNormals = new NormalsArray3D(maPoints.count());
1288 mpNormals->insert(nIndex, *rSource.mpNormals);
1290 else
1292 if(mpNormals)
1294 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1298 if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed())
1300 if(!mpTextureCoordiantes)
1302 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1305 mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes);
1307 else
1309 if(mpTextureCoordiantes)
1311 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1317 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1319 if(nCount)
1321 maPoints.remove(nIndex, nCount);
1322 invalidatePlaneNormal();
1324 if(mpBColors)
1326 mpBColors->remove(nIndex, nCount);
1328 if(!mpBColors->isUsed())
1330 delete mpBColors;
1331 mpBColors = 0L;
1335 if(mpNormals)
1337 mpNormals->remove(nIndex, nCount);
1339 if(!mpNormals->isUsed())
1341 delete mpNormals;
1342 mpNormals = 0L;
1346 if(mpTextureCoordiantes)
1348 mpTextureCoordiantes->remove(nIndex, nCount);
1350 if(!mpTextureCoordiantes->isUsed())
1352 delete mpTextureCoordiantes;
1353 mpTextureCoordiantes = 0L;
1359 void flip()
1361 if(maPoints.count() > 1)
1363 maPoints.flip();
1365 if(mbPlaneNormalValid)
1367 // mirror plane normal
1368 maPlaneNormal = -maPlaneNormal;
1371 if(mpBColors)
1373 mpBColors->flip();
1376 if(mpNormals)
1378 mpNormals->flip();
1381 if(mpTextureCoordiantes)
1383 mpTextureCoordiantes->flip();
1388 bool hasDoublePoints() const
1390 if(mbIsClosed)
1392 // check for same start and end point
1393 const sal_uInt32 nIndex(maPoints.count() - 1L);
1395 if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex))
1397 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)));
1399 if(bBColorEqual)
1401 const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)));
1403 if(bNormalsEqual)
1405 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)));
1407 if(bTextureCoordinatesEqual)
1409 return true;
1416 // test for range
1417 for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++)
1419 if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L))
1421 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L)));
1423 if(bBColorEqual)
1425 const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L)));
1427 if(bNormalsEqual)
1429 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L)));
1431 if(bTextureCoordinatesEqual)
1433 return true;
1440 return false;
1443 void removeDoublePointsAtBeginEnd()
1445 // Only remove DoublePoints at Begin and End when poly is closed
1446 if(mbIsClosed)
1448 bool bRemove;
1452 bRemove = false;
1454 if(maPoints.count() > 1L)
1456 const sal_uInt32 nIndex(maPoints.count() - 1L);
1457 bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex));
1459 if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)))
1461 bRemove = false;
1464 if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)))
1466 bRemove = false;
1469 if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)))
1471 bRemove = false;
1475 if(bRemove)
1477 const sal_uInt32 nIndex(maPoints.count() - 1L);
1478 remove(nIndex, 1L);
1480 } while(bRemove);
1484 void removeDoublePointsWholeTrack()
1486 sal_uInt32 nIndex(0L);
1488 // test as long as there are at least two points and as long as the index
1489 // is smaller or equal second last point
1490 while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L))
1492 const sal_uInt32 nNextIndex(nIndex + 1L);
1493 bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex));
1495 if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex)))
1497 bRemove = false;
1500 if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex)))
1502 bRemove = false;
1505 if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex)))
1507 bRemove = false;
1510 if(bRemove)
1512 // if next is same as index and the control vectors are unused, delete index
1513 remove(nIndex, 1L);
1515 else
1517 // if different, step forward
1518 nIndex++;
1523 void transform(const ::basegfx::B3DHomMatrix& rMatrix)
1525 maPoints.transform(rMatrix);
1527 // Here, it seems to be possible to transform a valid plane normal and to avoid
1528 // invalidation, but it's not true. If the transformation contains shears or e.g.
1529 // perspective projection, the orthogonality to the transformed plane will not
1530 // be preserved. It may be possible to test that at the matrix to not invalidate in
1531 // all cases or to extract a matrix which does not 'shear' the vector which is
1532 // a normal in this case. As long as this is not sure, i will just invalidate.
1533 invalidatePlaneNormal();
1537 //////////////////////////////////////////////////////////////////////////////
1539 namespace basegfx
1541 namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType,
1542 DefaultPolygon > {}; }
1544 B3DPolygon::B3DPolygon() :
1545 mpPolygon(DefaultPolygon::get())
1549 B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) :
1550 mpPolygon(rPolygon.mpPolygon)
1554 B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount) :
1555 mpPolygon(ImplB3DPolygon(*rPolygon.mpPolygon, nIndex, nCount))
1557 // TODO(P2): one extra temporary here (cow_wrapper copies
1558 // given ImplB3DPolygon into its internal impl_t wrapper type)
1559 OSL_ENSURE(nIndex + nCount > rPolygon.mpPolygon->count(), "B3DPolygon constructor outside range (!)");
1562 B3DPolygon::~B3DPolygon()
1566 B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon)
1568 mpPolygon = rPolygon.mpPolygon;
1569 return *this;
1572 void B3DPolygon::makeUnique()
1574 mpPolygon.make_unique();
1577 bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const
1579 if(mpPolygon.same_object(rPolygon.mpPolygon))
1580 return true;
1582 return (*mpPolygon == *rPolygon.mpPolygon);
1585 bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const
1587 return !(*this == rPolygon);
1590 sal_uInt32 B3DPolygon::count() const
1592 return mpPolygon->count();
1595 basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const
1597 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1599 return mpPolygon->getPoint(nIndex);
1602 void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
1604 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1606 if(getB3DPoint(nIndex) != rValue)
1607 mpPolygon->setPoint(nIndex, rValue);
1610 BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const
1612 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1614 return mpPolygon->getBColor(nIndex);
1617 void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue)
1619 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1621 if(mpPolygon->getBColor(nIndex) != rValue)
1622 mpPolygon->setBColor(nIndex, rValue);
1625 bool B3DPolygon::areBColorsUsed() const
1627 return mpPolygon->areBColorsUsed();
1630 void B3DPolygon::clearBColors()
1632 if(mpPolygon->areBColorsUsed())
1633 mpPolygon->clearBColors();
1636 B3DVector B3DPolygon::getNormal() const
1638 return mpPolygon->getNormal();
1641 B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const
1643 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1645 return mpPolygon->getNormal(nIndex);
1648 void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue)
1650 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1652 if(mpPolygon->getNormal(nIndex) != rValue)
1653 mpPolygon->setNormal(nIndex, rValue);
1656 void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix)
1658 if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity())
1659 mpPolygon->transformNormals(rMatrix);
1662 bool B3DPolygon::areNormalsUsed() const
1664 return mpPolygon->areNormalsUsed();
1667 void B3DPolygon::clearNormals()
1669 if(mpPolygon->areNormalsUsed())
1670 mpPolygon->clearNormals();
1673 B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const
1675 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1677 return mpPolygon->getTextureCoordinate(nIndex);
1680 void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue)
1682 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1684 if(mpPolygon->getTextureCoordinate(nIndex) != rValue)
1685 mpPolygon->setTextureCoordinate(nIndex, rValue);
1688 void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
1690 if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity())
1691 mpPolygon->transformTextureCoordinates(rMatrix);
1694 bool B3DPolygon::areTextureCoordinatesUsed() const
1696 return mpPolygon->areTextureCoordinatesUsed();
1699 void B3DPolygon::clearTextureCoordinates()
1701 if(mpPolygon->areTextureCoordinatesUsed())
1702 mpPolygon->clearTextureCoordinates();
1705 void B3DPolygon::insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1707 OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1709 if(nCount)
1710 mpPolygon->insert(nIndex, rPoint, nCount);
1713 void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1715 if(nCount)
1716 mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1719 void B3DPolygon::insert(sal_uInt32 nIndex, const B3DPolygon& rPoly, sal_uInt32 nIndex2, sal_uInt32 nCount)
1721 OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1723 if(rPoly.count())
1725 if(!nCount)
1727 nCount = rPoly.count();
1730 if(0L == nIndex2 && nCount == rPoly.count())
1732 mpPolygon->insert(nIndex, *rPoly.mpPolygon);
1734 else
1736 OSL_ENSURE(nIndex2 + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1737 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex2, nCount);
1738 mpPolygon->insert(nIndex, aTempPoly);
1743 void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
1745 if(rPoly.count())
1747 if(!nCount)
1749 nCount = rPoly.count();
1752 if(0L == nIndex && nCount == rPoly.count())
1754 mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
1756 else
1758 OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)");
1759 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
1760 mpPolygon->insert(mpPolygon->count(), aTempPoly);
1765 void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1767 OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)");
1769 if(nCount)
1770 mpPolygon->remove(nIndex, nCount);
1773 void B3DPolygon::clear()
1775 mpPolygon = DefaultPolygon::get();
1778 bool B3DPolygon::isClosed() const
1780 return mpPolygon->isClosed();
1783 void B3DPolygon::setClosed(bool bNew)
1785 if(isClosed() != bNew)
1786 mpPolygon->setClosed(bNew);
1789 void B3DPolygon::flip()
1791 if(count() > 1)
1792 mpPolygon->flip();
1795 bool B3DPolygon::hasDoublePoints() const
1797 return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints());
1800 void B3DPolygon::removeDoublePoints()
1802 if(hasDoublePoints())
1804 mpPolygon->removeDoublePointsAtBeginEnd();
1805 mpPolygon->removeDoublePointsWholeTrack();
1809 void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix)
1811 if(mpPolygon->count() && !rMatrix.isIdentity())
1813 mpPolygon->transform(rMatrix);
1816 } // end of namespace basegfx
1818 //////////////////////////////////////////////////////////////////////////////
1819 // eof