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 //////////////////////////////////////////////////////////////////////////////
33 class CoordinateData3D
35 basegfx::B3DPoint maPoint
;
43 explicit CoordinateData3D(const basegfx::B3DPoint
& rData
)
48 const basegfx::B3DPoint
& getCoordinate() const
53 void setCoordinate(const basegfx::B3DPoint
& rValue
)
59 bool operator==(const CoordinateData3D
& rData
) const
61 return (maPoint
== rData
.getCoordinate());
64 void transform(const basegfx::B3DHomMatrix
& rMatrix
)
70 //////////////////////////////////////////////////////////////////////////////
72 class CoordinateDataArray3D
74 typedef ::std::vector
< CoordinateData3D
> CoordinateData3DVector
;
76 CoordinateData3DVector maVector
;
79 explicit CoordinateDataArray3D(sal_uInt32 nCount
)
84 explicit CoordinateDataArray3D(const CoordinateDataArray3D
& rOriginal
)
85 : maVector(rOriginal
.maVector
)
89 CoordinateDataArray3D(const CoordinateDataArray3D
& rOriginal
, sal_uInt32 nIndex
, sal_uInt32 nCount
)
90 : maVector(rOriginal
.maVector
.begin() + nIndex
, rOriginal
.maVector
.begin() + (nIndex
+ nCount
))
94 ~CoordinateDataArray3D()
98 ::basegfx::B3DVector
getNormal() const
100 ::basegfx::B3DVector aRetval
;
101 const sal_uInt32
nPointCount(maVector
.size());
105 sal_uInt32
nISmallest(0);
107 const basegfx::B3DPoint
* pSmallest(&maVector
[0].getCoordinate());
108 const basegfx::B3DPoint
* pNext(0);
109 const basegfx::B3DPoint
* pPrev(0);
111 // To guarantee a correctly oriented point, choose an outmost one
112 // which then cannot be concave
113 for(a
= 1; a
< nPointCount
; a
++)
115 const basegfx::B3DPoint
& rCandidate
= maVector
[a
].getCoordinate();
117 if((rCandidate
.getX() < pSmallest
->getX())
118 || (rCandidate
.getX() == pSmallest
->getX() && rCandidate
.getY() < pSmallest
->getY())
119 || (rCandidate
.getX() == pSmallest
->getX() && rCandidate
.getY() == pSmallest
->getY() && rCandidate
.getZ() < pSmallest
->getZ()))
122 pSmallest
= &rCandidate
;
126 // look for a next point different from minimal one
127 for(a
= (nISmallest
+ 1) % nPointCount
; a
!= nISmallest
; a
= (a
+ 1) % nPointCount
)
129 const basegfx::B3DPoint
& rCandidate
= maVector
[a
].getCoordinate();
131 if(!rCandidate
.equal(*pSmallest
))
138 // look for a previous point different from minimal one
139 for(a
= (nISmallest
+ nPointCount
- 1) % nPointCount
; a
!= nISmallest
; a
= (a
+ nPointCount
- 1) % nPointCount
)
141 const basegfx::B3DPoint
& rCandidate
= maVector
[a
].getCoordinate();
143 if(!rCandidate
.equal(*pSmallest
))
150 // we always have a minimal point. If we also have a different next and previous,
151 // we can calculate the normal
154 const basegfx::B3DVector
aPrev(*pPrev
- *pSmallest
);
155 const basegfx::B3DVector
aNext(*pNext
- *pSmallest
);
157 aRetval
= cross(aPrev
, aNext
);
165 sal_uInt32
count() const
167 return maVector
.size();
170 bool operator==(const CoordinateDataArray3D
& rCandidate
) const
172 return (maVector
== rCandidate
.maVector
);
175 const basegfx::B3DPoint
& getCoordinate(sal_uInt32 nIndex
) const
177 return maVector
[nIndex
].getCoordinate();
180 void setCoordinate(sal_uInt32 nIndex
, const basegfx::B3DPoint
& rValue
)
182 maVector
[nIndex
].setCoordinate(rValue
);
185 void insert(sal_uInt32 nIndex
, const CoordinateData3D
& rValue
, sal_uInt32 nCount
)
189 // add nCount copies of rValue
190 CoordinateData3DVector::iterator
aIndex(maVector
.begin());
192 maVector
.insert(aIndex
, nCount
, rValue
);
196 void insert(sal_uInt32 nIndex
, const CoordinateDataArray3D
& rSource
)
198 const sal_uInt32
nCount(rSource
.maVector
.size());
203 CoordinateData3DVector::iterator
aIndex(maVector
.begin());
205 CoordinateData3DVector::const_iterator
aStart(rSource
.maVector
.begin());
206 CoordinateData3DVector::const_iterator
aEnd(rSource
.maVector
.end());
207 maVector
.insert(aIndex
, aStart
, aEnd
);
211 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
216 CoordinateData3DVector::iterator
aStart(maVector
.begin());
218 const CoordinateData3DVector::iterator
aEnd(aStart
+ nCount
);
219 maVector
.erase(aStart
, aEnd
);
225 if(maVector
.size() > 1)
227 const sal_uInt32
nHalfSize(maVector
.size() >> 1L);
228 CoordinateData3DVector::iterator
aStart(maVector
.begin());
229 CoordinateData3DVector::iterator
aEnd(maVector
.end() - 1L);
231 for(sal_uInt32
a(0); a
< nHalfSize
; a
++)
233 ::std::swap(*aStart
, *aEnd
);
240 void transform(const ::basegfx::B3DHomMatrix
& rMatrix
)
242 CoordinateData3DVector::iterator
aStart(maVector
.begin());
243 CoordinateData3DVector::iterator
aEnd(maVector
.end());
245 for(; aStart
!= aEnd
; ++aStart
)
247 aStart
->transform(rMatrix
);
252 //////////////////////////////////////////////////////////////////////////////
256 typedef ::std::vector
< ::basegfx::BColor
> BColorDataVector
;
258 BColorDataVector maVector
;
259 sal_uInt32 mnUsedEntries
;
262 explicit BColorArray(sal_uInt32 nCount
)
268 explicit BColorArray(const BColorArray
& rOriginal
)
269 : maVector(rOriginal
.maVector
),
270 mnUsedEntries(rOriginal
.mnUsedEntries
)
274 BColorArray(const BColorArray
& rOriginal
, sal_uInt32 nIndex
, sal_uInt32 nCount
)
278 BColorDataVector::const_iterator
aStart(rOriginal
.maVector
.begin());
280 BColorDataVector::const_iterator
aEnd(aStart
);
281 assert(nCount
<= rOriginal
.maVector
.size());
283 maVector
.reserve(nCount
);
285 for(; aStart
!= aEnd
; ++aStart
)
287 if(!aStart
->equalZero())
290 maVector
.push_back(*aStart
);
298 sal_uInt32
count() const
300 return maVector
.size();
303 bool operator==(const BColorArray
& rCandidate
) const
305 return (maVector
== rCandidate
.maVector
);
310 return (0L != mnUsedEntries
);
313 const ::basegfx::BColor
& getBColor(sal_uInt32 nIndex
) const
315 return maVector
[nIndex
];
318 void setBColor(sal_uInt32 nIndex
, const ::basegfx::BColor
& rValue
)
320 bool bWasUsed(mnUsedEntries
&& !maVector
[nIndex
].equalZero());
321 bool bIsUsed(!rValue
.equalZero());
327 maVector
[nIndex
] = rValue
;
331 maVector
[nIndex
] = ::basegfx::BColor::getEmptyBColor();
339 maVector
[nIndex
] = rValue
;
345 void insert(sal_uInt32 nIndex
, const ::basegfx::BColor
& rValue
, sal_uInt32 nCount
)
349 // add nCount copies of rValue
350 BColorDataVector::iterator
aIndex(maVector
.begin());
352 maVector
.insert(aIndex
, nCount
, rValue
);
354 if(!rValue
.equalZero())
355 mnUsedEntries
+= nCount
;
359 void insert(sal_uInt32 nIndex
, const BColorArray
& rSource
)
361 const sal_uInt32
nCount(rSource
.maVector
.size());
366 BColorDataVector::iterator
aIndex(maVector
.begin());
368 BColorDataVector::const_iterator
aStart(rSource
.maVector
.begin());
369 BColorDataVector::const_iterator
aEnd(rSource
.maVector
.end());
370 maVector
.insert(aIndex
, aStart
, aEnd
);
372 for(; aStart
!= aEnd
; ++aStart
)
374 if(!aStart
->equalZero())
380 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
384 const BColorDataVector::iterator
aDeleteStart(maVector
.begin() + nIndex
);
385 const BColorDataVector::iterator
aDeleteEnd(aDeleteStart
+ nCount
);
386 BColorDataVector::const_iterator
aStart(aDeleteStart
);
388 for(; mnUsedEntries
&& aStart
!= aDeleteEnd
; ++aStart
)
390 if(!aStart
->equalZero())
395 maVector
.erase(aDeleteStart
, aDeleteEnd
);
401 if(maVector
.size() > 1)
403 const sal_uInt32
nHalfSize(maVector
.size() >> 1L);
404 BColorDataVector::iterator
aStart(maVector
.begin());
405 BColorDataVector::iterator
aEnd(maVector
.end() - 1L);
407 for(sal_uInt32
a(0); a
< nHalfSize
; a
++)
409 ::std::swap(*aStart
, *aEnd
);
417 //////////////////////////////////////////////////////////////////////////////
421 typedef ::std::vector
< ::basegfx::B3DVector
> NormalsData3DVector
;
423 NormalsData3DVector maVector
;
424 sal_uInt32 mnUsedEntries
;
427 explicit NormalsArray3D(sal_uInt32 nCount
)
433 explicit NormalsArray3D(const NormalsArray3D
& rOriginal
)
434 : maVector(rOriginal
.maVector
),
435 mnUsedEntries(rOriginal
.mnUsedEntries
)
439 NormalsArray3D(const NormalsArray3D
& rOriginal
, sal_uInt32 nIndex
, sal_uInt32 nCount
)
443 NormalsData3DVector::const_iterator
aStart(rOriginal
.maVector
.begin());
445 NormalsData3DVector::const_iterator
aEnd(aStart
);
447 maVector
.reserve(nCount
);
449 for(; aStart
!= aEnd
; ++aStart
)
451 if(!aStart
->equalZero())
454 maVector
.push_back(*aStart
);
462 sal_uInt32
count() const
464 return maVector
.size();
467 bool operator==(const NormalsArray3D
& rCandidate
) const
469 return (maVector
== rCandidate
.maVector
);
474 return (0L != mnUsedEntries
);
477 const ::basegfx::B3DVector
& getNormal(sal_uInt32 nIndex
) const
479 return maVector
[nIndex
];
482 void setNormal(sal_uInt32 nIndex
, const ::basegfx::B3DVector
& rValue
)
484 bool bWasUsed(mnUsedEntries
&& !maVector
[nIndex
].equalZero());
485 bool bIsUsed(!rValue
.equalZero());
491 maVector
[nIndex
] = rValue
;
495 maVector
[nIndex
] = ::basegfx::B3DVector::getEmptyVector();
503 maVector
[nIndex
] = rValue
;
509 void insert(sal_uInt32 nIndex
, const ::basegfx::B3DVector
& rValue
, sal_uInt32 nCount
)
513 // add nCount copies of rValue
514 NormalsData3DVector::iterator
aIndex(maVector
.begin());
516 maVector
.insert(aIndex
, nCount
, rValue
);
518 if(!rValue
.equalZero())
519 mnUsedEntries
+= nCount
;
523 void insert(sal_uInt32 nIndex
, const NormalsArray3D
& rSource
)
525 const sal_uInt32
nCount(rSource
.maVector
.size());
530 NormalsData3DVector::iterator
aIndex(maVector
.begin());
532 NormalsData3DVector::const_iterator
aStart(rSource
.maVector
.begin());
533 NormalsData3DVector::const_iterator
aEnd(rSource
.maVector
.end());
534 maVector
.insert(aIndex
, aStart
, aEnd
);
536 for(; aStart
!= aEnd
; ++aStart
)
538 if(!aStart
->equalZero())
544 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
548 const NormalsData3DVector::iterator
aDeleteStart(maVector
.begin() + nIndex
);
549 const NormalsData3DVector::iterator
aDeleteEnd(aDeleteStart
+ nCount
);
550 NormalsData3DVector::const_iterator
aStart(aDeleteStart
);
552 for(; mnUsedEntries
&& aStart
!= aDeleteEnd
; ++aStart
)
554 if(!aStart
->equalZero())
559 maVector
.erase(aDeleteStart
, aDeleteEnd
);
565 if(maVector
.size() > 1)
567 const sal_uInt32
nHalfSize(maVector
.size() >> 1L);
568 NormalsData3DVector::iterator
aStart(maVector
.begin());
569 NormalsData3DVector::iterator
aEnd(maVector
.end() - 1L);
571 for(sal_uInt32
a(0); a
< nHalfSize
; a
++)
573 ::std::swap(*aStart
, *aEnd
);
580 void transform(const basegfx::B3DHomMatrix
& rMatrix
)
582 const NormalsData3DVector::const_iterator
aEnd(maVector
.end());
584 for(NormalsData3DVector::iterator
aStart(maVector
.begin()); aStart
!= aEnd
; ++aStart
)
586 (*aStart
) *= rMatrix
;
591 //////////////////////////////////////////////////////////////////////////////
593 class TextureCoordinate2D
595 typedef ::std::vector
< ::basegfx::B2DPoint
> TextureData2DVector
;
597 TextureData2DVector maVector
;
598 sal_uInt32 mnUsedEntries
;
601 explicit TextureCoordinate2D(sal_uInt32 nCount
)
607 explicit TextureCoordinate2D(const TextureCoordinate2D
& rOriginal
)
608 : maVector(rOriginal
.maVector
),
609 mnUsedEntries(rOriginal
.mnUsedEntries
)
613 TextureCoordinate2D(const TextureCoordinate2D
& rOriginal
, sal_uInt32 nIndex
, sal_uInt32 nCount
)
617 TextureData2DVector::const_iterator
aStart(rOriginal
.maVector
.begin());
619 TextureData2DVector::const_iterator
aEnd(aStart
);
621 maVector
.reserve(nCount
);
623 for(; aStart
!= aEnd
; ++aStart
)
625 if(!aStart
->equalZero())
628 maVector
.push_back(*aStart
);
632 ~TextureCoordinate2D()
636 sal_uInt32
count() const
638 return maVector
.size();
641 bool operator==(const TextureCoordinate2D
& rCandidate
) const
643 return (maVector
== rCandidate
.maVector
);
648 return (0L != mnUsedEntries
);
651 const ::basegfx::B2DPoint
& getTextureCoordinate(sal_uInt32 nIndex
) const
653 return maVector
[nIndex
];
656 void setTextureCoordinate(sal_uInt32 nIndex
, const ::basegfx::B2DPoint
& rValue
)
658 bool bWasUsed(mnUsedEntries
&& !maVector
[nIndex
].equalZero());
659 bool bIsUsed(!rValue
.equalZero());
665 maVector
[nIndex
] = rValue
;
669 maVector
[nIndex
] = ::basegfx::B2DPoint::getEmptyPoint();
677 maVector
[nIndex
] = rValue
;
683 void insert(sal_uInt32 nIndex
, const ::basegfx::B2DPoint
& rValue
, sal_uInt32 nCount
)
687 // add nCount copies of rValue
688 TextureData2DVector::iterator
aIndex(maVector
.begin());
690 maVector
.insert(aIndex
, nCount
, rValue
);
692 if(!rValue
.equalZero())
693 mnUsedEntries
+= nCount
;
697 void insert(sal_uInt32 nIndex
, const TextureCoordinate2D
& rSource
)
699 const sal_uInt32
nCount(rSource
.maVector
.size());
704 TextureData2DVector::iterator
aIndex(maVector
.begin());
706 TextureData2DVector::const_iterator
aStart(rSource
.maVector
.begin());
707 TextureData2DVector::const_iterator
aEnd(rSource
.maVector
.end());
708 maVector
.insert(aIndex
, aStart
, aEnd
);
710 for(; aStart
!= aEnd
; ++aStart
)
712 if(!aStart
->equalZero())
718 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
722 const TextureData2DVector::iterator
aDeleteStart(maVector
.begin() + nIndex
);
723 const TextureData2DVector::iterator
aDeleteEnd(aDeleteStart
+ nCount
);
724 TextureData2DVector::const_iterator
aStart(aDeleteStart
);
726 for(; mnUsedEntries
&& aStart
!= aDeleteEnd
; ++aStart
)
728 if(!aStart
->equalZero())
733 maVector
.erase(aDeleteStart
, aDeleteEnd
);
739 if(maVector
.size() > 1)
741 const sal_uInt32
nHalfSize(maVector
.size() >> 1L);
742 TextureData2DVector::iterator
aStart(maVector
.begin());
743 TextureData2DVector::iterator
aEnd(maVector
.end() - 1L);
745 for(sal_uInt32
a(0); a
< nHalfSize
; a
++)
747 ::std::swap(*aStart
, *aEnd
);
754 void transform(const ::basegfx::B2DHomMatrix
& rMatrix
)
756 const TextureData2DVector::const_iterator
aEnd(maVector
.end());
758 for(TextureData2DVector::iterator
aStart(maVector
.begin()); aStart
!= aEnd
; ++aStart
)
760 (*aStart
) *= rMatrix
;
765 //////////////////////////////////////////////////////////////////////////////
769 // The point vector. This vector exists always and defines the
771 CoordinateDataArray3D maPoints
;
773 // The BColor vector. This vectors are created on demand
775 BColorArray
* mpBColors
;
777 // The Normals vector. This vectors are created on demand
779 NormalsArray3D
* mpNormals
;
781 // The TextureCoordinates vector. This vectors are created on demand
783 TextureCoordinate2D
* mpTextureCoordiantes
;
785 // The calculated plane normal. mbPlaneNormalValid says if it's valid.
786 ::basegfx::B3DVector maPlaneNormal
;
789 // flag which decides if this polygon is opened or closed
790 unsigned mbIsClosed
: 1;
792 // flag which says if maPlaneNormal is up-to-date
793 unsigned mbPlaneNormalValid
: 1;
796 void invalidatePlaneNormal()
798 if(mbPlaneNormalValid
)
800 mbPlaneNormalValid
= false;
805 // This constructor is only used from the static identity polygon, thus
806 // the RefCount is set to 1 to never 'delete' this static incarnation.
811 mpTextureCoordiantes(0L),
812 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
814 mbPlaneNormalValid(true)
816 // complete initialization with defaults
819 ImplB3DPolygon(const ImplB3DPolygon
& rToBeCopied
)
820 : maPoints(rToBeCopied
.maPoints
),
823 mpTextureCoordiantes(0L),
824 maPlaneNormal(rToBeCopied
.maPlaneNormal
),
825 mbIsClosed(rToBeCopied
.mbIsClosed
),
826 mbPlaneNormalValid(rToBeCopied
.mbPlaneNormalValid
)
828 // complete initialization using copy
829 if(rToBeCopied
.mpBColors
&& rToBeCopied
.mpBColors
->isUsed())
831 mpBColors
= new BColorArray(*rToBeCopied
.mpBColors
);
834 if(rToBeCopied
.mpNormals
&& rToBeCopied
.mpNormals
->isUsed())
836 mpNormals
= new NormalsArray3D(*rToBeCopied
.mpNormals
);
839 if(rToBeCopied
.mpTextureCoordiantes
&& rToBeCopied
.mpTextureCoordiantes
->isUsed())
841 mpTextureCoordiantes
= new TextureCoordinate2D(*rToBeCopied
.mpTextureCoordiantes
);
845 ImplB3DPolygon(const ImplB3DPolygon
& rToBeCopied
, sal_uInt32 nIndex
, sal_uInt32 nCount
)
846 : maPoints(rToBeCopied
.maPoints
, nIndex
, nCount
),
849 mpTextureCoordiantes(0L),
850 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
851 mbIsClosed(rToBeCopied
.mbIsClosed
),
852 mbPlaneNormalValid(false)
854 // complete initialization using partly copy
855 if(rToBeCopied
.mpBColors
&& rToBeCopied
.mpBColors
->isUsed())
857 mpBColors
= new BColorArray(*rToBeCopied
.mpBColors
, nIndex
, nCount
);
859 if(!mpBColors
->isUsed())
866 if(rToBeCopied
.mpNormals
&& rToBeCopied
.mpNormals
->isUsed())
868 mpNormals
= new NormalsArray3D(*rToBeCopied
.mpNormals
, nIndex
, nCount
);
870 if(!mpNormals
->isUsed())
877 if(rToBeCopied
.mpTextureCoordiantes
&& rToBeCopied
.mpTextureCoordiantes
->isUsed())
879 mpTextureCoordiantes
= new TextureCoordinate2D(*rToBeCopied
.mpTextureCoordiantes
, nIndex
, nCount
);
881 if(!mpTextureCoordiantes
->isUsed())
883 delete mpTextureCoordiantes
;
884 mpTextureCoordiantes
= 0L;
903 if(mpTextureCoordiantes
)
905 delete mpTextureCoordiantes
;
906 mpTextureCoordiantes
= 0L;
910 sal_uInt32
count() const
912 return maPoints
.count();
915 bool isClosed() const
920 void setClosed(bool bNew
)
922 if(bNew
!= (bool)mbIsClosed
)
928 inline bool impBColorsAreEqual(const ImplB3DPolygon
& rCandidate
) const
930 bool bBColorsAreEqual(true);
934 if(rCandidate
.mpBColors
)
936 bBColorsAreEqual
= (*mpBColors
== *rCandidate
.mpBColors
);
940 // candidate has no BColors, so it's assumed all unused.
941 bBColorsAreEqual
= !mpBColors
->isUsed();
946 if(rCandidate
.mpBColors
)
948 // we have no TextureCoordiantes, so it's assumed all unused.
949 bBColorsAreEqual
= !rCandidate
.mpBColors
->isUsed();
953 return bBColorsAreEqual
;
956 inline bool impNormalsAreEqual(const ImplB3DPolygon
& rCandidate
) const
958 bool bNormalsAreEqual(true);
962 if(rCandidate
.mpNormals
)
964 bNormalsAreEqual
= (*mpNormals
== *rCandidate
.mpNormals
);
968 // candidate has no normals, so it's assumed all unused.
969 bNormalsAreEqual
= !mpNormals
->isUsed();
974 if(rCandidate
.mpNormals
)
976 // we have no normals, so it's assumed all unused.
977 bNormalsAreEqual
= !rCandidate
.mpNormals
->isUsed();
981 return bNormalsAreEqual
;
984 inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon
& rCandidate
) const
986 bool bTextureCoordinatesAreEqual(true);
988 if(mpTextureCoordiantes
)
990 if(rCandidate
.mpTextureCoordiantes
)
992 bTextureCoordinatesAreEqual
= (*mpTextureCoordiantes
== *rCandidate
.mpTextureCoordiantes
);
996 // candidate has no TextureCoordinates, so it's assumed all unused.
997 bTextureCoordinatesAreEqual
= !mpTextureCoordiantes
->isUsed();
1002 if(rCandidate
.mpTextureCoordiantes
)
1004 // we have no TextureCoordiantes, so it's assumed all unused.
1005 bTextureCoordinatesAreEqual
= !rCandidate
.mpTextureCoordiantes
->isUsed();
1009 return bTextureCoordinatesAreEqual
;
1012 bool operator==(const ImplB3DPolygon
& rCandidate
) const
1014 if(mbIsClosed
== rCandidate
.mbIsClosed
)
1016 if(maPoints
== rCandidate
.maPoints
)
1018 if(impBColorsAreEqual(rCandidate
))
1020 if(impNormalsAreEqual(rCandidate
))
1022 if(impTextureCoordinatesAreEqual(rCandidate
))
1034 const ::basegfx::B3DPoint
& getPoint(sal_uInt32 nIndex
) const
1036 return maPoints
.getCoordinate(nIndex
);
1039 void setPoint(sal_uInt32 nIndex
, const ::basegfx::B3DPoint
& rValue
)
1041 maPoints
.setCoordinate(nIndex
, rValue
);
1042 invalidatePlaneNormal();
1045 void insert(sal_uInt32 nIndex
, const ::basegfx::B3DPoint
& rPoint
, sal_uInt32 nCount
)
1049 CoordinateData3D
aCoordinate(rPoint
);
1050 maPoints
.insert(nIndex
, aCoordinate
, nCount
);
1051 invalidatePlaneNormal();
1055 mpBColors
->insert(nIndex
, ::basegfx::BColor::getEmptyBColor(), nCount
);
1060 mpNormals
->insert(nIndex
, ::basegfx::B3DVector::getEmptyVector(), nCount
);
1063 if(mpTextureCoordiantes
)
1065 mpTextureCoordiantes
->insert(nIndex
, ::basegfx::B2DPoint::getEmptyPoint(), nCount
);
1070 const ::basegfx::BColor
& getBColor(sal_uInt32 nIndex
) const
1074 return mpBColors
->getBColor(nIndex
);
1078 return ::basegfx::BColor::getEmptyBColor();
1082 void setBColor(sal_uInt32 nIndex
, const ::basegfx::BColor
& rValue
)
1086 if(!rValue
.equalZero())
1088 mpBColors
= new BColorArray(maPoints
.count());
1089 mpBColors
->setBColor(nIndex
, rValue
);
1094 mpBColors
->setBColor(nIndex
, rValue
);
1096 if(!mpBColors
->isUsed())
1104 bool areBColorsUsed() const
1106 return (mpBColors
&& mpBColors
->isUsed());
1118 const ::basegfx::B3DVector
& getNormal() const
1120 if(!mbPlaneNormalValid
)
1122 const_cast< ImplB3DPolygon
* >(this)->maPlaneNormal
= maPoints
.getNormal();
1123 const_cast< ImplB3DPolygon
* >(this)->mbPlaneNormalValid
= true;
1126 return maPlaneNormal
;
1129 const ::basegfx::B3DVector
& getNormal(sal_uInt32 nIndex
) const
1133 return mpNormals
->getNormal(nIndex
);
1137 return ::basegfx::B3DVector::getEmptyVector();
1141 void setNormal(sal_uInt32 nIndex
, const ::basegfx::B3DVector
& rValue
)
1145 if(!rValue
.equalZero())
1147 mpNormals
= new NormalsArray3D(maPoints
.count());
1148 mpNormals
->setNormal(nIndex
, rValue
);
1153 mpNormals
->setNormal(nIndex
, rValue
);
1155 if(!mpNormals
->isUsed())
1163 void transformNormals(const ::basegfx::B3DHomMatrix
& rMatrix
)
1167 mpNormals
->transform(rMatrix
);
1171 bool areNormalsUsed() const
1173 return (mpNormals
&& mpNormals
->isUsed());
1185 const ::basegfx::B2DPoint
& getTextureCoordinate(sal_uInt32 nIndex
) const
1187 if(mpTextureCoordiantes
)
1189 return mpTextureCoordiantes
->getTextureCoordinate(nIndex
);
1193 return ::basegfx::B2DPoint::getEmptyPoint();
1197 void setTextureCoordinate(sal_uInt32 nIndex
, const ::basegfx::B2DPoint
& rValue
)
1199 if(!mpTextureCoordiantes
)
1201 if(!rValue
.equalZero())
1203 mpTextureCoordiantes
= new TextureCoordinate2D(maPoints
.count());
1204 mpTextureCoordiantes
->setTextureCoordinate(nIndex
, rValue
);
1209 mpTextureCoordiantes
->setTextureCoordinate(nIndex
, rValue
);
1211 if(!mpTextureCoordiantes
->isUsed())
1213 delete mpTextureCoordiantes
;
1214 mpTextureCoordiantes
= 0L;
1219 bool areTextureCoordinatesUsed() const
1221 return (mpTextureCoordiantes
&& mpTextureCoordiantes
->isUsed());
1224 void clearTextureCoordinates()
1226 if(mpTextureCoordiantes
)
1228 delete mpTextureCoordiantes
;
1229 mpTextureCoordiantes
= 0L;
1233 void transformTextureCoordinates(const ::basegfx::B2DHomMatrix
& rMatrix
)
1235 if(mpTextureCoordiantes
)
1237 mpTextureCoordiantes
->transform(rMatrix
);
1241 void insert(sal_uInt32 nIndex
, const ImplB3DPolygon
& rSource
)
1243 const sal_uInt32
nCount(rSource
.maPoints
.count());
1247 maPoints
.insert(nIndex
, rSource
.maPoints
);
1248 invalidatePlaneNormal();
1250 if(rSource
.mpBColors
&& rSource
.mpBColors
->isUsed())
1254 mpBColors
= new BColorArray(maPoints
.count());
1257 mpBColors
->insert(nIndex
, *rSource
.mpBColors
);
1263 mpBColors
->insert(nIndex
, ::basegfx::BColor::getEmptyBColor(), nCount
);
1267 if(rSource
.mpNormals
&& rSource
.mpNormals
->isUsed())
1271 mpNormals
= new NormalsArray3D(maPoints
.count());
1274 mpNormals
->insert(nIndex
, *rSource
.mpNormals
);
1280 mpNormals
->insert(nIndex
, ::basegfx::B3DVector::getEmptyVector(), nCount
);
1284 if(rSource
.mpTextureCoordiantes
&& rSource
.mpTextureCoordiantes
->isUsed())
1286 if(!mpTextureCoordiantes
)
1288 mpTextureCoordiantes
= new TextureCoordinate2D(maPoints
.count());
1291 mpTextureCoordiantes
->insert(nIndex
, *rSource
.mpTextureCoordiantes
);
1295 if(mpTextureCoordiantes
)
1297 mpTextureCoordiantes
->insert(nIndex
, ::basegfx::B2DPoint::getEmptyPoint(), nCount
);
1303 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
1307 maPoints
.remove(nIndex
, nCount
);
1308 invalidatePlaneNormal();
1312 mpBColors
->remove(nIndex
, nCount
);
1314 if(!mpBColors
->isUsed())
1323 mpNormals
->remove(nIndex
, nCount
);
1325 if(!mpNormals
->isUsed())
1332 if(mpTextureCoordiantes
)
1334 mpTextureCoordiantes
->remove(nIndex
, nCount
);
1336 if(!mpTextureCoordiantes
->isUsed())
1338 delete mpTextureCoordiantes
;
1339 mpTextureCoordiantes
= 0L;
1347 if(maPoints
.count() > 1)
1351 if(mbPlaneNormalValid
)
1353 // mirror plane normal
1354 maPlaneNormal
= -maPlaneNormal
;
1367 if(mpTextureCoordiantes
)
1369 mpTextureCoordiantes
->flip();
1374 bool hasDoublePoints() const
1378 // check for same start and end point
1379 const sal_uInt32
nIndex(maPoints
.count() - 1L);
1381 if(maPoints
.getCoordinate(0L) == maPoints
.getCoordinate(nIndex
))
1383 const bool bBColorEqual(!mpBColors
|| (mpBColors
->getBColor(0L) == mpBColors
->getBColor(nIndex
)));
1387 const bool bNormalsEqual(!mpNormals
|| (mpNormals
->getNormal(0L) == mpNormals
->getNormal(nIndex
)));
1391 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes
|| (mpTextureCoordiantes
->getTextureCoordinate(0L) == mpTextureCoordiantes
->getTextureCoordinate(nIndex
)));
1393 if(bTextureCoordinatesEqual
)
1403 for(sal_uInt32
a(0L); a
< maPoints
.count() - 1L; a
++)
1405 if(maPoints
.getCoordinate(a
) == maPoints
.getCoordinate(a
+ 1L))
1407 const bool bBColorEqual(!mpBColors
|| (mpBColors
->getBColor(a
) == mpBColors
->getBColor(a
+ 1L)));
1411 const bool bNormalsEqual(!mpNormals
|| (mpNormals
->getNormal(a
) == mpNormals
->getNormal(a
+ 1L)));
1415 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes
|| (mpTextureCoordiantes
->getTextureCoordinate(a
) == mpTextureCoordiantes
->getTextureCoordinate(a
+ 1L)));
1417 if(bTextureCoordinatesEqual
)
1429 void removeDoublePointsAtBeginEnd()
1431 // Only remove DoublePoints at Begin and End when poly is closed
1440 if(maPoints
.count() > 1L)
1442 const sal_uInt32
nIndex(maPoints
.count() - 1L);
1443 bRemove
= (maPoints
.getCoordinate(0L) == maPoints
.getCoordinate(nIndex
));
1445 if(bRemove
&& mpBColors
&& !(mpBColors
->getBColor(0L) == mpBColors
->getBColor(nIndex
)))
1450 if(bRemove
&& mpNormals
&& !(mpNormals
->getNormal(0L) == mpNormals
->getNormal(nIndex
)))
1455 if(bRemove
&& mpTextureCoordiantes
&& !(mpTextureCoordiantes
->getTextureCoordinate(0L) == mpTextureCoordiantes
->getTextureCoordinate(nIndex
)))
1463 const sal_uInt32
nIndex(maPoints
.count() - 1L);
1470 void removeDoublePointsWholeTrack()
1472 sal_uInt32
nIndex(0L);
1474 // test as long as there are at least two points and as long as the index
1475 // is smaller or equal second last point
1476 while((maPoints
.count() > 1L) && (nIndex
<= maPoints
.count() - 2L))
1478 const sal_uInt32
nNextIndex(nIndex
+ 1L);
1479 bool bRemove(maPoints
.getCoordinate(nIndex
) == maPoints
.getCoordinate(nNextIndex
));
1481 if(bRemove
&& mpBColors
&& !(mpBColors
->getBColor(nIndex
) == mpBColors
->getBColor(nNextIndex
)))
1486 if(bRemove
&& mpNormals
&& !(mpNormals
->getNormal(nIndex
) == mpNormals
->getNormal(nNextIndex
)))
1491 if(bRemove
&& mpTextureCoordiantes
&& !(mpTextureCoordiantes
->getTextureCoordinate(nIndex
) == mpTextureCoordiantes
->getTextureCoordinate(nNextIndex
)))
1498 // if next is same as index and the control vectors are unused, delete index
1503 // if different, step forward
1509 void transform(const ::basegfx::B3DHomMatrix
& rMatrix
)
1511 maPoints
.transform(rMatrix
);
1513 // Here, it seems to be possible to transform a valid plane normal and to avoid
1514 // invalidation, but it's not true. If the transformation contains shears or e.g.
1515 // perspective projection, the orthogonality to the transformed plane will not
1516 // be preserved. It may be possible to test that at the matrix to not invalidate in
1517 // all cases or to extract a matrix which does not 'shear' the vector which is
1518 // a normal in this case. As long as this is not sure, i will just invalidate.
1519 invalidatePlaneNormal();
1523 //////////////////////////////////////////////////////////////////////////////
1527 namespace { struct DefaultPolygon
: public rtl::Static
< B3DPolygon::ImplType
,
1528 DefaultPolygon
> {}; }
1530 B3DPolygon::B3DPolygon() :
1531 mpPolygon(DefaultPolygon::get())
1535 B3DPolygon::B3DPolygon(const B3DPolygon
& rPolygon
) :
1536 mpPolygon(rPolygon
.mpPolygon
)
1540 B3DPolygon::~B3DPolygon()
1544 B3DPolygon
& B3DPolygon::operator=(const B3DPolygon
& rPolygon
)
1546 mpPolygon
= rPolygon
.mpPolygon
;
1550 bool B3DPolygon::operator==(const B3DPolygon
& rPolygon
) const
1552 if(mpPolygon
.same_object(rPolygon
.mpPolygon
))
1555 return (*mpPolygon
== *rPolygon
.mpPolygon
);
1558 bool B3DPolygon::operator!=(const B3DPolygon
& rPolygon
) const
1560 return !(*this == rPolygon
);
1563 sal_uInt32
B3DPolygon::count() const
1565 return mpPolygon
->count();
1568 basegfx::B3DPoint
B3DPolygon::getB3DPoint(sal_uInt32 nIndex
) const
1570 OSL_ENSURE(nIndex
< mpPolygon
->count(), "B3DPolygon access outside range (!)");
1572 return mpPolygon
->getPoint(nIndex
);
1575 void B3DPolygon::setB3DPoint(sal_uInt32 nIndex
, const basegfx::B3DPoint
& rValue
)
1577 OSL_ENSURE(nIndex
< mpPolygon
->count(), "B3DPolygon access outside range (!)");
1579 if(getB3DPoint(nIndex
) != rValue
)
1580 mpPolygon
->setPoint(nIndex
, rValue
);
1583 BColor
B3DPolygon::getBColor(sal_uInt32 nIndex
) const
1585 OSL_ENSURE(nIndex
< mpPolygon
->count(), "B3DPolygon access outside range (!)");
1587 return mpPolygon
->getBColor(nIndex
);
1590 void B3DPolygon::setBColor(sal_uInt32 nIndex
, const BColor
& rValue
)
1592 OSL_ENSURE(nIndex
< mpPolygon
->count(), "B3DPolygon access outside range (!)");
1594 if(mpPolygon
->getBColor(nIndex
) != rValue
)
1595 mpPolygon
->setBColor(nIndex
, rValue
);
1598 bool B3DPolygon::areBColorsUsed() const
1600 return mpPolygon
->areBColorsUsed();
1603 void B3DPolygon::clearBColors()
1605 if(mpPolygon
->areBColorsUsed())
1606 mpPolygon
->clearBColors();
1609 B3DVector
B3DPolygon::getNormal() const
1611 return mpPolygon
->getNormal();
1614 B3DVector
B3DPolygon::getNormal(sal_uInt32 nIndex
) const
1616 OSL_ENSURE(nIndex
< mpPolygon
->count(), "B3DPolygon access outside range (!)");
1618 return mpPolygon
->getNormal(nIndex
);
1621 void B3DPolygon::setNormal(sal_uInt32 nIndex
, const B3DVector
& rValue
)
1623 OSL_ENSURE(nIndex
< mpPolygon
->count(), "B3DPolygon access outside range (!)");
1625 if(mpPolygon
->getNormal(nIndex
) != rValue
)
1626 mpPolygon
->setNormal(nIndex
, rValue
);
1629 void B3DPolygon::transformNormals(const B3DHomMatrix
& rMatrix
)
1631 if(mpPolygon
->areNormalsUsed() && !rMatrix
.isIdentity())
1632 mpPolygon
->transformNormals(rMatrix
);
1635 bool B3DPolygon::areNormalsUsed() const
1637 return mpPolygon
->areNormalsUsed();
1640 void B3DPolygon::clearNormals()
1642 if(mpPolygon
->areNormalsUsed())
1643 mpPolygon
->clearNormals();
1646 B2DPoint
B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex
) const
1648 OSL_ENSURE(nIndex
< mpPolygon
->count(), "B3DPolygon access outside range (!)");
1650 return mpPolygon
->getTextureCoordinate(nIndex
);
1653 void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex
, const B2DPoint
& rValue
)
1655 OSL_ENSURE(nIndex
< mpPolygon
->count(), "B3DPolygon access outside range (!)");
1657 if(mpPolygon
->getTextureCoordinate(nIndex
) != rValue
)
1658 mpPolygon
->setTextureCoordinate(nIndex
, rValue
);
1661 void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix
& rMatrix
)
1663 if(mpPolygon
->areTextureCoordinatesUsed() && !rMatrix
.isIdentity())
1664 mpPolygon
->transformTextureCoordinates(rMatrix
);
1667 bool B3DPolygon::areTextureCoordinatesUsed() const
1669 return mpPolygon
->areTextureCoordinatesUsed();
1672 void B3DPolygon::clearTextureCoordinates()
1674 if(mpPolygon
->areTextureCoordinatesUsed())
1675 mpPolygon
->clearTextureCoordinates();
1678 void B3DPolygon::append(const basegfx::B3DPoint
& rPoint
, sal_uInt32 nCount
)
1681 mpPolygon
->insert(mpPolygon
->count(), rPoint
, nCount
);
1684 void B3DPolygon::append(const B3DPolygon
& rPoly
, sal_uInt32 nIndex
, sal_uInt32 nCount
)
1690 nCount
= rPoly
.count();
1693 if(0L == nIndex
&& nCount
== rPoly
.count())
1695 mpPolygon
->insert(mpPolygon
->count(), *rPoly
.mpPolygon
);
1699 OSL_ENSURE(nIndex
+ nCount
<= rPoly
.mpPolygon
->count(), "B3DPolygon Append outside range (!)");
1700 ImplB3DPolygon
aTempPoly(*rPoly
.mpPolygon
, nIndex
, nCount
);
1701 mpPolygon
->insert(mpPolygon
->count(), aTempPoly
);
1706 void B3DPolygon::remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
1708 OSL_ENSURE(nIndex
+ nCount
<= mpPolygon
->count(), "B3DPolygon Remove outside range (!)");
1711 mpPolygon
->remove(nIndex
, nCount
);
1714 void B3DPolygon::clear()
1716 mpPolygon
= DefaultPolygon::get();
1719 bool B3DPolygon::isClosed() const
1721 return mpPolygon
->isClosed();
1724 void B3DPolygon::setClosed(bool bNew
)
1726 if(isClosed() != bNew
)
1727 mpPolygon
->setClosed(bNew
);
1730 void B3DPolygon::flip()
1736 bool B3DPolygon::hasDoublePoints() const
1738 return (mpPolygon
->count() > 1L && mpPolygon
->hasDoublePoints());
1741 void B3DPolygon::removeDoublePoints()
1743 if(hasDoublePoints())
1745 mpPolygon
->removeDoublePointsAtBeginEnd();
1746 mpPolygon
->removeDoublePointsWholeTrack();
1750 void B3DPolygon::transform(const basegfx::B3DHomMatrix
& rMatrix
)
1752 if(mpPolygon
->count() && !rMatrix
.isIdentity())
1754 mpPolygon
->transform(rMatrix
);
1757 } // end of namespace basegfx
1759 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */