1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: b3dpolygon.cxx,v $
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>
44 //////////////////////////////////////////////////////////////////////////////
46 class CoordinateData3D
48 basegfx::B3DPoint maPoint
;
56 explicit CoordinateData3D(const basegfx::B3DPoint
& rData
)
61 const basegfx::B3DPoint
& getCoordinate() const
66 void setCoordinate(const basegfx::B3DPoint
& rValue
)
72 bool operator==(const CoordinateData3D
& rData
) const
74 return (maPoint
== rData
.getCoordinate());
77 void transform(const basegfx::B3DHomMatrix
& rMatrix
)
83 //////////////////////////////////////////////////////////////////////////////
85 class CoordinateDataArray3D
87 typedef ::std::vector
< CoordinateData3D
> CoordinateData3DVector
;
89 CoordinateData3DVector maVector
;
92 explicit CoordinateDataArray3D(sal_uInt32 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());
118 sal_uInt32
nISmallest(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()))
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
))
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
))
163 // we always have a minimal point. If we also have a different next and previous,
164 // we can calculate the normal
167 const basegfx::B3DVector
aPrev(*pPrev
- *pSmallest
);
168 const basegfx::B3DVector
aNext(*pNext
- *pSmallest
);
170 aRetval
= cross(aPrev
, aNext
);
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
)
202 // add nCount copies of rValue
203 CoordinateData3DVector::iterator
aIndex(maVector
.begin());
205 maVector
.insert(aIndex
, nCount
, rValue
);
209 void insert(sal_uInt32 nIndex
, const CoordinateDataArray3D
& rSource
)
211 const sal_uInt32
nCount(rSource
.maVector
.size());
216 CoordinateData3DVector::iterator
aIndex(maVector
.begin());
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
)
229 CoordinateData3DVector::iterator
aStart(maVector
.begin());
231 const CoordinateData3DVector::iterator
aEnd(aStart
+ nCount
);
232 maVector
.erase(aStart
, aEnd
);
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
);
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 //////////////////////////////////////////////////////////////////////////////
269 typedef ::std::vector
< ::basegfx::BColor
> BColorDataVector
;
271 BColorDataVector maVector
;
272 sal_uInt32 mnUsedEntries
;
275 explicit BColorArray(sal_uInt32 nCount
)
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
)
291 BColorDataVector::const_iterator
aStart(rOriginal
.maVector
.begin());
293 BColorDataVector::const_iterator
aEnd(aStart
);
295 maVector
.reserve(nCount
);
297 for(; aStart
!= aEnd
; aStart
++)
299 if(!aStart
->equalZero())
302 maVector
.push_back(*aStart
);
310 sal_uInt32
count() const
312 return maVector
.size();
315 bool operator==(const BColorArray
& rCandidate
) const
317 return (maVector
== rCandidate
.maVector
);
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());
339 maVector
[nIndex
] = rValue
;
343 maVector
[nIndex
] = ::basegfx::BColor::getEmptyBColor();
351 maVector
[nIndex
] = rValue
;
357 void insert(sal_uInt32 nIndex
, const ::basegfx::BColor
& rValue
, sal_uInt32 nCount
)
361 // add nCount copies of rValue
362 BColorDataVector::iterator
aIndex(maVector
.begin());
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());
378 BColorDataVector::iterator
aIndex(maVector
.begin());
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())
392 void remove(sal_uInt32 nIndex
, sal_uInt32 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())
407 maVector
.erase(aDeleteStart
, aDeleteEnd
);
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
);
429 //////////////////////////////////////////////////////////////////////////////
433 typedef ::std::vector
< ::basegfx::B3DVector
> NormalsData3DVector
;
435 NormalsData3DVector maVector
;
436 sal_uInt32 mnUsedEntries
;
439 explicit NormalsArray3D(sal_uInt32 nCount
)
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
)
455 NormalsData3DVector::const_iterator
aStart(rOriginal
.maVector
.begin());
457 NormalsData3DVector::const_iterator
aEnd(aStart
);
459 maVector
.reserve(nCount
);
461 for(; aStart
!= aEnd
; aStart
++)
463 if(!aStart
->equalZero())
466 maVector
.push_back(*aStart
);
474 sal_uInt32
count() const
476 return maVector
.size();
479 bool operator==(const NormalsArray3D
& rCandidate
) const
481 return (maVector
== rCandidate
.maVector
);
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());
503 maVector
[nIndex
] = rValue
;
507 maVector
[nIndex
] = ::basegfx::B3DVector::getEmptyVector();
515 maVector
[nIndex
] = rValue
;
521 void insert(sal_uInt32 nIndex
, const ::basegfx::B3DVector
& rValue
, sal_uInt32 nCount
)
525 // add nCount copies of rValue
526 NormalsData3DVector::iterator
aIndex(maVector
.begin());
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());
542 NormalsData3DVector::iterator
aIndex(maVector
.begin());
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())
556 void remove(sal_uInt32 nIndex
, sal_uInt32 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())
571 maVector
.erase(aDeleteStart
, aDeleteEnd
);
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
);
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
;
614 explicit TextureCoordinate2D(sal_uInt32 nCount
)
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
)
630 TextureData2DVector::const_iterator
aStart(rOriginal
.maVector
.begin());
632 TextureData2DVector::const_iterator
aEnd(aStart
);
634 maVector
.reserve(nCount
);
636 for(; aStart
!= aEnd
; aStart
++)
638 if(!aStart
->equalZero())
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
);
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());
678 maVector
[nIndex
] = rValue
;
682 maVector
[nIndex
] = ::basegfx::B2DPoint::getEmptyPoint();
690 maVector
[nIndex
] = rValue
;
696 void insert(sal_uInt32 nIndex
, const ::basegfx::B2DPoint
& rValue
, sal_uInt32 nCount
)
700 // add nCount copies of rValue
701 TextureData2DVector::iterator
aIndex(maVector
.begin());
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());
717 TextureData2DVector::iterator
aIndex(maVector
.begin());
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())
731 void remove(sal_uInt32 nIndex
, sal_uInt32 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())
746 maVector
.erase(aDeleteStart
, aDeleteEnd
);
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
);
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 //////////////////////////////////////////////////////////////////////////////
783 // The point vector. This vector exists always and defines the
785 CoordinateDataArray3D maPoints
;
787 // The BColor vector. This vectors are created on demand
789 BColorArray
* mpBColors
;
791 // The Normals vector. This vectors are created on demand
793 NormalsArray3D
* mpNormals
;
795 // The TextureCoordinates vector. This vectors are created on demand
797 TextureCoordinate2D
* mpTextureCoordiantes
;
799 // The calculated plane normal. mbPlaneNormalValid says if it's valid.
800 ::basegfx::B3DVector maPlaneNormal
;
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;
810 void invalidatePlaneNormal()
812 if(mbPlaneNormalValid
)
814 mbPlaneNormalValid
= false;
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.
825 mpTextureCoordiantes(0L),
826 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
828 mbPlaneNormalValid(true)
830 // complete initialization with defaults
833 ImplB3DPolygon(const ImplB3DPolygon
& rToBeCopied
)
834 : maPoints(rToBeCopied
.maPoints
),
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
),
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())
880 if(rToBeCopied
.mpNormals
&& rToBeCopied
.mpNormals
->isUsed())
882 mpNormals
= new NormalsArray3D(*rToBeCopied
.mpNormals
, nIndex
, nCount
);
884 if(!mpNormals
->isUsed())
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;
917 if(mpTextureCoordiantes
)
919 delete mpTextureCoordiantes
;
920 mpTextureCoordiantes
= 0L;
924 sal_uInt32
count() const
926 return maPoints
.count();
929 bool isClosed() const
934 void setClosed(bool bNew
)
936 if(bNew
!= (bool)mbIsClosed
)
942 inline bool impBColorsAreEqual(const ImplB3DPolygon
& rCandidate
) const
944 bool bBColorsAreEqual(true);
948 if(rCandidate
.mpBColors
)
950 bBColorsAreEqual
= (*mpBColors
== *rCandidate
.mpBColors
);
954 // candidate has no BColors, so it's assumed all unused.
955 bBColorsAreEqual
= !mpBColors
->isUsed();
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);
976 if(rCandidate
.mpNormals
)
978 bNormalsAreEqual
= (*mpNormals
== *rCandidate
.mpNormals
);
982 // candidate has no normals, so it's assumed all unused.
983 bNormalsAreEqual
= !mpNormals
->isUsed();
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
);
1010 // candidate has no TextureCoordinates, so it's assumed all unused.
1011 bTextureCoordinatesAreEqual
= !mpTextureCoordiantes
->isUsed();
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
))
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
)
1063 CoordinateData3D
aCoordinate(rPoint
);
1064 maPoints
.insert(nIndex
, aCoordinate
, nCount
);
1065 invalidatePlaneNormal();
1069 mpBColors
->insert(nIndex
, ::basegfx::BColor::getEmptyBColor(), nCount
);
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
1088 return mpBColors
->getBColor(nIndex
);
1092 return ::basegfx::BColor::getEmptyBColor();
1096 void setBColor(sal_uInt32 nIndex
, const ::basegfx::BColor
& rValue
)
1100 if(!rValue
.equalZero())
1102 mpBColors
= new BColorArray(maPoints
.count());
1103 mpBColors
->setBColor(nIndex
, rValue
);
1108 mpBColors
->setBColor(nIndex
, rValue
);
1110 if(!mpBColors
->isUsed())
1118 bool areBColorsUsed() const
1120 return (mpBColors
&& mpBColors
->isUsed());
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
1147 return mpNormals
->getNormal(nIndex
);
1151 return ::basegfx::B3DVector::getEmptyVector();
1155 void setNormal(sal_uInt32 nIndex
, const ::basegfx::B3DVector
& rValue
)
1159 if(!rValue
.equalZero())
1161 mpNormals
= new NormalsArray3D(maPoints
.count());
1162 mpNormals
->setNormal(nIndex
, rValue
);
1167 mpNormals
->setNormal(nIndex
, rValue
);
1169 if(!mpNormals
->isUsed())
1177 void transformNormals(const ::basegfx::B3DHomMatrix
& rMatrix
)
1181 mpNormals
->transform(rMatrix
);
1185 bool areNormalsUsed() const
1187 return (mpNormals
&& mpNormals
->isUsed());
1199 const ::basegfx::B2DPoint
& getTextureCoordinate(sal_uInt32 nIndex
) const
1201 if(mpTextureCoordiantes
)
1203 return mpTextureCoordiantes
->getTextureCoordinate(nIndex
);
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
);
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());
1261 maPoints
.insert(nIndex
, rSource
.maPoints
);
1262 invalidatePlaneNormal();
1264 if(rSource
.mpBColors
&& rSource
.mpBColors
->isUsed())
1268 mpBColors
= new BColorArray(maPoints
.count());
1271 mpBColors
->insert(nIndex
, *rSource
.mpBColors
);
1277 mpBColors
->insert(nIndex
, ::basegfx::BColor::getEmptyBColor(), nCount
);
1281 if(rSource
.mpNormals
&& rSource
.mpNormals
->isUsed())
1285 mpNormals
= new NormalsArray3D(maPoints
.count());
1288 mpNormals
->insert(nIndex
, *rSource
.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
);
1309 if(mpTextureCoordiantes
)
1311 mpTextureCoordiantes
->insert(nIndex
, ::basegfx::B2DPoint::getEmptyPoint(), nCount
);
1317 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
1321 maPoints
.remove(nIndex
, nCount
);
1322 invalidatePlaneNormal();
1326 mpBColors
->remove(nIndex
, nCount
);
1328 if(!mpBColors
->isUsed())
1337 mpNormals
->remove(nIndex
, nCount
);
1339 if(!mpNormals
->isUsed())
1346 if(mpTextureCoordiantes
)
1348 mpTextureCoordiantes
->remove(nIndex
, nCount
);
1350 if(!mpTextureCoordiantes
->isUsed())
1352 delete mpTextureCoordiantes
;
1353 mpTextureCoordiantes
= 0L;
1361 if(maPoints
.count() > 1)
1365 if(mbPlaneNormalValid
)
1367 // mirror plane normal
1368 maPlaneNormal
= -maPlaneNormal
;
1381 if(mpTextureCoordiantes
)
1383 mpTextureCoordiantes
->flip();
1388 bool hasDoublePoints() const
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
)));
1401 const bool bNormalsEqual(!mpNormals
|| (mpNormals
->getNormal(0L) == mpNormals
->getNormal(nIndex
)));
1405 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes
|| (mpTextureCoordiantes
->getTextureCoordinate(0L) == mpTextureCoordiantes
->getTextureCoordinate(nIndex
)));
1407 if(bTextureCoordinatesEqual
)
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)));
1425 const bool bNormalsEqual(!mpNormals
|| (mpNormals
->getNormal(a
) == mpNormals
->getNormal(a
+ 1L)));
1429 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes
|| (mpTextureCoordiantes
->getTextureCoordinate(a
) == mpTextureCoordiantes
->getTextureCoordinate(a
+ 1L)));
1431 if(bTextureCoordinatesEqual
)
1443 void removeDoublePointsAtBeginEnd()
1445 // Only remove DoublePoints at Begin and End when poly is closed
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
)))
1464 if(bRemove
&& mpNormals
&& !(mpNormals
->getNormal(0L) == mpNormals
->getNormal(nIndex
)))
1469 if(bRemove
&& mpTextureCoordiantes
&& !(mpTextureCoordiantes
->getTextureCoordinate(0L) == mpTextureCoordiantes
->getTextureCoordinate(nIndex
)))
1477 const sal_uInt32
nIndex(maPoints
.count() - 1L);
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
)))
1500 if(bRemove
&& mpNormals
&& !(mpNormals
->getNormal(nIndex
) == mpNormals
->getNormal(nNextIndex
)))
1505 if(bRemove
&& mpTextureCoordiantes
&& !(mpTextureCoordiantes
->getTextureCoordinate(nIndex
) == mpTextureCoordiantes
->getTextureCoordinate(nNextIndex
)))
1512 // if next is same as index and the control vectors are unused, delete index
1517 // if different, step forward
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 //////////////////////////////////////////////////////////////////////////////
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
;
1572 void B3DPolygon::makeUnique()
1574 mpPolygon
.make_unique();
1577 bool B3DPolygon::operator==(const B3DPolygon
& rPolygon
) const
1579 if(mpPolygon
.same_object(rPolygon
.mpPolygon
))
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 (!)");
1710 mpPolygon
->insert(nIndex
, rPoint
, nCount
);
1713 void B3DPolygon::append(const basegfx::B3DPoint
& rPoint
, sal_uInt32 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 (!)");
1727 nCount
= rPoly
.count();
1730 if(0L == nIndex2
&& nCount
== rPoly
.count())
1732 mpPolygon
->insert(nIndex
, *rPoly
.mpPolygon
);
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
)
1749 nCount
= rPoly
.count();
1752 if(0L == nIndex
&& nCount
== rPoly
.count())
1754 mpPolygon
->insert(mpPolygon
->count(), *rPoly
.mpPolygon
);
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 (!)");
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()
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 //////////////////////////////////////////////////////////////////////////////