1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
31 class CoordinateData3D
33 basegfx::B3DPoint maPoint
;
41 explicit CoordinateData3D(const basegfx::B3DPoint
& rData
)
46 const basegfx::B3DPoint
& getCoordinate() const
51 void setCoordinate(const basegfx::B3DPoint
& rValue
)
57 bool operator==(const CoordinateData3D
& rData
) const
59 return (maPoint
== rData
.getCoordinate());
62 void transform(const basegfx::B3DHomMatrix
& rMatrix
)
68 class CoordinateDataArray3D
70 typedef ::std::vector
< CoordinateData3D
> CoordinateData3DVector
;
72 CoordinateData3DVector maVector
;
75 explicit CoordinateDataArray3D(sal_uInt32 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());
101 sal_uInt32
nISmallest(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()))
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
))
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
))
146 // we always have a minimal point. If we also have a different next and previous,
147 // we can calculate the normal
150 const basegfx::B3DVector
aPrev(*pPrev
- *pSmallest
);
151 const basegfx::B3DVector
aNext(*pNext
- *pSmallest
);
153 aRetval
= cross(aPrev
, aNext
);
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
)
185 // add nCount copies of rValue
186 CoordinateData3DVector::iterator
aIndex(maVector
.begin());
188 maVector
.insert(aIndex
, nCount
, rValue
);
192 void insert(sal_uInt32 nIndex
, const CoordinateDataArray3D
& rSource
)
194 const sal_uInt32
nCount(rSource
.maVector
.size());
199 CoordinateData3DVector::iterator
aIndex(maVector
.begin());
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
)
212 CoordinateData3DVector::iterator
aStart(maVector
.begin());
214 const CoordinateData3DVector::iterator
aEnd(aStart
+ nCount
);
215 maVector
.erase(aStart
, aEnd
);
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
);
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
);
250 typedef ::std::vector
< ::basegfx::BColor
> BColorDataVector
;
252 BColorDataVector maVector
;
253 sal_uInt32 mnUsedEntries
;
256 explicit BColorArray(sal_uInt32 nCount
)
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
)
272 BColorDataVector::const_iterator
aStart(rOriginal
.maVector
.begin());
274 BColorDataVector::const_iterator
aEnd(aStart
);
275 assert(nCount
<= rOriginal
.maVector
.size());
277 maVector
.reserve(nCount
);
279 for(; aStart
!= aEnd
; ++aStart
)
281 if(!aStart
->equalZero())
284 maVector
.push_back(*aStart
);
292 bool operator==(const BColorArray
& rCandidate
) const
294 return (maVector
== rCandidate
.maVector
);
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());
316 maVector
[nIndex
] = rValue
;
320 maVector
[nIndex
] = ::basegfx::BColor::getEmptyBColor();
328 maVector
[nIndex
] = rValue
;
334 void insert(sal_uInt32 nIndex
, const ::basegfx::BColor
& rValue
, sal_uInt32 nCount
)
338 // add nCount copies of rValue
339 BColorDataVector::iterator
aIndex(maVector
.begin());
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());
355 BColorDataVector::iterator
aIndex(maVector
.begin());
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())
369 void remove(sal_uInt32 nIndex
, sal_uInt32 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())
384 maVector
.erase(aDeleteStart
, aDeleteEnd
);
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
);
408 typedef ::std::vector
< ::basegfx::B3DVector
> NormalsData3DVector
;
410 NormalsData3DVector maVector
;
411 sal_uInt32 mnUsedEntries
;
414 explicit NormalsArray3D(sal_uInt32 nCount
)
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
)
430 NormalsData3DVector::const_iterator
aStart(rOriginal
.maVector
.begin());
432 NormalsData3DVector::const_iterator
aEnd(aStart
);
434 maVector
.reserve(nCount
);
436 for(; aStart
!= aEnd
; ++aStart
)
438 if(!aStart
->equalZero())
441 maVector
.push_back(*aStart
);
449 bool operator==(const NormalsArray3D
& rCandidate
) const
451 return (maVector
== rCandidate
.maVector
);
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());
473 maVector
[nIndex
] = rValue
;
477 maVector
[nIndex
] = ::basegfx::B3DVector::getEmptyVector();
485 maVector
[nIndex
] = rValue
;
491 void insert(sal_uInt32 nIndex
, const ::basegfx::B3DVector
& rValue
, sal_uInt32 nCount
)
495 // add nCount copies of rValue
496 NormalsData3DVector::iterator
aIndex(maVector
.begin());
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());
512 NormalsData3DVector::iterator
aIndex(maVector
.begin());
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())
526 void remove(sal_uInt32 nIndex
, sal_uInt32 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())
541 maVector
.erase(aDeleteStart
, aDeleteEnd
);
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
);
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
;
581 explicit TextureCoordinate2D(sal_uInt32 nCount
)
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
)
597 TextureData2DVector::const_iterator
aStart(rOriginal
.maVector
.begin());
599 TextureData2DVector::const_iterator
aEnd(aStart
);
601 maVector
.reserve(nCount
);
603 for(; aStart
!= aEnd
; ++aStart
)
605 if(!aStart
->equalZero())
608 maVector
.push_back(*aStart
);
612 ~TextureCoordinate2D()
616 bool operator==(const TextureCoordinate2D
& rCandidate
) const
618 return (maVector
== rCandidate
.maVector
);
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());
640 maVector
[nIndex
] = rValue
;
644 maVector
[nIndex
] = ::basegfx::B2DPoint::getEmptyPoint();
652 maVector
[nIndex
] = rValue
;
658 void insert(sal_uInt32 nIndex
, const ::basegfx::B2DPoint
& rValue
, sal_uInt32 nCount
)
662 // add nCount copies of rValue
663 TextureData2DVector::iterator
aIndex(maVector
.begin());
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());
679 TextureData2DVector::iterator
aIndex(maVector
.begin());
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())
693 void remove(sal_uInt32 nIndex
, sal_uInt32 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())
708 maVector
.erase(aDeleteStart
, aDeleteEnd
);
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
);
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
;
742 // The point vector. This vector exists always and defines the
744 CoordinateDataArray3D maPoints
;
746 // The BColor vector. This vectors are created on demand
748 BColorArray
* mpBColors
;
750 // The Normals vector. This vectors are created on demand
752 NormalsArray3D
* mpNormals
;
754 // The TextureCoordinates vector. This vectors are created on demand
756 TextureCoordinate2D
* mpTextureCoordiantes
;
758 // The calculated plane normal. mbPlaneNormalValid says if it's valid.
759 ::basegfx::B3DVector maPlaneNormal
;
762 // flag which decides if this polygon is opened or closed
765 // flag which says if maPlaneNormal is up-to-date
766 bool mbPlaneNormalValid
: 1;
769 void invalidatePlaneNormal()
771 if(mbPlaneNormalValid
)
773 mbPlaneNormalValid
= false;
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.
784 mpTextureCoordiantes(0L),
785 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
787 mbPlaneNormalValid(true)
789 // complete initialization with defaults
792 ImplB3DPolygon(const ImplB3DPolygon
& rToBeCopied
)
793 : maPoints(rToBeCopied
.maPoints
),
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
),
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())
839 if(rToBeCopied
.mpNormals
&& rToBeCopied
.mpNormals
->isUsed())
841 mpNormals
= new NormalsArray3D(*rToBeCopied
.mpNormals
, nIndex
, nCount
);
843 if(!mpNormals
->isUsed())
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;
876 if(mpTextureCoordiantes
)
878 delete mpTextureCoordiantes
;
879 mpTextureCoordiantes
= 0L;
883 sal_uInt32
count() const
885 return maPoints
.count();
888 bool isClosed() const
893 void setClosed(bool bNew
)
895 if(bNew
!= (bool)mbIsClosed
)
901 inline bool impBColorsAreEqual(const ImplB3DPolygon
& rCandidate
) const
903 bool bBColorsAreEqual(true);
907 if(rCandidate
.mpBColors
)
909 bBColorsAreEqual
= (*mpBColors
== *rCandidate
.mpBColors
);
913 // candidate has no BColors, so it's assumed all unused.
914 bBColorsAreEqual
= !mpBColors
->isUsed();
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);
935 if(rCandidate
.mpNormals
)
937 bNormalsAreEqual
= (*mpNormals
== *rCandidate
.mpNormals
);
941 // candidate has no normals, so it's assumed all unused.
942 bNormalsAreEqual
= !mpNormals
->isUsed();
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
);
969 // candidate has no TextureCoordinates, so it's assumed all unused.
970 bTextureCoordinatesAreEqual
= !mpTextureCoordiantes
->isUsed();
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
))
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
)
1022 CoordinateData3D
aCoordinate(rPoint
);
1023 maPoints
.insert(nIndex
, aCoordinate
, nCount
);
1024 invalidatePlaneNormal();
1028 mpBColors
->insert(nIndex
, ::basegfx::BColor::getEmptyBColor(), nCount
);
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
1047 return mpBColors
->getBColor(nIndex
);
1051 return ::basegfx::BColor::getEmptyBColor();
1055 void setBColor(sal_uInt32 nIndex
, const ::basegfx::BColor
& rValue
)
1059 if(!rValue
.equalZero())
1061 mpBColors
= new BColorArray(maPoints
.count());
1062 mpBColors
->setBColor(nIndex
, rValue
);
1067 mpBColors
->setBColor(nIndex
, rValue
);
1069 if(!mpBColors
->isUsed())
1077 bool areBColorsUsed() const
1079 return (mpBColors
&& mpBColors
->isUsed());
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
1106 return mpNormals
->getNormal(nIndex
);
1110 return ::basegfx::B3DVector::getEmptyVector();
1114 void setNormal(sal_uInt32 nIndex
, const ::basegfx::B3DVector
& rValue
)
1118 if(!rValue
.equalZero())
1120 mpNormals
= new NormalsArray3D(maPoints
.count());
1121 mpNormals
->setNormal(nIndex
, rValue
);
1126 mpNormals
->setNormal(nIndex
, rValue
);
1128 if(!mpNormals
->isUsed())
1136 void transformNormals(const ::basegfx::B3DHomMatrix
& rMatrix
)
1140 mpNormals
->transform(rMatrix
);
1144 bool areNormalsUsed() const
1146 return (mpNormals
&& mpNormals
->isUsed());
1158 const ::basegfx::B2DPoint
& getTextureCoordinate(sal_uInt32 nIndex
) const
1160 if(mpTextureCoordiantes
)
1162 return mpTextureCoordiantes
->getTextureCoordinate(nIndex
);
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
);
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());
1220 maPoints
.insert(nIndex
, rSource
.maPoints
);
1221 invalidatePlaneNormal();
1223 if(rSource
.mpBColors
&& rSource
.mpBColors
->isUsed())
1227 mpBColors
= new BColorArray(maPoints
.count());
1230 mpBColors
->insert(nIndex
, *rSource
.mpBColors
);
1236 mpBColors
->insert(nIndex
, ::basegfx::BColor::getEmptyBColor(), nCount
);
1240 if(rSource
.mpNormals
&& rSource
.mpNormals
->isUsed())
1244 mpNormals
= new NormalsArray3D(maPoints
.count());
1247 mpNormals
->insert(nIndex
, *rSource
.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
);
1268 if(mpTextureCoordiantes
)
1270 mpTextureCoordiantes
->insert(nIndex
, ::basegfx::B2DPoint::getEmptyPoint(), nCount
);
1276 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
1280 maPoints
.remove(nIndex
, nCount
);
1281 invalidatePlaneNormal();
1285 mpBColors
->remove(nIndex
, nCount
);
1287 if(!mpBColors
->isUsed())
1296 mpNormals
->remove(nIndex
, nCount
);
1298 if(!mpNormals
->isUsed())
1305 if(mpTextureCoordiantes
)
1307 mpTextureCoordiantes
->remove(nIndex
, nCount
);
1309 if(!mpTextureCoordiantes
->isUsed())
1311 delete mpTextureCoordiantes
;
1312 mpTextureCoordiantes
= 0L;
1320 if(maPoints
.count() > 1)
1324 if(mbPlaneNormalValid
)
1326 // mirror plane normal
1327 maPlaneNormal
= -maPlaneNormal
;
1340 if(mpTextureCoordiantes
)
1342 mpTextureCoordiantes
->flip();
1347 bool hasDoublePoints() const
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
)));
1360 const bool bNormalsEqual(!mpNormals
|| (mpNormals
->getNormal(0L) == mpNormals
->getNormal(nIndex
)));
1364 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes
|| (mpTextureCoordiantes
->getTextureCoordinate(0L) == mpTextureCoordiantes
->getTextureCoordinate(nIndex
)));
1366 if(bTextureCoordinatesEqual
)
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)));
1384 const bool bNormalsEqual(!mpNormals
|| (mpNormals
->getNormal(a
) == mpNormals
->getNormal(a
+ 1L)));
1388 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes
|| (mpTextureCoordiantes
->getTextureCoordinate(a
) == mpTextureCoordiantes
->getTextureCoordinate(a
+ 1L)));
1390 if(bTextureCoordinatesEqual
)
1402 void removeDoublePointsAtBeginEnd()
1404 // Only remove DoublePoints at Begin and End when poly is closed
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
)))
1423 if(bRemove
&& mpNormals
&& !(mpNormals
->getNormal(0L) == mpNormals
->getNormal(nIndex
)))
1428 if(bRemove
&& mpTextureCoordiantes
&& !(mpTextureCoordiantes
->getTextureCoordinate(0L) == mpTextureCoordiantes
->getTextureCoordinate(nIndex
)))
1436 const sal_uInt32
nIndex(maPoints
.count() - 1L);
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
)))
1459 if(bRemove
&& mpNormals
&& !(mpNormals
->getNormal(nIndex
) == mpNormals
->getNormal(nNextIndex
)))
1464 if(bRemove
&& mpTextureCoordiantes
&& !(mpTextureCoordiantes
->getTextureCoordinate(nIndex
) == mpTextureCoordiantes
->getTextureCoordinate(nNextIndex
)))
1471 // if next is same as index and the control vectors are unused, delete index
1476 // if different, step forward
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();
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
;
1521 bool B3DPolygon::operator==(const B3DPolygon
& rPolygon
) const
1523 if(mpPolygon
.same_object(rPolygon
.mpPolygon
))
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
)
1652 mpPolygon
->insert(mpPolygon
->count(), rPoint
, nCount
);
1655 void B3DPolygon::append(const B3DPolygon
& rPoly
, sal_uInt32 nIndex
, sal_uInt32 nCount
)
1661 nCount
= rPoly
.count();
1664 if(0L == nIndex
&& nCount
== rPoly
.count())
1666 mpPolygon
->insert(mpPolygon
->count(), *rPoly
.mpPolygon
);
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 (!)");
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()
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: */