diff options
author | Vladimir Glazounov <vg@openoffice.org> | 2008-08-19 23:03:41 +0000 |
---|---|---|
committer | Vladimir Glazounov <vg@openoffice.org> | 2008-08-19 23:03:41 +0000 |
commit | 00182bc47ccdc2dde85e189403424c736641e8e1 (patch) | |
tree | f59ea7cc873a061d607d8b72860d6b32526429ec /basegfx | |
parent | 4345ff22d65f3ea74e3ae0dd521f31cbae77a316 (diff) |
INTEGRATION: CWS aw033 (1.6.2); FILE MERGED
2008/05/27 14:08:45 aw 1.6.2.8: #i39532# changes DEV300 m12 resync corrections
2008/05/15 14:59:21 aw 1.6.2.7: adaptions after resync
2008/05/15 14:32:39 aw 1.6.2.6: adaptions after resync
2008/05/14 14:40:54 aw 1.6.2.5: RESYNC: (1.10-1.12); FILE MERGED
2006/11/28 16:13:27 aw 1.6.2.4: RESYNC: (1.9-1.10); FILE MERGED
2006/09/27 16:29:23 aw 1.6.2.3: #i39532# changes after resync to m185
2006/09/26 14:50:46 aw 1.6.2.2: RESYNC: (1.6-1.9); FILE MERGED
2006/05/12 11:36:07 aw 1.6.2.1: code changes for primitive support
Diffstat (limited to 'basegfx')
-rw-r--r-- | basegfx/source/polygon/b3dpolygon.cxx | 1341 |
1 files changed, 1302 insertions, 39 deletions
diff --git a/basegfx/source/polygon/b3dpolygon.cxx b/basegfx/source/polygon/b3dpolygon.cxx index e235eb99e9d6..84383bc55ec9 100644 --- a/basegfx/source/polygon/b3dpolygon.cxx +++ b/basegfx/source/polygon/b3dpolygon.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: b3dpolygon.cxx,v $ - * $Revision: 1.12 $ + * $Revision: 1.13 $ * * This file is part of OpenOffice.org. * @@ -35,7 +35,9 @@ #include <basegfx/point/b3dpoint.hxx> #include <basegfx/matrix/b3dhommatrix.hxx> #include <rtl/instance.hxx> - +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/color/bcolor.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> #include <vector> #include <algorithm> @@ -102,6 +104,77 @@ public: { } + ~CoordinateDataArray3D() + { + } + + ::basegfx::B3DVector getNormal() const + { + ::basegfx::B3DVector aRetval; + const sal_uInt32 nPointCount(maVector.size()); + + if(nPointCount > 2) + { + sal_uInt32 nISmallest(0); + sal_uInt32 a(0); + const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate()); + const basegfx::B3DPoint* pNext(0); + const basegfx::B3DPoint* pPrev(0); + + // To guarantee a correctly oriented point, choose an outmost one + // which then cannot be concave + for(a = 1; a < nPointCount; a++) + { + const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate(); + + if((rCandidate.getX() < pSmallest->getX()) + || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY()) + || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ())) + { + nISmallest = a; + pSmallest = &rCandidate; + } + } + + // look for a next point different from minimal one + for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount) + { + const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate(); + + if(!rCandidate.equal(*pSmallest)) + { + pNext = &rCandidate; + break; + } + } + + // look for a previous point different from minimal one + for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount) + { + const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate(); + + if(!rCandidate.equal(*pSmallest)) + { + pPrev = &rCandidate; + break; + } + } + + // we always have a minimal point. If we also have a different next and previous, + // we can calculate the normal + if(pNext && pPrev) + { + const basegfx::B3DVector aPrev(*pPrev - *pSmallest); + const basegfx::B3DVector aNext(*pNext - *pSmallest); + + aRetval = cross(aPrev, aNext); + aRetval.normalize(); + } + } + + return aRetval; + } + sal_uInt32 count() const { return maVector.size(); @@ -177,45 +250,528 @@ public: } } - void removeDoublePointsAtBeginEnd() + void transform(const ::basegfx::B3DHomMatrix& rMatrix) { - // remove from end as long as there are at least two points - // and begin/end are equal - while((maVector.size() > 1L) && (maVector[0] == maVector[maVector.size() - 1L])) + CoordinateData3DVector::iterator aStart(maVector.begin()); + CoordinateData3DVector::iterator aEnd(maVector.end()); + + for(; aStart != aEnd; aStart++) { - maVector.pop_back(); + aStart->transform(rMatrix); } } +}; - void removeDoublePointsWholeTrack() +////////////////////////////////////////////////////////////////////////////// + +class BColorArray +{ + typedef ::std::vector< ::basegfx::BColor > BColorDataVector; + + BColorDataVector maVector; + sal_uInt32 mnUsedEntries; + +public: + explicit BColorArray(sal_uInt32 nCount) + : maVector(nCount), + mnUsedEntries(0L) { - sal_uInt32 nIndex(0L); + } - // test as long as there are at least two points and as long as the index - // is smaller or equal second last point - while((maVector.size() > 1L) && (nIndex <= maVector.size() - 2L)) + explicit BColorArray(const BColorArray& rOriginal) + : maVector(rOriginal.maVector), + mnUsedEntries(rOriginal.mnUsedEntries) + { + } + + BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) + : maVector(), + mnUsedEntries(0L) + { + BColorDataVector::const_iterator aStart(rOriginal.maVector.begin()); + aStart += nIndex; + BColorDataVector::const_iterator aEnd(aStart); + aEnd += nCount; + maVector.reserve(nCount); + + for(; aStart != aEnd; aStart++) { - if(maVector[nIndex] == maVector[nIndex + 1L]) + if(!aStart->equalZero()) + mnUsedEntries++; + + maVector.push_back(*aStart); + } + } + + ~BColorArray() + { + } + + sal_uInt32 count() const + { + return maVector.size(); + } + + bool operator==(const BColorArray& rCandidate) const + { + return (maVector == rCandidate.maVector); + } + + bool isUsed() const + { + return (0L != mnUsedEntries); + } + + const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const + { + return maVector[nIndex]; + } + + void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue) + { + bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero()); + bool bIsUsed(!rValue.equalZero()); + + if(bWasUsed) + { + if(bIsUsed) { - // if next is same as index, delete next - maVector.erase(maVector.begin() + (nIndex + 1L)); + maVector[nIndex] = rValue; } else { - // if different, step forward - nIndex++; + maVector[nIndex] = ::basegfx::BColor::getEmptyBColor(); + mnUsedEntries--; + } + } + else + { + if(bIsUsed) + { + maVector[nIndex] = rValue; + mnUsedEntries++; + } + } + } + + void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount) + { + if(nCount) + { + // add nCount copies of rValue + BColorDataVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + maVector.insert(aIndex, nCount, rValue); + + if(!rValue.equalZero()) + mnUsedEntries += nCount; + } + } + + void insert(sal_uInt32 nIndex, const BColorArray& rSource) + { + const sal_uInt32 nCount(rSource.maVector.size()); + + if(nCount) + { + // insert data + BColorDataVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + BColorDataVector::const_iterator aStart(rSource.maVector.begin()); + BColorDataVector::const_iterator aEnd(rSource.maVector.end()); + maVector.insert(aIndex, aStart, aEnd); + + for(; aStart != aEnd; aStart++) + { + if(!aStart->equalZero()) + mnUsedEntries++; + } + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex); + const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount); + BColorDataVector::const_iterator aStart(aDeleteStart); + + for(; mnUsedEntries && aStart != aDeleteEnd; aStart++) + { + if(!aStart->equalZero()) + mnUsedEntries--; + } + + // remove point data + maVector.erase(aDeleteStart, aDeleteEnd); + } + } + + void flip() + { + if(maVector.size() > 1) + { + const sal_uInt32 nHalfSize(maVector.size() >> 1L); + BColorDataVector::iterator aStart(maVector.begin()); + BColorDataVector::iterator aEnd(maVector.end() - 1L); + + for(sal_uInt32 a(0); a < nHalfSize; a++) + { + ::std::swap(*aStart, *aEnd); + aStart++; + aEnd--; + } + } + } +}; + +////////////////////////////////////////////////////////////////////////////// + +class NormalsArray3D +{ + typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector; + + NormalsData3DVector maVector; + sal_uInt32 mnUsedEntries; + +public: + explicit NormalsArray3D(sal_uInt32 nCount) + : maVector(nCount), + mnUsedEntries(0L) + { + } + + explicit NormalsArray3D(const NormalsArray3D& rOriginal) + : maVector(rOriginal.maVector), + mnUsedEntries(rOriginal.mnUsedEntries) + { + } + + NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) + : maVector(), + mnUsedEntries(0L) + { + NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin()); + aStart += nIndex; + NormalsData3DVector::const_iterator aEnd(aStart); + aEnd += nCount; + maVector.reserve(nCount); + + for(; aStart != aEnd; aStart++) + { + if(!aStart->equalZero()) + mnUsedEntries++; + + maVector.push_back(*aStart); + } + } + + ~NormalsArray3D() + { + } + + sal_uInt32 count() const + { + return maVector.size(); + } + + bool operator==(const NormalsArray3D& rCandidate) const + { + return (maVector == rCandidate.maVector); + } + + bool isUsed() const + { + return (0L != mnUsedEntries); + } + + const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const + { + return maVector[nIndex]; + } + + void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue) + { + bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero()); + bool bIsUsed(!rValue.equalZero()); + + if(bWasUsed) + { + if(bIsUsed) + { + maVector[nIndex] = rValue; + } + else + { + maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector(); + mnUsedEntries--; + } + } + else + { + if(bIsUsed) + { + maVector[nIndex] = rValue; + mnUsedEntries++; + } + } + } + + void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount) + { + if(nCount) + { + // add nCount copies of rValue + NormalsData3DVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + maVector.insert(aIndex, nCount, rValue); + + if(!rValue.equalZero()) + mnUsedEntries += nCount; + } + } + + void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource) + { + const sal_uInt32 nCount(rSource.maVector.size()); + + if(nCount) + { + // insert data + NormalsData3DVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + NormalsData3DVector::const_iterator aStart(rSource.maVector.begin()); + NormalsData3DVector::const_iterator aEnd(rSource.maVector.end()); + maVector.insert(aIndex, aStart, aEnd); + + for(; aStart != aEnd; aStart++) + { + if(!aStart->equalZero()) + mnUsedEntries++; + } + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex); + const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount); + NormalsData3DVector::const_iterator aStart(aDeleteStart); + + for(; mnUsedEntries && aStart != aDeleteEnd; aStart++) + { + if(!aStart->equalZero()) + mnUsedEntries--; + } + + // remove point data + maVector.erase(aDeleteStart, aDeleteEnd); + } + } + + void flip() + { + if(maVector.size() > 1) + { + const sal_uInt32 nHalfSize(maVector.size() >> 1L); + NormalsData3DVector::iterator aStart(maVector.begin()); + NormalsData3DVector::iterator aEnd(maVector.end() - 1L); + + for(sal_uInt32 a(0); a < nHalfSize; a++) + { + ::std::swap(*aStart, *aEnd); + aStart++; + aEnd--; } } } void transform(const basegfx::B3DHomMatrix& rMatrix) { - CoordinateData3DVector::iterator aStart(maVector.begin()); - CoordinateData3DVector::iterator aEnd(maVector.end()); + NormalsData3DVector::iterator aStart(maVector.begin()); + NormalsData3DVector::iterator aEnd(maVector.end()); for(; aStart != aEnd; aStart++) { - aStart->transform(rMatrix); + (*aStart) *= rMatrix; + } + } +}; + +////////////////////////////////////////////////////////////////////////////// + +class TextureCoordinate2D +{ + typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector; + + TextureData2DVector maVector; + sal_uInt32 mnUsedEntries; + +public: + explicit TextureCoordinate2D(sal_uInt32 nCount) + : maVector(nCount), + mnUsedEntries(0L) + { + } + + explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal) + : maVector(rOriginal.maVector), + mnUsedEntries(rOriginal.mnUsedEntries) + { + } + + TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) + : maVector(), + mnUsedEntries(0L) + { + TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin()); + aStart += nIndex; + TextureData2DVector::const_iterator aEnd(aStart); + aEnd += nCount; + maVector.reserve(nCount); + + for(; aStart != aEnd; aStart++) + { + if(!aStart->equalZero()) + mnUsedEntries++; + + maVector.push_back(*aStart); + } + } + + ~TextureCoordinate2D() + { + } + + sal_uInt32 count() const + { + return maVector.size(); + } + + bool operator==(const TextureCoordinate2D& rCandidate) const + { + return (maVector == rCandidate.maVector); + } + + bool isUsed() const + { + return (0L != mnUsedEntries); + } + + const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const + { + return maVector[nIndex]; + } + + void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue) + { + bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero()); + bool bIsUsed(!rValue.equalZero()); + + if(bWasUsed) + { + if(bIsUsed) + { + maVector[nIndex] = rValue; + } + else + { + maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint(); + mnUsedEntries--; + } + } + else + { + if(bIsUsed) + { + maVector[nIndex] = rValue; + mnUsedEntries++; + } + } + } + + void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount) + { + if(nCount) + { + // add nCount copies of rValue + TextureData2DVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + maVector.insert(aIndex, nCount, rValue); + + if(!rValue.equalZero()) + mnUsedEntries += nCount; + } + } + + void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource) + { + const sal_uInt32 nCount(rSource.maVector.size()); + + if(nCount) + { + // insert data + TextureData2DVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + TextureData2DVector::const_iterator aStart(rSource.maVector.begin()); + TextureData2DVector::const_iterator aEnd(rSource.maVector.end()); + maVector.insert(aIndex, aStart, aEnd); + + for(; aStart != aEnd; aStart++) + { + if(!aStart->equalZero()) + mnUsedEntries++; + } + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex); + const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount); + TextureData2DVector::const_iterator aStart(aDeleteStart); + + for(; mnUsedEntries && aStart != aDeleteEnd; aStart++) + { + if(!aStart->equalZero()) + mnUsedEntries--; + } + + // remove point data + maVector.erase(aDeleteStart, aDeleteEnd); + } + } + + void flip() + { + if(maVector.size() > 1) + { + const sal_uInt32 nHalfSize(maVector.size() >> 1L); + TextureData2DVector::iterator aStart(maVector.begin()); + TextureData2DVector::iterator aEnd(maVector.end() - 1L); + + for(sal_uInt32 a(0); a < nHalfSize; a++) + { + ::std::swap(*aStart, *aEnd); + aStart++; + aEnd--; + } + } + } + + void transform(const ::basegfx::B2DHomMatrix& rMatrix) + { + TextureData2DVector::iterator aStart(maVector.begin()); + TextureData2DVector::iterator aEnd(maVector.end()); + + for(; aStart != aEnd; aStart++) + { + (*aStart) *= rMatrix; } } }; @@ -228,21 +784,141 @@ class ImplB3DPolygon // count of members. CoordinateDataArray3D maPoints; + // The BColor vector. This vectors are created on demand + // and may be zero. + BColorArray* mpBColors; + + // The Normals vector. This vectors are created on demand + // and may be zero. + NormalsArray3D* mpNormals; + + // The TextureCoordinates vector. This vectors are created on demand + // and may be zero. + TextureCoordinate2D* mpTextureCoordiantes; + + // The calculated plane normal. mbPlaneNormalValid says if it's valid. + ::basegfx::B3DVector maPlaneNormal; + // bitfield // flag which decides if this polygon is opened or closed - bool mbIsClosed; + unsigned mbIsClosed : 1; + + // flag which says if maPlaneNormal is up-to-date + unsigned mbPlaneNormalValid : 1; + +protected: + void invalidatePlaneNormal() + { + if(mbPlaneNormalValid) + { + mbPlaneNormalValid = false; + } + } public: - ImplB3DPolygon() : - maPoints(0L), - mbIsClosed(false) + // This constructor is only used from the static identity polygon, thus + // the RefCount is set to 1 to never 'delete' this static incarnation. + ImplB3DPolygon() + : maPoints(0L), + mpBColors(0L), + mpNormals(0L), + mpTextureCoordiantes(0L), + maPlaneNormal(::basegfx::B3DVector::getEmptyVector()), + mbIsClosed(false), + mbPlaneNormalValid(true) + { + // complete initialization with defaults + } + + ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied) + : maPoints(rToBeCopied.maPoints), + mpBColors(0L), + mpNormals(0L), + mpTextureCoordiantes(0L), + maPlaneNormal(rToBeCopied.maPlaneNormal), + mbIsClosed(rToBeCopied.mbIsClosed), + mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid) { + // complete initialization using copy + if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed()) + { + mpBColors = new BColorArray(*rToBeCopied.mpBColors); + } + + if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed()) + { + mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals); + } + + if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed()) + { + mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes); + } + } + + ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount) + : maPoints(rToBeCopied.maPoints, nIndex, nCount), + mpBColors(0L), + mpNormals(0L), + mpTextureCoordiantes(0L), + maPlaneNormal(::basegfx::B3DVector::getEmptyVector()), + mbIsClosed(rToBeCopied.mbIsClosed), + mbPlaneNormalValid(false) + { + // complete initialization using partly copy + if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed()) + { + mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount); + + if(!mpBColors->isUsed()) + { + delete mpBColors; + mpBColors = 0L; + } + } + + if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed()) + { + mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount); + + if(!mpNormals->isUsed()) + { + delete mpNormals; + mpNormals = 0L; + } + } + + if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed()) + { + mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount); + + if(!mpTextureCoordiantes->isUsed()) + { + delete mpTextureCoordiantes; + mpTextureCoordiantes = 0L; + } + } } - ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount) : - maPoints(rToBeCopied.maPoints, nIndex, nCount), - mbIsClosed(rToBeCopied.mbIsClosed) + ~ImplB3DPolygon() { + if(mpBColors) + { + delete mpBColors; + mpBColors = 0L; + } + + if(mpNormals) + { + delete mpNormals; + mpNormals = 0L; + } + + if(mpTextureCoordiantes) + { + delete mpTextureCoordiantes; + mpTextureCoordiantes = 0L; + } } sal_uInt32 count() const @@ -257,41 +933,322 @@ public: void setClosed(bool bNew) { - if(bNew != mbIsClosed) + if(bNew != (bool)mbIsClosed) { mbIsClosed = bNew; } } + inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const + { + bool bBColorsAreEqual(true); + + if(mpBColors) + { + if(rCandidate.mpBColors) + { + bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors); + } + else + { + // candidate has no BColors, so it's assumed all unused. + bBColorsAreEqual = !mpBColors->isUsed(); + } + } + else + { + if(rCandidate.mpBColors) + { + // we have no TextureCoordiantes, so it's assumed all unused. + bBColorsAreEqual = !rCandidate.mpBColors->isUsed(); + } + } + + return bBColorsAreEqual; + } + + inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const + { + bool bNormalsAreEqual(true); + + if(mpNormals) + { + if(rCandidate.mpNormals) + { + bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals); + } + else + { + // candidate has no normals, so it's assumed all unused. + bNormalsAreEqual = !mpNormals->isUsed(); + } + } + else + { + if(rCandidate.mpNormals) + { + // we have no normals, so it's assumed all unused. + bNormalsAreEqual = !rCandidate.mpNormals->isUsed(); + } + } + + return bNormalsAreEqual; + } + + inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const + { + bool bTextureCoordinatesAreEqual(true); + + if(mpTextureCoordiantes) + { + if(rCandidate.mpTextureCoordiantes) + { + bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes); + } + else + { + // candidate has no TextureCoordinates, so it's assumed all unused. + bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed(); + } + } + else + { + if(rCandidate.mpTextureCoordiantes) + { + // we have no TextureCoordiantes, so it's assumed all unused. + bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed(); + } + } + + return bTextureCoordinatesAreEqual; + } + bool operator==(const ImplB3DPolygon& rCandidate) const { if(mbIsClosed == rCandidate.mbIsClosed) { if(maPoints == rCandidate.maPoints) { - return true; + if(impBColorsAreEqual(rCandidate)) + { + if(impNormalsAreEqual(rCandidate)) + { + if(impTextureCoordinatesAreEqual(rCandidate)) + { + return true; + } + } + } } } return false; } - const basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const + const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const { return maPoints.getCoordinate(nIndex); } - void setPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue) + void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue) { maPoints.setCoordinate(nIndex, rValue); + invalidatePlaneNormal(); } - void insert(sal_uInt32 nIndex, const basegfx::B3DPoint& rPoint, sal_uInt32 nCount) + void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount) { if(nCount) { CoordinateData3D aCoordinate(rPoint); maPoints.insert(nIndex, aCoordinate, nCount); + invalidatePlaneNormal(); + + if(mpBColors) + { + mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount); + } + + if(mpNormals) + { + mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount); + } + + if(mpTextureCoordiantes) + { + mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount); + } + } + } + + const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const + { + if(mpBColors) + { + return mpBColors->getBColor(nIndex); + } + else + { + return ::basegfx::BColor::getEmptyBColor(); + } + } + + void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue) + { + if(!mpBColors) + { + if(!rValue.equalZero()) + { + mpBColors = new BColorArray(maPoints.count()); + mpBColors->setBColor(nIndex, rValue); + } + } + else + { + mpBColors->setBColor(nIndex, rValue); + + if(!mpBColors->isUsed()) + { + delete mpBColors; + mpBColors = 0L; + } + } + } + + bool areBColorsUsed() const + { + return (mpBColors && mpBColors->isUsed()); + } + + void clearBColors() + { + if(mpBColors) + { + delete mpBColors; + mpBColors = 0L; + } + } + + const ::basegfx::B3DVector& getNormal() const + { + if(!mbPlaneNormalValid) + { + const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal(); + const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true; + } + + return maPlaneNormal; + } + + const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const + { + if(mpNormals) + { + return mpNormals->getNormal(nIndex); + } + else + { + return ::basegfx::B3DVector::getEmptyVector(); + } + } + + void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue) + { + if(!mpNormals) + { + if(!rValue.equalZero()) + { + mpNormals = new NormalsArray3D(maPoints.count()); + mpNormals->setNormal(nIndex, rValue); + } + } + else + { + mpNormals->setNormal(nIndex, rValue); + + if(!mpNormals->isUsed()) + { + delete mpNormals; + mpNormals = 0L; + } + } + } + + void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix) + { + if(mpNormals) + { + mpNormals->transform(rMatrix); + } + } + + bool areNormalsUsed() const + { + return (mpNormals && mpNormals->isUsed()); + } + + void clearNormals() + { + if(mpNormals) + { + delete mpNormals; + mpNormals = 0L; + } + } + + const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const + { + if(mpTextureCoordiantes) + { + return mpTextureCoordiantes->getTextureCoordinate(nIndex); + } + else + { + return ::basegfx::B2DPoint::getEmptyPoint(); + } + } + + void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue) + { + if(!mpTextureCoordiantes) + { + if(!rValue.equalZero()) + { + mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count()); + mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue); + } + } + else + { + mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue); + + if(!mpTextureCoordiantes->isUsed()) + { + delete mpTextureCoordiantes; + mpTextureCoordiantes = 0L; + } + } + } + + bool areTextureCoordinatesUsed() const + { + return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed()); + } + + void clearTextureCoordinates() + { + if(mpTextureCoordiantes) + { + delete mpTextureCoordiantes; + mpTextureCoordiantes = 0L; + } + } + + void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix) + { + if(mpTextureCoordiantes) + { + mpTextureCoordiantes->transform(rMatrix); } } @@ -302,6 +1259,58 @@ public: if(nCount) { maPoints.insert(nIndex, rSource.maPoints); + invalidatePlaneNormal(); + + if(rSource.mpBColors && rSource.mpBColors->isUsed()) + { + if(!mpBColors) + { + mpBColors = new BColorArray(maPoints.count()); + } + + mpBColors->insert(nIndex, *rSource.mpBColors); + } + else + { + if(mpBColors) + { + mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount); + } + } + + if(rSource.mpNormals && rSource.mpNormals->isUsed()) + { + if(!mpNormals) + { + mpNormals = new NormalsArray3D(maPoints.count()); + } + + mpNormals->insert(nIndex, *rSource.mpNormals); + } + else + { + if(mpNormals) + { + mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount); + } + } + + if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed()) + { + if(!mpTextureCoordiantes) + { + mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count()); + } + + mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes); + } + else + { + if(mpTextureCoordiantes) + { + mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount); + } + } } } @@ -310,6 +1319,40 @@ public: if(nCount) { maPoints.remove(nIndex, nCount); + invalidatePlaneNormal(); + + if(mpBColors) + { + mpBColors->remove(nIndex, nCount); + + if(!mpBColors->isUsed()) + { + delete mpBColors; + mpBColors = 0L; + } + } + + if(mpNormals) + { + mpNormals->remove(nIndex, nCount); + + if(!mpNormals->isUsed()) + { + delete mpNormals; + mpNormals = 0L; + } + } + + if(mpTextureCoordiantes) + { + mpTextureCoordiantes->remove(nIndex, nCount); + + if(!mpTextureCoordiantes->isUsed()) + { + delete mpTextureCoordiantes; + mpTextureCoordiantes = 0L; + } + } } } @@ -318,6 +1361,27 @@ public: if(maPoints.count() > 1) { maPoints.flip(); + + if(mbPlaneNormalValid) + { + // mirror plane normal + maPlaneNormal = -maPlaneNormal; + } + + if(mpBColors) + { + mpBColors->flip(); + } + + if(mpNormals) + { + mpNormals->flip(); + } + + if(mpTextureCoordiantes) + { + mpTextureCoordiantes->flip(); + } } } @@ -330,7 +1394,22 @@ public: if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex)) { - return true; + const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex))); + + if(bBColorEqual) + { + const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex))); + + if(bNormalsEqual) + { + const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex))); + + if(bTextureCoordinatesEqual) + { + return true; + } + } + } } } @@ -339,7 +1418,22 @@ public: { if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L)) { - return true; + const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L))); + + if(bBColorEqual) + { + const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L))); + + if(bNormalsEqual) + { + const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L))); + + if(bTextureCoordinatesEqual) + { + return true; + } + } + } } } @@ -351,18 +1445,92 @@ public: // Only remove DoublePoints at Begin and End when poly is closed if(mbIsClosed) { - maPoints.removeDoublePointsAtBeginEnd(); + bool bRemove; + + do + { + bRemove = false; + + if(maPoints.count() > 1L) + { + const sal_uInt32 nIndex(maPoints.count() - 1L); + bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex)); + + if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex))) + { + bRemove = false; + } + + if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex))) + { + bRemove = false; + } + + if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex))) + { + bRemove = false; + } + } + + if(bRemove) + { + const sal_uInt32 nIndex(maPoints.count() - 1L); + remove(nIndex, 1L); + } + } while(bRemove); } } void removeDoublePointsWholeTrack() { - maPoints.removeDoublePointsWholeTrack(); + sal_uInt32 nIndex(0L); + + // test as long as there are at least two points and as long as the index + // is smaller or equal second last point + while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L)) + { + const sal_uInt32 nNextIndex(nIndex + 1L); + bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex)); + + if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex))) + { + bRemove = false; + } + + if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex))) + { + bRemove = false; + } + + if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex))) + { + bRemove = false; + } + + if(bRemove) + { + // if next is same as index and the control vectors are unused, delete index + remove(nIndex, 1L); + } + else + { + // if different, step forward + nIndex++; + } + } } - void transform(const basegfx::B3DHomMatrix& rMatrix) + void transform(const ::basegfx::B3DHomMatrix& rMatrix) { maPoints.transform(rMatrix); + + // Here, it seems to be possible to transform a valid plane normal and to avoid + // invalidation, but it's not true. If the transformation contains shears or e.g. + // perspective projection, the orthogonality to the transformed plane will not + // be preserved. It may be possible to test that at the matrix to not invalidate in + // all cases or to extract a matrix which does not 'shear' the vector which is + // a normal in this case. As long as this is not sure, i will just invalidate. + invalidatePlaneNormal(); } }; @@ -411,7 +1579,7 @@ namespace basegfx if(mpPolygon.same_object(rPolygon.mpPolygon)) return true; - return ((*mpPolygon) == (*rPolygon.mpPolygon)); + return (*mpPolygon == *rPolygon.mpPolygon); } bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const @@ -439,7 +1607,102 @@ namespace basegfx mpPolygon->setPoint(nIndex, rValue); } - void B3DPolygon::insert(sal_uInt32 nIndex, const basegfx::B3DPoint& rPoint, sal_uInt32 nCount) + BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const + { + OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); + + return mpPolygon->getBColor(nIndex); + } + + void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue) + { + OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); + + if(mpPolygon->getBColor(nIndex) != rValue) + mpPolygon->setBColor(nIndex, rValue); + } + + bool B3DPolygon::areBColorsUsed() const + { + return mpPolygon->areBColorsUsed(); + } + + void B3DPolygon::clearBColors() + { + if(mpPolygon->areBColorsUsed()) + mpPolygon->clearBColors(); + } + + B3DVector B3DPolygon::getNormal() const + { + return mpPolygon->getNormal(); + } + + B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const + { + OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); + + return mpPolygon->getNormal(nIndex); + } + + void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue) + { + OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); + + if(mpPolygon->getNormal(nIndex) != rValue) + mpPolygon->setNormal(nIndex, rValue); + } + + void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix) + { + if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity()) + mpPolygon->transformNormals(rMatrix); + } + + bool B3DPolygon::areNormalsUsed() const + { + return mpPolygon->areNormalsUsed(); + } + + void B3DPolygon::clearNormals() + { + if(mpPolygon->areNormalsUsed()) + mpPolygon->clearNormals(); + } + + B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const + { + OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); + + return mpPolygon->getTextureCoordinate(nIndex); + } + + void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue) + { + OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); + + if(mpPolygon->getTextureCoordinate(nIndex) != rValue) + mpPolygon->setTextureCoordinate(nIndex, rValue); + } + + void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix) + { + if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity()) + mpPolygon->transformTextureCoordinates(rMatrix); + } + + bool B3DPolygon::areTextureCoordinatesUsed() const + { + return mpPolygon->areTextureCoordinatesUsed(); + } + + void B3DPolygon::clearTextureCoordinates() + { + if(mpPolygon->areTextureCoordinatesUsed()) + mpPolygon->clearTextureCoordinates(); + } + + void B3DPolygon::insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount) { OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)"); |