| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_basegfx.hxx" |
| #include <osl/diagnose.h> |
| #include <basegfx/polygon/b3dpolygon.hxx> |
| #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> |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| class CoordinateData3D |
| { |
| basegfx::B3DPoint maPoint; |
| |
| public: |
| CoordinateData3D() |
| : maPoint() |
| { |
| } |
| |
| explicit CoordinateData3D(const basegfx::B3DPoint& rData) |
| : maPoint(rData) |
| { |
| } |
| |
| const basegfx::B3DPoint& getCoordinate() const |
| { |
| return maPoint; |
| } |
| |
| void setCoordinate(const basegfx::B3DPoint& rValue) |
| { |
| if(rValue != maPoint) |
| maPoint = rValue; |
| } |
| |
| bool operator==(const CoordinateData3D& rData) const |
| { |
| return (maPoint == rData.getCoordinate()); |
| } |
| |
| void transform(const basegfx::B3DHomMatrix& rMatrix) |
| { |
| maPoint *= rMatrix; |
| } |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| class CoordinateDataArray3D |
| { |
| typedef ::std::vector< CoordinateData3D > CoordinateData3DVector; |
| |
| CoordinateData3DVector maVector; |
| |
| public: |
| explicit CoordinateDataArray3D(sal_uInt32 nCount) |
| : maVector(nCount) |
| { |
| } |
| |
| explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal) |
| : maVector(rOriginal.maVector) |
| { |
| } |
| |
| CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) |
| : maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount)) |
| { |
| } |
| |
| ~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(); |
| } |
| |
| bool operator==(const CoordinateDataArray3D& rCandidate) const |
| { |
| return (maVector == rCandidate.maVector); |
| } |
| |
| const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const |
| { |
| return maVector[nIndex].getCoordinate(); |
| } |
| |
| void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue) |
| { |
| maVector[nIndex].setCoordinate(rValue); |
| } |
| |
| void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount) |
| { |
| if(nCount) |
| { |
| // add nCount copies of rValue |
| CoordinateData3DVector::iterator aIndex(maVector.begin()); |
| aIndex += nIndex; |
| maVector.insert(aIndex, nCount, rValue); |
| } |
| } |
| |
| void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource) |
| { |
| const sal_uInt32 nCount(rSource.maVector.size()); |
| |
| if(nCount) |
| { |
| // insert data |
| CoordinateData3DVector::iterator aIndex(maVector.begin()); |
| aIndex += nIndex; |
| CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin()); |
| CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end()); |
| maVector.insert(aIndex, aStart, aEnd); |
| } |
| } |
| |
| void remove(sal_uInt32 nIndex, sal_uInt32 nCount) |
| { |
| if(nCount) |
| { |
| // remove point data |
| CoordinateData3DVector::iterator aStart(maVector.begin()); |
| aStart += nIndex; |
| const CoordinateData3DVector::iterator aEnd(aStart + nCount); |
| maVector.erase(aStart, aEnd); |
| } |
| } |
| |
| void flip() |
| { |
| if(maVector.size() > 1) |
| { |
| const sal_uInt32 nHalfSize(maVector.size() >> 1L); |
| CoordinateData3DVector::iterator aStart(maVector.begin()); |
| CoordinateData3DVector::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()); |
| |
| for(; aStart != aEnd; aStart++) |
| { |
| aStart->transform(rMatrix); |
| } |
| } |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| class BColorArray |
| { |
| typedef ::std::vector< ::basegfx::BColor > BColorDataVector; |
| |
| BColorDataVector maVector; |
| sal_uInt32 mnUsedEntries; |
| |
| public: |
| explicit BColorArray(sal_uInt32 nCount) |
| : maVector(nCount), |
| mnUsedEntries(0L) |
| { |
| } |
| |
| 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(!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) |
| { |
| maVector[nIndex] = rValue; |
| } |
| else |
| { |
| 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) |
| { |
| NormalsData3DVector::iterator aStart(maVector.begin()); |
| NormalsData3DVector::iterator aEnd(maVector.end()); |
| |
| for(; aStart != aEnd; aStart++) |
| { |
| (*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; |
| } |
| } |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| class ImplB3DPolygon |
| { |
| // The point vector. This vector exists always and defines the |
| // 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 |
| unsigned mbIsClosed : 1; |
| |
| // flag which says if maPlaneNormal is up-to-date |
| unsigned mbPlaneNormalValid : 1; |
| |
| protected: |
| void invalidatePlaneNormal() |
| { |
| if(mbPlaneNormalValid) |
| { |
| mbPlaneNormalValid = false; |
| } |
| } |
| |
| public: |
| // 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() |
| { |
| if(mpBColors) |
| { |
| delete mpBColors; |
| mpBColors = 0L; |
| } |
| |
| if(mpNormals) |
| { |
| delete mpNormals; |
| mpNormals = 0L; |
| } |
| |
| if(mpTextureCoordiantes) |
| { |
| delete mpTextureCoordiantes; |
| mpTextureCoordiantes = 0L; |
| } |
| } |
| |
| sal_uInt32 count() const |
| { |
| return maPoints.count(); |
| } |
| |
| bool isClosed() const |
| { |
| return mbIsClosed; |
| } |
| |
| void setClosed(bool bNew) |
| { |
| 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) |
| { |
| if(impBColorsAreEqual(rCandidate)) |
| { |
| if(impNormalsAreEqual(rCandidate)) |
| { |
| if(impTextureCoordinatesAreEqual(rCandidate)) |
| { |
| return true; |
| } |
| } |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const |
| { |
| return maPoints.getCoordinate(nIndex); |
| } |
| |
| 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) |
| { |
| 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); |
| } |
| } |
| |
| void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource) |
| { |
| const sal_uInt32 nCount(rSource.maPoints.count()); |
| |
| 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); |
| } |
| } |
| } |
| } |
| |
| void remove(sal_uInt32 nIndex, sal_uInt32 nCount) |
| { |
| 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; |
| } |
| } |
| } |
| } |
| |
| void flip() |
| { |
| 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(); |
| } |
| } |
| } |
| |
| bool hasDoublePoints() const |
| { |
| if(mbIsClosed) |
| { |
| // check for same start and end point |
| const sal_uInt32 nIndex(maPoints.count() - 1L); |
| |
| if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex)) |
| { |
| 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; |
| } |
| } |
| } |
| } |
| } |
| |
| // test for range |
| for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++) |
| { |
| if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L)) |
| { |
| 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; |
| } |
| } |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| void removeDoublePointsAtBeginEnd() |
| { |
| // Only remove DoublePoints at Begin and End when poly is closed |
| if(mbIsClosed) |
| { |
| 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() |
| { |
| 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) |
| { |
| 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(); |
| } |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| namespace basegfx |
| { |
| namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType, |
| DefaultPolygon > {}; } |
| |
| B3DPolygon::B3DPolygon() : |
| mpPolygon(DefaultPolygon::get()) |
| { |
| } |
| |
| B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) : |
| mpPolygon(rPolygon.mpPolygon) |
| { |
| } |
| |
| B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount) : |
| mpPolygon(ImplB3DPolygon(*rPolygon.mpPolygon, nIndex, nCount)) |
| { |
| // TODO(P2): one extra temporary here (cow_wrapper copies |
| // given ImplB3DPolygon into its internal impl_t wrapper type) |
| OSL_ENSURE(nIndex + nCount > rPolygon.mpPolygon->count(), "B3DPolygon constructor outside range (!)"); |
| } |
| |
| B3DPolygon::~B3DPolygon() |
| { |
| } |
| |
| B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon) |
| { |
| mpPolygon = rPolygon.mpPolygon; |
| return *this; |
| } |
| |
| void B3DPolygon::makeUnique() |
| { |
| mpPolygon.make_unique(); |
| } |
| |
| bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const |
| { |
| if(mpPolygon.same_object(rPolygon.mpPolygon)) |
| return true; |
| |
| return (*mpPolygon == *rPolygon.mpPolygon); |
| } |
| |
| bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const |
| { |
| return !(*this == rPolygon); |
| } |
| |
| sal_uInt32 B3DPolygon::count() const |
| { |
| return mpPolygon->count(); |
| } |
| |
| basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const |
| { |
| OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); |
| |
| return mpPolygon->getPoint(nIndex); |
| } |
| |
| void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue) |
| { |
| OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)"); |
| |
| if(getB3DPoint(nIndex) != rValue) |
| mpPolygon->setPoint(nIndex, rValue); |
| } |
| |
| 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 (!)"); |
| |
| if(nCount) |
| mpPolygon->insert(nIndex, rPoint, nCount); |
| } |
| |
| void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount) |
| { |
| if(nCount) |
| mpPolygon->insert(mpPolygon->count(), rPoint, nCount); |
| } |
| |
| void B3DPolygon::insert(sal_uInt32 nIndex, const B3DPolygon& rPoly, sal_uInt32 nIndex2, sal_uInt32 nCount) |
| { |
| OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)"); |
| |
| if(rPoly.count()) |
| { |
| if(!nCount) |
| { |
| nCount = rPoly.count(); |
| } |
| |
| if(0L == nIndex2 && nCount == rPoly.count()) |
| { |
| mpPolygon->insert(nIndex, *rPoly.mpPolygon); |
| } |
| else |
| { |
| OSL_ENSURE(nIndex2 + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Insert outside range (!)"); |
| ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex2, nCount); |
| mpPolygon->insert(nIndex, aTempPoly); |
| } |
| } |
| } |
| |
| void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount) |
| { |
| if(rPoly.count()) |
| { |
| if(!nCount) |
| { |
| nCount = rPoly.count(); |
| } |
| |
| if(0L == nIndex && nCount == rPoly.count()) |
| { |
| mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon); |
| } |
| else |
| { |
| OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)"); |
| ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount); |
| mpPolygon->insert(mpPolygon->count(), aTempPoly); |
| } |
| } |
| } |
| |
| void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount) |
| { |
| OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)"); |
| |
| if(nCount) |
| mpPolygon->remove(nIndex, nCount); |
| } |
| |
| void B3DPolygon::clear() |
| { |
| mpPolygon = DefaultPolygon::get(); |
| } |
| |
| bool B3DPolygon::isClosed() const |
| { |
| return mpPolygon->isClosed(); |
| } |
| |
| void B3DPolygon::setClosed(bool bNew) |
| { |
| if(isClosed() != bNew) |
| mpPolygon->setClosed(bNew); |
| } |
| |
| void B3DPolygon::flip() |
| { |
| if(count() > 1) |
| mpPolygon->flip(); |
| } |
| |
| bool B3DPolygon::hasDoublePoints() const |
| { |
| return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints()); |
| } |
| |
| void B3DPolygon::removeDoublePoints() |
| { |
| if(hasDoublePoints()) |
| { |
| mpPolygon->removeDoublePointsAtBeginEnd(); |
| mpPolygon->removeDoublePointsWholeTrack(); |
| } |
| } |
| |
| void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix) |
| { |
| if(mpPolygon->count() && !rMatrix.isIdentity()) |
| { |
| mpPolygon->transform(rMatrix); |
| } |
| } |
| } // end of namespace basegfx |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // eof |