1*09dbbe93SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*09dbbe93SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*09dbbe93SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*09dbbe93SAndrew Rist  * distributed with this work for additional information
6*09dbbe93SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*09dbbe93SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*09dbbe93SAndrew Rist  * "License"); you may not use this file except in compliance
9*09dbbe93SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*09dbbe93SAndrew Rist  *
11*09dbbe93SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*09dbbe93SAndrew Rist  *
13*09dbbe93SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*09dbbe93SAndrew Rist  * software distributed under the License is distributed on an
15*09dbbe93SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*09dbbe93SAndrew Rist  * KIND, either express or implied.  See the License for the
17*09dbbe93SAndrew Rist  * specific language governing permissions and limitations
18*09dbbe93SAndrew Rist  * under the License.
19*09dbbe93SAndrew Rist  *
20*09dbbe93SAndrew Rist  *************************************************************/
21*09dbbe93SAndrew Rist 
22*09dbbe93SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basegfx.hxx"
26cdf0e10cSrcweir #include <osl/diagnose.h>
27cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygon.hxx>
28cdf0e10cSrcweir #include <basegfx/point/b3dpoint.hxx>
29cdf0e10cSrcweir #include <basegfx/matrix/b3dhommatrix.hxx>
30cdf0e10cSrcweir #include <rtl/instance.hxx>
31cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
32cdf0e10cSrcweir #include <basegfx/color/bcolor.hxx>
33cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
34cdf0e10cSrcweir #include <vector>
35cdf0e10cSrcweir #include <algorithm>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
38cdf0e10cSrcweir 
39cdf0e10cSrcweir class CoordinateData3D
40cdf0e10cSrcweir {
41cdf0e10cSrcweir 	basegfx::B3DPoint								maPoint;
42cdf0e10cSrcweir 
43cdf0e10cSrcweir public:
CoordinateData3D()44cdf0e10cSrcweir 	CoordinateData3D()
45cdf0e10cSrcweir 	:	maPoint()
46cdf0e10cSrcweir 	{
47cdf0e10cSrcweir 	}
48cdf0e10cSrcweir 
CoordinateData3D(const basegfx::B3DPoint & rData)49cdf0e10cSrcweir 	explicit CoordinateData3D(const basegfx::B3DPoint& rData)
50cdf0e10cSrcweir 	:	maPoint(rData)
51cdf0e10cSrcweir 	{
52cdf0e10cSrcweir 	}
53cdf0e10cSrcweir 
getCoordinate() const54cdf0e10cSrcweir 	const basegfx::B3DPoint& getCoordinate() const
55cdf0e10cSrcweir 	{
56cdf0e10cSrcweir 		return maPoint;
57cdf0e10cSrcweir 	}
58cdf0e10cSrcweir 
setCoordinate(const basegfx::B3DPoint & rValue)59cdf0e10cSrcweir 	void setCoordinate(const basegfx::B3DPoint& rValue)
60cdf0e10cSrcweir 	{
61cdf0e10cSrcweir 		if(rValue != maPoint)
62cdf0e10cSrcweir 			maPoint = rValue;
63cdf0e10cSrcweir 	}
64cdf0e10cSrcweir 
operator ==(const CoordinateData3D & rData) const65cdf0e10cSrcweir 	bool operator==(const CoordinateData3D& rData) const
66cdf0e10cSrcweir 	{
67cdf0e10cSrcweir 		return (maPoint == rData.getCoordinate());
68cdf0e10cSrcweir 	}
69cdf0e10cSrcweir 
transform(const basegfx::B3DHomMatrix & rMatrix)70cdf0e10cSrcweir 	void transform(const basegfx::B3DHomMatrix& rMatrix)
71cdf0e10cSrcweir 	{
72cdf0e10cSrcweir 		maPoint *= rMatrix;
73cdf0e10cSrcweir 	}
74cdf0e10cSrcweir };
75cdf0e10cSrcweir 
76cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
77cdf0e10cSrcweir 
78cdf0e10cSrcweir class CoordinateDataArray3D
79cdf0e10cSrcweir {
80cdf0e10cSrcweir 	typedef ::std::vector< CoordinateData3D > CoordinateData3DVector;
81cdf0e10cSrcweir 
82cdf0e10cSrcweir 	CoordinateData3DVector							maVector;
83cdf0e10cSrcweir 
84cdf0e10cSrcweir public:
CoordinateDataArray3D(sal_uInt32 nCount)85cdf0e10cSrcweir 	explicit CoordinateDataArray3D(sal_uInt32 nCount)
86cdf0e10cSrcweir 	:	maVector(nCount)
87cdf0e10cSrcweir 	{
88cdf0e10cSrcweir 	}
89cdf0e10cSrcweir 
CoordinateDataArray3D(const CoordinateDataArray3D & rOriginal)90cdf0e10cSrcweir 	explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal)
91cdf0e10cSrcweir 	:	maVector(rOriginal.maVector)
92cdf0e10cSrcweir 	{
93cdf0e10cSrcweir 	}
94cdf0e10cSrcweir 
CoordinateDataArray3D(const CoordinateDataArray3D & rOriginal,sal_uInt32 nIndex,sal_uInt32 nCount)95cdf0e10cSrcweir 	CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
96cdf0e10cSrcweir 	:	maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
97cdf0e10cSrcweir 	{
98cdf0e10cSrcweir 	}
99cdf0e10cSrcweir 
~CoordinateDataArray3D()100cdf0e10cSrcweir 	~CoordinateDataArray3D()
101cdf0e10cSrcweir 	{
102cdf0e10cSrcweir 	}
103cdf0e10cSrcweir 
getNormal() const104cdf0e10cSrcweir 	::basegfx::B3DVector getNormal() const
105cdf0e10cSrcweir 	{
106cdf0e10cSrcweir 		::basegfx::B3DVector aRetval;
107cdf0e10cSrcweir 		const sal_uInt32 nPointCount(maVector.size());
108cdf0e10cSrcweir 
109cdf0e10cSrcweir 		if(nPointCount > 2)
110cdf0e10cSrcweir 		{
111cdf0e10cSrcweir             sal_uInt32 nISmallest(0);
112cdf0e10cSrcweir             sal_uInt32 a(0);
113cdf0e10cSrcweir             const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate());
114cdf0e10cSrcweir             const basegfx::B3DPoint* pNext(0);
115cdf0e10cSrcweir             const basegfx::B3DPoint* pPrev(0);
116cdf0e10cSrcweir 
117cdf0e10cSrcweir             // To guarantee a correctly oriented point, choose an outmost one
118cdf0e10cSrcweir             // which then cannot be concave
119cdf0e10cSrcweir             for(a = 1; a < nPointCount; a++)
120cdf0e10cSrcweir             {
121cdf0e10cSrcweir             	const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
122cdf0e10cSrcweir 
123cdf0e10cSrcweir                 if((rCandidate.getX() < pSmallest->getX())
124cdf0e10cSrcweir                     || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY())
125cdf0e10cSrcweir                     || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ()))
126cdf0e10cSrcweir                 {
127cdf0e10cSrcweir                     nISmallest = a;
128cdf0e10cSrcweir                     pSmallest = &rCandidate;
129cdf0e10cSrcweir                 }
130cdf0e10cSrcweir             }
131cdf0e10cSrcweir 
132cdf0e10cSrcweir             // look for a next point different from minimal one
133cdf0e10cSrcweir             for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount)
134cdf0e10cSrcweir             {
135cdf0e10cSrcweir             	const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
136cdf0e10cSrcweir 
137cdf0e10cSrcweir                 if(!rCandidate.equal(*pSmallest))
138cdf0e10cSrcweir                 {
139cdf0e10cSrcweir                 	pNext = &rCandidate;
140cdf0e10cSrcweir                     break;
141cdf0e10cSrcweir                 }
142cdf0e10cSrcweir             }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir             // look for a previous point different from minimal one
145cdf0e10cSrcweir             for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount)
146cdf0e10cSrcweir             {
147cdf0e10cSrcweir             	const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
148cdf0e10cSrcweir 
149cdf0e10cSrcweir                 if(!rCandidate.equal(*pSmallest))
150cdf0e10cSrcweir                 {
151cdf0e10cSrcweir                 	pPrev = &rCandidate;
152cdf0e10cSrcweir                     break;
153cdf0e10cSrcweir                 }
154cdf0e10cSrcweir             }
155cdf0e10cSrcweir 
156cdf0e10cSrcweir             // we always have a minimal point. If we also have a different next and previous,
157cdf0e10cSrcweir             // we can calculate the normal
158cdf0e10cSrcweir             if(pNext && pPrev)
159cdf0e10cSrcweir             {
160cdf0e10cSrcweir                 const basegfx::B3DVector aPrev(*pPrev - *pSmallest);
161cdf0e10cSrcweir                 const basegfx::B3DVector aNext(*pNext - *pSmallest);
162cdf0e10cSrcweir 
163cdf0e10cSrcweir                 aRetval = cross(aPrev, aNext);
164cdf0e10cSrcweir     			aRetval.normalize();
165cdf0e10cSrcweir             }
166cdf0e10cSrcweir 		}
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 		return aRetval;
169cdf0e10cSrcweir 	}
170cdf0e10cSrcweir 
count() const171cdf0e10cSrcweir 	sal_uInt32 count() const
172cdf0e10cSrcweir 	{
173cdf0e10cSrcweir 		return maVector.size();
174cdf0e10cSrcweir 	}
175cdf0e10cSrcweir 
operator ==(const CoordinateDataArray3D & rCandidate) const176cdf0e10cSrcweir 	bool operator==(const CoordinateDataArray3D& rCandidate) const
177cdf0e10cSrcweir 	{
178cdf0e10cSrcweir 		return (maVector == rCandidate.maVector);
179cdf0e10cSrcweir 	}
180cdf0e10cSrcweir 
getCoordinate(sal_uInt32 nIndex) const181cdf0e10cSrcweir 	const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const
182cdf0e10cSrcweir 	{
183cdf0e10cSrcweir 		return maVector[nIndex].getCoordinate();
184cdf0e10cSrcweir 	}
185cdf0e10cSrcweir 
setCoordinate(sal_uInt32 nIndex,const basegfx::B3DPoint & rValue)186cdf0e10cSrcweir 	void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
187cdf0e10cSrcweir 	{
188cdf0e10cSrcweir 		maVector[nIndex].setCoordinate(rValue);
189cdf0e10cSrcweir 	}
190cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const CoordinateData3D & rValue,sal_uInt32 nCount)191cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount)
192cdf0e10cSrcweir 	{
193cdf0e10cSrcweir 		if(nCount)
194cdf0e10cSrcweir 		{
195cdf0e10cSrcweir 			// add nCount copies of rValue
196cdf0e10cSrcweir 			CoordinateData3DVector::iterator aIndex(maVector.begin());
197cdf0e10cSrcweir 			aIndex += nIndex;
198cdf0e10cSrcweir 			maVector.insert(aIndex, nCount, rValue);
199cdf0e10cSrcweir 		}
200cdf0e10cSrcweir 	}
201cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const CoordinateDataArray3D & rSource)202cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource)
203cdf0e10cSrcweir 	{
204cdf0e10cSrcweir 		const sal_uInt32 nCount(rSource.maVector.size());
205cdf0e10cSrcweir 
206cdf0e10cSrcweir 		if(nCount)
207cdf0e10cSrcweir 		{
208cdf0e10cSrcweir 			// insert data
209cdf0e10cSrcweir 			CoordinateData3DVector::iterator aIndex(maVector.begin());
210cdf0e10cSrcweir 			aIndex += nIndex;
211cdf0e10cSrcweir 			CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin());
212cdf0e10cSrcweir 			CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end());
213cdf0e10cSrcweir 			maVector.insert(aIndex, aStart, aEnd);
214cdf0e10cSrcweir 		}
215cdf0e10cSrcweir 	}
216cdf0e10cSrcweir 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)217cdf0e10cSrcweir 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
218cdf0e10cSrcweir 	{
219cdf0e10cSrcweir 		if(nCount)
220cdf0e10cSrcweir 		{
221cdf0e10cSrcweir 			// remove point data
222cdf0e10cSrcweir 			CoordinateData3DVector::iterator aStart(maVector.begin());
223cdf0e10cSrcweir 			aStart += nIndex;
224cdf0e10cSrcweir 			const CoordinateData3DVector::iterator aEnd(aStart + nCount);
225cdf0e10cSrcweir 			maVector.erase(aStart, aEnd);
226cdf0e10cSrcweir 		}
227cdf0e10cSrcweir 	}
228cdf0e10cSrcweir 
flip()229cdf0e10cSrcweir 	void flip()
230cdf0e10cSrcweir 	{
231cdf0e10cSrcweir 		if(maVector.size() > 1)
232cdf0e10cSrcweir 		{
233cdf0e10cSrcweir 			const sal_uInt32 nHalfSize(maVector.size() >> 1L);
234cdf0e10cSrcweir 			CoordinateData3DVector::iterator aStart(maVector.begin());
235cdf0e10cSrcweir 			CoordinateData3DVector::iterator aEnd(maVector.end() - 1L);
236cdf0e10cSrcweir 
237cdf0e10cSrcweir 			for(sal_uInt32 a(0); a < nHalfSize; a++)
238cdf0e10cSrcweir 			{
239cdf0e10cSrcweir 				::std::swap(*aStart, *aEnd);
240cdf0e10cSrcweir 				aStart++;
241cdf0e10cSrcweir 				aEnd--;
242cdf0e10cSrcweir 			}
243cdf0e10cSrcweir 		}
244cdf0e10cSrcweir 	}
245cdf0e10cSrcweir 
transform(const::basegfx::B3DHomMatrix & rMatrix)246cdf0e10cSrcweir 	void transform(const ::basegfx::B3DHomMatrix& rMatrix)
247cdf0e10cSrcweir 	{
248cdf0e10cSrcweir 		CoordinateData3DVector::iterator aStart(maVector.begin());
249cdf0e10cSrcweir 		CoordinateData3DVector::iterator aEnd(maVector.end());
250cdf0e10cSrcweir 
251cdf0e10cSrcweir 		for(; aStart != aEnd; aStart++)
252cdf0e10cSrcweir 		{
253cdf0e10cSrcweir 			aStart->transform(rMatrix);
254cdf0e10cSrcweir 		}
255cdf0e10cSrcweir 	}
256cdf0e10cSrcweir };
257cdf0e10cSrcweir 
258cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
259cdf0e10cSrcweir 
260cdf0e10cSrcweir class BColorArray
261cdf0e10cSrcweir {
262cdf0e10cSrcweir 	typedef ::std::vector< ::basegfx::BColor > BColorDataVector;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir 	BColorDataVector									maVector;
265cdf0e10cSrcweir 	sal_uInt32											mnUsedEntries;
266cdf0e10cSrcweir 
267cdf0e10cSrcweir public:
BColorArray(sal_uInt32 nCount)268cdf0e10cSrcweir 	explicit BColorArray(sal_uInt32 nCount)
269cdf0e10cSrcweir 	:	maVector(nCount),
270cdf0e10cSrcweir 		mnUsedEntries(0L)
271cdf0e10cSrcweir 	{
272cdf0e10cSrcweir 	}
273cdf0e10cSrcweir 
BColorArray(const BColorArray & rOriginal)274cdf0e10cSrcweir 	explicit BColorArray(const BColorArray& rOriginal)
275cdf0e10cSrcweir 	:	maVector(rOriginal.maVector),
276cdf0e10cSrcweir 		mnUsedEntries(rOriginal.mnUsedEntries)
277cdf0e10cSrcweir 	{
278cdf0e10cSrcweir 	}
279cdf0e10cSrcweir 
BColorArray(const BColorArray & rOriginal,sal_uInt32 nIndex,sal_uInt32 nCount)280cdf0e10cSrcweir 	BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
281cdf0e10cSrcweir 	:	maVector(),
282cdf0e10cSrcweir 		mnUsedEntries(0L)
283cdf0e10cSrcweir 	{
284cdf0e10cSrcweir 		BColorDataVector::const_iterator aStart(rOriginal.maVector.begin());
285cdf0e10cSrcweir 		aStart += nIndex;
286cdf0e10cSrcweir 		BColorDataVector::const_iterator aEnd(aStart);
287cdf0e10cSrcweir 		aEnd += nCount;
288cdf0e10cSrcweir 		maVector.reserve(nCount);
289cdf0e10cSrcweir 
290cdf0e10cSrcweir 		for(; aStart != aEnd; aStart++)
291cdf0e10cSrcweir 		{
292cdf0e10cSrcweir 			if(!aStart->equalZero())
293cdf0e10cSrcweir 				mnUsedEntries++;
294cdf0e10cSrcweir 
295cdf0e10cSrcweir 			maVector.push_back(*aStart);
296cdf0e10cSrcweir 		}
297cdf0e10cSrcweir 	}
298cdf0e10cSrcweir 
~BColorArray()299cdf0e10cSrcweir 	~BColorArray()
300cdf0e10cSrcweir 	{
301cdf0e10cSrcweir 	}
302cdf0e10cSrcweir 
count() const303cdf0e10cSrcweir 	sal_uInt32 count() const
304cdf0e10cSrcweir 	{
305cdf0e10cSrcweir 		return maVector.size();
306cdf0e10cSrcweir 	}
307cdf0e10cSrcweir 
operator ==(const BColorArray & rCandidate) const308cdf0e10cSrcweir 	bool operator==(const BColorArray& rCandidate) const
309cdf0e10cSrcweir 	{
310cdf0e10cSrcweir 		return (maVector == rCandidate.maVector);
311cdf0e10cSrcweir 	}
312cdf0e10cSrcweir 
isUsed() const313cdf0e10cSrcweir 	bool isUsed() const
314cdf0e10cSrcweir 	{
315cdf0e10cSrcweir 		return (0L != mnUsedEntries);
316cdf0e10cSrcweir 	}
317cdf0e10cSrcweir 
getBColor(sal_uInt32 nIndex) const318cdf0e10cSrcweir 	const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
319cdf0e10cSrcweir 	{
320cdf0e10cSrcweir 		return maVector[nIndex];
321cdf0e10cSrcweir 	}
322cdf0e10cSrcweir 
setBColor(sal_uInt32 nIndex,const::basegfx::BColor & rValue)323cdf0e10cSrcweir 	void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
324cdf0e10cSrcweir 	{
325cdf0e10cSrcweir 		bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
326cdf0e10cSrcweir 		bool bIsUsed(!rValue.equalZero());
327cdf0e10cSrcweir 
328cdf0e10cSrcweir 		if(bWasUsed)
329cdf0e10cSrcweir 		{
330cdf0e10cSrcweir 			if(bIsUsed)
331cdf0e10cSrcweir 			{
332cdf0e10cSrcweir 				maVector[nIndex] = rValue;
333cdf0e10cSrcweir 			}
334cdf0e10cSrcweir 			else
335cdf0e10cSrcweir 			{
336cdf0e10cSrcweir 				maVector[nIndex] = ::basegfx::BColor::getEmptyBColor();
337cdf0e10cSrcweir 				mnUsedEntries--;
338cdf0e10cSrcweir 			}
339cdf0e10cSrcweir 		}
340cdf0e10cSrcweir 		else
341cdf0e10cSrcweir 		{
342cdf0e10cSrcweir 			if(bIsUsed)
343cdf0e10cSrcweir 			{
344cdf0e10cSrcweir 				maVector[nIndex] = rValue;
345cdf0e10cSrcweir 				mnUsedEntries++;
346cdf0e10cSrcweir 			}
347cdf0e10cSrcweir 		}
348cdf0e10cSrcweir 	}
349cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const::basegfx::BColor & rValue,sal_uInt32 nCount)350cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount)
351cdf0e10cSrcweir 	{
352cdf0e10cSrcweir 		if(nCount)
353cdf0e10cSrcweir 		{
354cdf0e10cSrcweir 			// add nCount copies of rValue
355cdf0e10cSrcweir 			BColorDataVector::iterator aIndex(maVector.begin());
356cdf0e10cSrcweir 			aIndex += nIndex;
357cdf0e10cSrcweir 			maVector.insert(aIndex, nCount, rValue);
358cdf0e10cSrcweir 
359cdf0e10cSrcweir 			if(!rValue.equalZero())
360cdf0e10cSrcweir 				mnUsedEntries += nCount;
361cdf0e10cSrcweir 		}
362cdf0e10cSrcweir 	}
363cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const BColorArray & rSource)364cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const BColorArray& rSource)
365cdf0e10cSrcweir 	{
366cdf0e10cSrcweir 		const sal_uInt32 nCount(rSource.maVector.size());
367cdf0e10cSrcweir 
368cdf0e10cSrcweir 		if(nCount)
369cdf0e10cSrcweir 		{
370cdf0e10cSrcweir 			// insert data
371cdf0e10cSrcweir 			BColorDataVector::iterator aIndex(maVector.begin());
372cdf0e10cSrcweir 			aIndex += nIndex;
373cdf0e10cSrcweir 			BColorDataVector::const_iterator aStart(rSource.maVector.begin());
374cdf0e10cSrcweir 			BColorDataVector::const_iterator aEnd(rSource.maVector.end());
375cdf0e10cSrcweir 			maVector.insert(aIndex, aStart, aEnd);
376cdf0e10cSrcweir 
377cdf0e10cSrcweir 			for(; aStart != aEnd; aStart++)
378cdf0e10cSrcweir 			{
379cdf0e10cSrcweir 				if(!aStart->equalZero())
380cdf0e10cSrcweir 					mnUsedEntries++;
381cdf0e10cSrcweir 			}
382cdf0e10cSrcweir 		}
383cdf0e10cSrcweir 	}
384cdf0e10cSrcweir 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)385cdf0e10cSrcweir 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
386cdf0e10cSrcweir 	{
387cdf0e10cSrcweir 		if(nCount)
388cdf0e10cSrcweir 		{
389cdf0e10cSrcweir 			const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex);
390cdf0e10cSrcweir 			const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount);
391cdf0e10cSrcweir 			BColorDataVector::const_iterator aStart(aDeleteStart);
392cdf0e10cSrcweir 
393cdf0e10cSrcweir 			for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
394cdf0e10cSrcweir 			{
395cdf0e10cSrcweir 				if(!aStart->equalZero())
396cdf0e10cSrcweir 					mnUsedEntries--;
397cdf0e10cSrcweir 			}
398cdf0e10cSrcweir 
399cdf0e10cSrcweir 			// remove point data
400cdf0e10cSrcweir 			maVector.erase(aDeleteStart, aDeleteEnd);
401cdf0e10cSrcweir 		}
402cdf0e10cSrcweir 	}
403cdf0e10cSrcweir 
flip()404cdf0e10cSrcweir 	void flip()
405cdf0e10cSrcweir 	{
406cdf0e10cSrcweir 		if(maVector.size() > 1)
407cdf0e10cSrcweir 		{
408cdf0e10cSrcweir 			const sal_uInt32 nHalfSize(maVector.size() >> 1L);
409cdf0e10cSrcweir 			BColorDataVector::iterator aStart(maVector.begin());
410cdf0e10cSrcweir 			BColorDataVector::iterator aEnd(maVector.end() - 1L);
411cdf0e10cSrcweir 
412cdf0e10cSrcweir 			for(sal_uInt32 a(0); a < nHalfSize; a++)
413cdf0e10cSrcweir 			{
414cdf0e10cSrcweir 				::std::swap(*aStart, *aEnd);
415cdf0e10cSrcweir 				aStart++;
416cdf0e10cSrcweir 				aEnd--;
417cdf0e10cSrcweir 			}
418cdf0e10cSrcweir 		}
419cdf0e10cSrcweir 	}
420cdf0e10cSrcweir };
421cdf0e10cSrcweir 
422cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
423cdf0e10cSrcweir 
424cdf0e10cSrcweir class NormalsArray3D
425cdf0e10cSrcweir {
426cdf0e10cSrcweir 	typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector;
427cdf0e10cSrcweir 
428cdf0e10cSrcweir 	NormalsData3DVector									maVector;
429cdf0e10cSrcweir 	sal_uInt32											mnUsedEntries;
430cdf0e10cSrcweir 
431cdf0e10cSrcweir public:
NormalsArray3D(sal_uInt32 nCount)432cdf0e10cSrcweir 	explicit NormalsArray3D(sal_uInt32 nCount)
433cdf0e10cSrcweir 	:	maVector(nCount),
434cdf0e10cSrcweir 		mnUsedEntries(0L)
435cdf0e10cSrcweir 	{
436cdf0e10cSrcweir 	}
437cdf0e10cSrcweir 
NormalsArray3D(const NormalsArray3D & rOriginal)438cdf0e10cSrcweir 	explicit NormalsArray3D(const NormalsArray3D& rOriginal)
439cdf0e10cSrcweir 	:	maVector(rOriginal.maVector),
440cdf0e10cSrcweir 		mnUsedEntries(rOriginal.mnUsedEntries)
441cdf0e10cSrcweir 	{
442cdf0e10cSrcweir 	}
443cdf0e10cSrcweir 
NormalsArray3D(const NormalsArray3D & rOriginal,sal_uInt32 nIndex,sal_uInt32 nCount)444cdf0e10cSrcweir 	NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
445cdf0e10cSrcweir 	:	maVector(),
446cdf0e10cSrcweir 		mnUsedEntries(0L)
447cdf0e10cSrcweir 	{
448cdf0e10cSrcweir 		NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin());
449cdf0e10cSrcweir 		aStart += nIndex;
450cdf0e10cSrcweir 		NormalsData3DVector::const_iterator aEnd(aStart);
451cdf0e10cSrcweir 		aEnd += nCount;
452cdf0e10cSrcweir 		maVector.reserve(nCount);
453cdf0e10cSrcweir 
454cdf0e10cSrcweir 		for(; aStart != aEnd; aStart++)
455cdf0e10cSrcweir 		{
456cdf0e10cSrcweir 			if(!aStart->equalZero())
457cdf0e10cSrcweir 				mnUsedEntries++;
458cdf0e10cSrcweir 
459cdf0e10cSrcweir 			maVector.push_back(*aStart);
460cdf0e10cSrcweir 		}
461cdf0e10cSrcweir 	}
462cdf0e10cSrcweir 
~NormalsArray3D()463cdf0e10cSrcweir 	~NormalsArray3D()
464cdf0e10cSrcweir 	{
465cdf0e10cSrcweir 	}
466cdf0e10cSrcweir 
count() const467cdf0e10cSrcweir 	sal_uInt32 count() const
468cdf0e10cSrcweir 	{
469cdf0e10cSrcweir 		return maVector.size();
470cdf0e10cSrcweir 	}
471cdf0e10cSrcweir 
operator ==(const NormalsArray3D & rCandidate) const472cdf0e10cSrcweir 	bool operator==(const NormalsArray3D& rCandidate) const
473cdf0e10cSrcweir 	{
474cdf0e10cSrcweir 		return (maVector == rCandidate.maVector);
475cdf0e10cSrcweir 	}
476cdf0e10cSrcweir 
isUsed() const477cdf0e10cSrcweir 	bool isUsed() const
478cdf0e10cSrcweir 	{
479cdf0e10cSrcweir 		return (0L != mnUsedEntries);
480cdf0e10cSrcweir 	}
481cdf0e10cSrcweir 
getNormal(sal_uInt32 nIndex) const482cdf0e10cSrcweir 	const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
483cdf0e10cSrcweir 	{
484cdf0e10cSrcweir 		return maVector[nIndex];
485cdf0e10cSrcweir 	}
486cdf0e10cSrcweir 
setNormal(sal_uInt32 nIndex,const::basegfx::B3DVector & rValue)487cdf0e10cSrcweir 	void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
488cdf0e10cSrcweir 	{
489cdf0e10cSrcweir 		bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
490cdf0e10cSrcweir 		bool bIsUsed(!rValue.equalZero());
491cdf0e10cSrcweir 
492cdf0e10cSrcweir 		if(bWasUsed)
493cdf0e10cSrcweir 		{
494cdf0e10cSrcweir 			if(bIsUsed)
495cdf0e10cSrcweir 			{
496cdf0e10cSrcweir 				maVector[nIndex] = rValue;
497cdf0e10cSrcweir 			}
498cdf0e10cSrcweir 			else
499cdf0e10cSrcweir 			{
500cdf0e10cSrcweir 				maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector();
501cdf0e10cSrcweir 				mnUsedEntries--;
502cdf0e10cSrcweir 			}
503cdf0e10cSrcweir 		}
504cdf0e10cSrcweir 		else
505cdf0e10cSrcweir 		{
506cdf0e10cSrcweir 			if(bIsUsed)
507cdf0e10cSrcweir 			{
508cdf0e10cSrcweir 				maVector[nIndex] = rValue;
509cdf0e10cSrcweir 				mnUsedEntries++;
510cdf0e10cSrcweir 			}
511cdf0e10cSrcweir 		}
512cdf0e10cSrcweir 	}
513cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const::basegfx::B3DVector & rValue,sal_uInt32 nCount)514cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount)
515cdf0e10cSrcweir 	{
516cdf0e10cSrcweir 		if(nCount)
517cdf0e10cSrcweir 		{
518cdf0e10cSrcweir 			// add nCount copies of rValue
519cdf0e10cSrcweir 			NormalsData3DVector::iterator aIndex(maVector.begin());
520cdf0e10cSrcweir 			aIndex += nIndex;
521cdf0e10cSrcweir 			maVector.insert(aIndex, nCount, rValue);
522cdf0e10cSrcweir 
523cdf0e10cSrcweir 			if(!rValue.equalZero())
524cdf0e10cSrcweir 				mnUsedEntries += nCount;
525cdf0e10cSrcweir 		}
526cdf0e10cSrcweir 	}
527cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const NormalsArray3D & rSource)528cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource)
529cdf0e10cSrcweir 	{
530cdf0e10cSrcweir 		const sal_uInt32 nCount(rSource.maVector.size());
531cdf0e10cSrcweir 
532cdf0e10cSrcweir 		if(nCount)
533cdf0e10cSrcweir 		{
534cdf0e10cSrcweir 			// insert data
535cdf0e10cSrcweir 			NormalsData3DVector::iterator aIndex(maVector.begin());
536cdf0e10cSrcweir 			aIndex += nIndex;
537cdf0e10cSrcweir 			NormalsData3DVector::const_iterator aStart(rSource.maVector.begin());
538cdf0e10cSrcweir 			NormalsData3DVector::const_iterator aEnd(rSource.maVector.end());
539cdf0e10cSrcweir 			maVector.insert(aIndex, aStart, aEnd);
540cdf0e10cSrcweir 
541cdf0e10cSrcweir 			for(; aStart != aEnd; aStart++)
542cdf0e10cSrcweir 			{
543cdf0e10cSrcweir 				if(!aStart->equalZero())
544cdf0e10cSrcweir 					mnUsedEntries++;
545cdf0e10cSrcweir 			}
546cdf0e10cSrcweir 		}
547cdf0e10cSrcweir 	}
548cdf0e10cSrcweir 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)549cdf0e10cSrcweir 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
550cdf0e10cSrcweir 	{
551cdf0e10cSrcweir 		if(nCount)
552cdf0e10cSrcweir 		{
553cdf0e10cSrcweir 			const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex);
554cdf0e10cSrcweir 			const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount);
555cdf0e10cSrcweir 			NormalsData3DVector::const_iterator aStart(aDeleteStart);
556cdf0e10cSrcweir 
557cdf0e10cSrcweir 			for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
558cdf0e10cSrcweir 			{
559cdf0e10cSrcweir 				if(!aStart->equalZero())
560cdf0e10cSrcweir 					mnUsedEntries--;
561cdf0e10cSrcweir 			}
562cdf0e10cSrcweir 
563cdf0e10cSrcweir 			// remove point data
564cdf0e10cSrcweir 			maVector.erase(aDeleteStart, aDeleteEnd);
565cdf0e10cSrcweir 		}
566cdf0e10cSrcweir 	}
567cdf0e10cSrcweir 
flip()568cdf0e10cSrcweir 	void flip()
569cdf0e10cSrcweir 	{
570cdf0e10cSrcweir 		if(maVector.size() > 1)
571cdf0e10cSrcweir 		{
572cdf0e10cSrcweir 			const sal_uInt32 nHalfSize(maVector.size() >> 1L);
573cdf0e10cSrcweir 			NormalsData3DVector::iterator aStart(maVector.begin());
574cdf0e10cSrcweir 			NormalsData3DVector::iterator aEnd(maVector.end() - 1L);
575cdf0e10cSrcweir 
576cdf0e10cSrcweir 			for(sal_uInt32 a(0); a < nHalfSize; a++)
577cdf0e10cSrcweir 			{
578cdf0e10cSrcweir 				::std::swap(*aStart, *aEnd);
579cdf0e10cSrcweir 				aStart++;
580cdf0e10cSrcweir 				aEnd--;
581cdf0e10cSrcweir 			}
582cdf0e10cSrcweir 		}
583cdf0e10cSrcweir 	}
584cdf0e10cSrcweir 
transform(const basegfx::B3DHomMatrix & rMatrix)585cdf0e10cSrcweir 	void transform(const basegfx::B3DHomMatrix& rMatrix)
586cdf0e10cSrcweir 	{
587cdf0e10cSrcweir 		NormalsData3DVector::iterator aStart(maVector.begin());
588cdf0e10cSrcweir 		NormalsData3DVector::iterator aEnd(maVector.end());
589cdf0e10cSrcweir 
590cdf0e10cSrcweir 		for(; aStart != aEnd; aStart++)
591cdf0e10cSrcweir 		{
592cdf0e10cSrcweir 			(*aStart) *= rMatrix;
593cdf0e10cSrcweir 		}
594cdf0e10cSrcweir 	}
595cdf0e10cSrcweir };
596cdf0e10cSrcweir 
597cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
598cdf0e10cSrcweir 
599cdf0e10cSrcweir class TextureCoordinate2D
600cdf0e10cSrcweir {
601cdf0e10cSrcweir 	typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector;
602cdf0e10cSrcweir 
603cdf0e10cSrcweir 	TextureData2DVector									maVector;
604cdf0e10cSrcweir 	sal_uInt32											mnUsedEntries;
605cdf0e10cSrcweir 
606cdf0e10cSrcweir public:
TextureCoordinate2D(sal_uInt32 nCount)607cdf0e10cSrcweir 	explicit TextureCoordinate2D(sal_uInt32 nCount)
608cdf0e10cSrcweir 	:	maVector(nCount),
609cdf0e10cSrcweir 		mnUsedEntries(0L)
610cdf0e10cSrcweir 	{
611cdf0e10cSrcweir 	}
612cdf0e10cSrcweir 
TextureCoordinate2D(const TextureCoordinate2D & rOriginal)613cdf0e10cSrcweir 	explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal)
614cdf0e10cSrcweir 	:	maVector(rOriginal.maVector),
615cdf0e10cSrcweir 		mnUsedEntries(rOriginal.mnUsedEntries)
616cdf0e10cSrcweir 	{
617cdf0e10cSrcweir 	}
618cdf0e10cSrcweir 
TextureCoordinate2D(const TextureCoordinate2D & rOriginal,sal_uInt32 nIndex,sal_uInt32 nCount)619cdf0e10cSrcweir 	TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
620cdf0e10cSrcweir 	:	maVector(),
621cdf0e10cSrcweir 		mnUsedEntries(0L)
622cdf0e10cSrcweir 	{
623cdf0e10cSrcweir 		TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin());
624cdf0e10cSrcweir 		aStart += nIndex;
625cdf0e10cSrcweir 		TextureData2DVector::const_iterator aEnd(aStart);
626cdf0e10cSrcweir 		aEnd += nCount;
627cdf0e10cSrcweir 		maVector.reserve(nCount);
628cdf0e10cSrcweir 
629cdf0e10cSrcweir 		for(; aStart != aEnd; aStart++)
630cdf0e10cSrcweir 		{
631cdf0e10cSrcweir 			if(!aStart->equalZero())
632cdf0e10cSrcweir 				mnUsedEntries++;
633cdf0e10cSrcweir 
634cdf0e10cSrcweir 			maVector.push_back(*aStart);
635cdf0e10cSrcweir 		}
636cdf0e10cSrcweir 	}
637cdf0e10cSrcweir 
~TextureCoordinate2D()638cdf0e10cSrcweir 	~TextureCoordinate2D()
639cdf0e10cSrcweir 	{
640cdf0e10cSrcweir 	}
641cdf0e10cSrcweir 
count() const642cdf0e10cSrcweir 	sal_uInt32 count() const
643cdf0e10cSrcweir 	{
644cdf0e10cSrcweir 		return maVector.size();
645cdf0e10cSrcweir 	}
646cdf0e10cSrcweir 
operator ==(const TextureCoordinate2D & rCandidate) const647cdf0e10cSrcweir 	bool operator==(const TextureCoordinate2D& rCandidate) const
648cdf0e10cSrcweir 	{
649cdf0e10cSrcweir 		return (maVector == rCandidate.maVector);
650cdf0e10cSrcweir 	}
651cdf0e10cSrcweir 
isUsed() const652cdf0e10cSrcweir 	bool isUsed() const
653cdf0e10cSrcweir 	{
654cdf0e10cSrcweir 		return (0L != mnUsedEntries);
655cdf0e10cSrcweir 	}
656cdf0e10cSrcweir 
getTextureCoordinate(sal_uInt32 nIndex) const657cdf0e10cSrcweir 	const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
658cdf0e10cSrcweir 	{
659cdf0e10cSrcweir 		return maVector[nIndex];
660cdf0e10cSrcweir 	}
661cdf0e10cSrcweir 
setTextureCoordinate(sal_uInt32 nIndex,const::basegfx::B2DPoint & rValue)662cdf0e10cSrcweir 	void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
663cdf0e10cSrcweir 	{
664cdf0e10cSrcweir 		bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
665cdf0e10cSrcweir 		bool bIsUsed(!rValue.equalZero());
666cdf0e10cSrcweir 
667cdf0e10cSrcweir 		if(bWasUsed)
668cdf0e10cSrcweir 		{
669cdf0e10cSrcweir 			if(bIsUsed)
670cdf0e10cSrcweir 			{
671cdf0e10cSrcweir 				maVector[nIndex] = rValue;
672cdf0e10cSrcweir 			}
673cdf0e10cSrcweir 			else
674cdf0e10cSrcweir 			{
675cdf0e10cSrcweir 				maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint();
676cdf0e10cSrcweir 				mnUsedEntries--;
677cdf0e10cSrcweir 			}
678cdf0e10cSrcweir 		}
679cdf0e10cSrcweir 		else
680cdf0e10cSrcweir 		{
681cdf0e10cSrcweir 			if(bIsUsed)
682cdf0e10cSrcweir 			{
683cdf0e10cSrcweir 				maVector[nIndex] = rValue;
684cdf0e10cSrcweir 				mnUsedEntries++;
685cdf0e10cSrcweir 			}
686cdf0e10cSrcweir 		}
687cdf0e10cSrcweir 	}
688cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const::basegfx::B2DPoint & rValue,sal_uInt32 nCount)689cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount)
690cdf0e10cSrcweir 	{
691cdf0e10cSrcweir 		if(nCount)
692cdf0e10cSrcweir 		{
693cdf0e10cSrcweir 			// add nCount copies of rValue
694cdf0e10cSrcweir 			TextureData2DVector::iterator aIndex(maVector.begin());
695cdf0e10cSrcweir 			aIndex += nIndex;
696cdf0e10cSrcweir 			maVector.insert(aIndex, nCount, rValue);
697cdf0e10cSrcweir 
698cdf0e10cSrcweir 			if(!rValue.equalZero())
699cdf0e10cSrcweir 				mnUsedEntries += nCount;
700cdf0e10cSrcweir 		}
701cdf0e10cSrcweir 	}
702cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const TextureCoordinate2D & rSource)703cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource)
704cdf0e10cSrcweir 	{
705cdf0e10cSrcweir 		const sal_uInt32 nCount(rSource.maVector.size());
706cdf0e10cSrcweir 
707cdf0e10cSrcweir 		if(nCount)
708cdf0e10cSrcweir 		{
709cdf0e10cSrcweir 			// insert data
710cdf0e10cSrcweir 			TextureData2DVector::iterator aIndex(maVector.begin());
711cdf0e10cSrcweir 			aIndex += nIndex;
712cdf0e10cSrcweir 			TextureData2DVector::const_iterator aStart(rSource.maVector.begin());
713cdf0e10cSrcweir 			TextureData2DVector::const_iterator aEnd(rSource.maVector.end());
714cdf0e10cSrcweir 			maVector.insert(aIndex, aStart, aEnd);
715cdf0e10cSrcweir 
716cdf0e10cSrcweir 			for(; aStart != aEnd; aStart++)
717cdf0e10cSrcweir 			{
718cdf0e10cSrcweir 				if(!aStart->equalZero())
719cdf0e10cSrcweir 					mnUsedEntries++;
720cdf0e10cSrcweir 			}
721cdf0e10cSrcweir 		}
722cdf0e10cSrcweir 	}
723cdf0e10cSrcweir 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)724cdf0e10cSrcweir 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
725cdf0e10cSrcweir 	{
726cdf0e10cSrcweir 		if(nCount)
727cdf0e10cSrcweir 		{
728cdf0e10cSrcweir 			const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
729cdf0e10cSrcweir 			const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
730cdf0e10cSrcweir 			TextureData2DVector::const_iterator aStart(aDeleteStart);
731cdf0e10cSrcweir 
732cdf0e10cSrcweir 			for(; mnUsedEntries && aStart != aDeleteEnd; aStart++)
733cdf0e10cSrcweir 			{
734cdf0e10cSrcweir 				if(!aStart->equalZero())
735cdf0e10cSrcweir 					mnUsedEntries--;
736cdf0e10cSrcweir 			}
737cdf0e10cSrcweir 
738cdf0e10cSrcweir 			// remove point data
739cdf0e10cSrcweir 			maVector.erase(aDeleteStart, aDeleteEnd);
740cdf0e10cSrcweir 		}
741cdf0e10cSrcweir 	}
742cdf0e10cSrcweir 
flip()743cdf0e10cSrcweir 	void flip()
744cdf0e10cSrcweir 	{
745cdf0e10cSrcweir 		if(maVector.size() > 1)
746cdf0e10cSrcweir 		{
747cdf0e10cSrcweir 			const sal_uInt32 nHalfSize(maVector.size() >> 1L);
748cdf0e10cSrcweir 			TextureData2DVector::iterator aStart(maVector.begin());
749cdf0e10cSrcweir 			TextureData2DVector::iterator aEnd(maVector.end() - 1L);
750cdf0e10cSrcweir 
751cdf0e10cSrcweir 			for(sal_uInt32 a(0); a < nHalfSize; a++)
752cdf0e10cSrcweir 			{
753cdf0e10cSrcweir 				::std::swap(*aStart, *aEnd);
754cdf0e10cSrcweir 				aStart++;
755cdf0e10cSrcweir 				aEnd--;
756cdf0e10cSrcweir 			}
757cdf0e10cSrcweir 		}
758cdf0e10cSrcweir 	}
759cdf0e10cSrcweir 
transform(const::basegfx::B2DHomMatrix & rMatrix)760cdf0e10cSrcweir 	void transform(const ::basegfx::B2DHomMatrix& rMatrix)
761cdf0e10cSrcweir 	{
762cdf0e10cSrcweir 		TextureData2DVector::iterator aStart(maVector.begin());
763cdf0e10cSrcweir 		TextureData2DVector::iterator aEnd(maVector.end());
764cdf0e10cSrcweir 
765cdf0e10cSrcweir 		for(; aStart != aEnd; aStart++)
766cdf0e10cSrcweir 		{
767cdf0e10cSrcweir 			(*aStart) *= rMatrix;
768cdf0e10cSrcweir 		}
769cdf0e10cSrcweir 	}
770cdf0e10cSrcweir };
771cdf0e10cSrcweir 
772cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
773cdf0e10cSrcweir 
774cdf0e10cSrcweir class ImplB3DPolygon
775cdf0e10cSrcweir {
776cdf0e10cSrcweir 	// The point vector. This vector exists always and defines the
777cdf0e10cSrcweir 	// count of members.
778cdf0e10cSrcweir 	CoordinateDataArray3D							maPoints;
779cdf0e10cSrcweir 
780cdf0e10cSrcweir 	// The BColor vector. This vectors are created on demand
781cdf0e10cSrcweir 	// and may be zero.
782cdf0e10cSrcweir 	BColorArray*									mpBColors;
783cdf0e10cSrcweir 
784cdf0e10cSrcweir 	// The Normals vector. This vectors are created on demand
785cdf0e10cSrcweir 	// and may be zero.
786cdf0e10cSrcweir 	NormalsArray3D*									mpNormals;
787cdf0e10cSrcweir 
788cdf0e10cSrcweir 	// The TextureCoordinates vector. This vectors are created on demand
789cdf0e10cSrcweir 	// and may be zero.
790cdf0e10cSrcweir 	TextureCoordinate2D*							mpTextureCoordiantes;
791cdf0e10cSrcweir 
792cdf0e10cSrcweir 	// The calculated plane normal. mbPlaneNormalValid says if it's valid.
793cdf0e10cSrcweir 	::basegfx::B3DVector							maPlaneNormal;
794cdf0e10cSrcweir 
795cdf0e10cSrcweir 	// bitfield
796cdf0e10cSrcweir 	// flag which decides if this polygon is opened or closed
797cdf0e10cSrcweir 	unsigned										mbIsClosed : 1;
798cdf0e10cSrcweir 
799cdf0e10cSrcweir 	// flag which says if maPlaneNormal is up-to-date
800cdf0e10cSrcweir 	unsigned										mbPlaneNormalValid : 1;
801cdf0e10cSrcweir 
802cdf0e10cSrcweir protected:
invalidatePlaneNormal()803cdf0e10cSrcweir 	void invalidatePlaneNormal()
804cdf0e10cSrcweir 	{
805cdf0e10cSrcweir 		if(mbPlaneNormalValid)
806cdf0e10cSrcweir 		{
807cdf0e10cSrcweir 			mbPlaneNormalValid = false;
808cdf0e10cSrcweir 		}
809cdf0e10cSrcweir 	}
810cdf0e10cSrcweir 
811cdf0e10cSrcweir public:
812cdf0e10cSrcweir 	// This constructor is only used from the static identity polygon, thus
813cdf0e10cSrcweir 	// the RefCount is set to 1 to never 'delete' this static incarnation.
ImplB3DPolygon()814cdf0e10cSrcweir 	ImplB3DPolygon()
815cdf0e10cSrcweir 	:	maPoints(0L),
816cdf0e10cSrcweir 		mpBColors(0L),
817cdf0e10cSrcweir 		mpNormals(0L),
818cdf0e10cSrcweir 		mpTextureCoordiantes(0L),
819cdf0e10cSrcweir 		maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
820cdf0e10cSrcweir 		mbIsClosed(false),
821cdf0e10cSrcweir 		mbPlaneNormalValid(true)
822cdf0e10cSrcweir 	{
823cdf0e10cSrcweir 		// complete initialization with defaults
824cdf0e10cSrcweir 	}
825cdf0e10cSrcweir 
ImplB3DPolygon(const ImplB3DPolygon & rToBeCopied)826cdf0e10cSrcweir 	ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied)
827cdf0e10cSrcweir 	:	maPoints(rToBeCopied.maPoints),
828cdf0e10cSrcweir 		mpBColors(0L),
829cdf0e10cSrcweir 		mpNormals(0L),
830cdf0e10cSrcweir 		mpTextureCoordiantes(0L),
831cdf0e10cSrcweir 		maPlaneNormal(rToBeCopied.maPlaneNormal),
832cdf0e10cSrcweir 		mbIsClosed(rToBeCopied.mbIsClosed),
833cdf0e10cSrcweir 		mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid)
834cdf0e10cSrcweir 	{
835cdf0e10cSrcweir 		// complete initialization using copy
836cdf0e10cSrcweir 		if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
837cdf0e10cSrcweir 		{
838cdf0e10cSrcweir 			mpBColors = new BColorArray(*rToBeCopied.mpBColors);
839cdf0e10cSrcweir 		}
840cdf0e10cSrcweir 
841cdf0e10cSrcweir 		if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
842cdf0e10cSrcweir 		{
843cdf0e10cSrcweir 			mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals);
844cdf0e10cSrcweir 		}
845cdf0e10cSrcweir 
846cdf0e10cSrcweir 		if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
847cdf0e10cSrcweir 		{
848cdf0e10cSrcweir 			mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes);
849cdf0e10cSrcweir 		}
850cdf0e10cSrcweir 	}
851cdf0e10cSrcweir 
ImplB3DPolygon(const ImplB3DPolygon & rToBeCopied,sal_uInt32 nIndex,sal_uInt32 nCount)852cdf0e10cSrcweir 	ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
853cdf0e10cSrcweir 	:	maPoints(rToBeCopied.maPoints, nIndex, nCount),
854cdf0e10cSrcweir 		mpBColors(0L),
855cdf0e10cSrcweir 		mpNormals(0L),
856cdf0e10cSrcweir 		mpTextureCoordiantes(0L),
857cdf0e10cSrcweir 		maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
858cdf0e10cSrcweir 		mbIsClosed(rToBeCopied.mbIsClosed),
859cdf0e10cSrcweir 		mbPlaneNormalValid(false)
860cdf0e10cSrcweir 	{
861cdf0e10cSrcweir 		// complete initialization using partly copy
862cdf0e10cSrcweir 		if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
863cdf0e10cSrcweir 		{
864cdf0e10cSrcweir 			mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount);
865cdf0e10cSrcweir 
866cdf0e10cSrcweir 			if(!mpBColors->isUsed())
867cdf0e10cSrcweir 			{
868cdf0e10cSrcweir 				delete mpBColors;
869cdf0e10cSrcweir 				mpBColors = 0L;
870cdf0e10cSrcweir 			}
871cdf0e10cSrcweir 		}
872cdf0e10cSrcweir 
873cdf0e10cSrcweir 		if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
874cdf0e10cSrcweir 		{
875cdf0e10cSrcweir 			mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount);
876cdf0e10cSrcweir 
877cdf0e10cSrcweir 			if(!mpNormals->isUsed())
878cdf0e10cSrcweir 			{
879cdf0e10cSrcweir 				delete mpNormals;
880cdf0e10cSrcweir 				mpNormals = 0L;
881cdf0e10cSrcweir 			}
882cdf0e10cSrcweir 		}
883cdf0e10cSrcweir 
884cdf0e10cSrcweir 		if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
885cdf0e10cSrcweir 		{
886cdf0e10cSrcweir 			mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount);
887cdf0e10cSrcweir 
888cdf0e10cSrcweir 			if(!mpTextureCoordiantes->isUsed())
889cdf0e10cSrcweir 			{
890cdf0e10cSrcweir 				delete mpTextureCoordiantes;
891cdf0e10cSrcweir 				mpTextureCoordiantes = 0L;
892cdf0e10cSrcweir 			}
893cdf0e10cSrcweir 		}
894cdf0e10cSrcweir 	}
895cdf0e10cSrcweir 
~ImplB3DPolygon()896cdf0e10cSrcweir 	~ImplB3DPolygon()
897cdf0e10cSrcweir 	{
898cdf0e10cSrcweir 		if(mpBColors)
899cdf0e10cSrcweir 		{
900cdf0e10cSrcweir 			delete mpBColors;
901cdf0e10cSrcweir 			mpBColors = 0L;
902cdf0e10cSrcweir 		}
903cdf0e10cSrcweir 
904cdf0e10cSrcweir 		if(mpNormals)
905cdf0e10cSrcweir 		{
906cdf0e10cSrcweir 			delete mpNormals;
907cdf0e10cSrcweir 			mpNormals = 0L;
908cdf0e10cSrcweir 		}
909cdf0e10cSrcweir 
910cdf0e10cSrcweir 		if(mpTextureCoordiantes)
911cdf0e10cSrcweir 		{
912cdf0e10cSrcweir 			delete mpTextureCoordiantes;
913cdf0e10cSrcweir 			mpTextureCoordiantes = 0L;
914cdf0e10cSrcweir 		}
915cdf0e10cSrcweir 	}
916cdf0e10cSrcweir 
count() const917cdf0e10cSrcweir 	sal_uInt32 count() const
918cdf0e10cSrcweir 	{
919cdf0e10cSrcweir 		return maPoints.count();
920cdf0e10cSrcweir 	}
921cdf0e10cSrcweir 
isClosed() const922cdf0e10cSrcweir 	bool isClosed() const
923cdf0e10cSrcweir 	{
924cdf0e10cSrcweir 		return mbIsClosed;
925cdf0e10cSrcweir 	}
926cdf0e10cSrcweir 
setClosed(bool bNew)927cdf0e10cSrcweir 	void setClosed(bool bNew)
928cdf0e10cSrcweir 	{
929cdf0e10cSrcweir 		if(bNew != (bool)mbIsClosed)
930cdf0e10cSrcweir 		{
931cdf0e10cSrcweir 			mbIsClosed = bNew;
932cdf0e10cSrcweir 		}
933cdf0e10cSrcweir 	}
934cdf0e10cSrcweir 
impBColorsAreEqual(const ImplB3DPolygon & rCandidate) const935cdf0e10cSrcweir 	inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const
936cdf0e10cSrcweir 	{
937cdf0e10cSrcweir 		bool bBColorsAreEqual(true);
938cdf0e10cSrcweir 
939cdf0e10cSrcweir 		if(mpBColors)
940cdf0e10cSrcweir 		{
941cdf0e10cSrcweir 			if(rCandidate.mpBColors)
942cdf0e10cSrcweir 			{
943cdf0e10cSrcweir 				bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors);
944cdf0e10cSrcweir 			}
945cdf0e10cSrcweir 			else
946cdf0e10cSrcweir 			{
947cdf0e10cSrcweir 				// candidate has no BColors, so it's assumed all unused.
948cdf0e10cSrcweir 				bBColorsAreEqual = !mpBColors->isUsed();
949cdf0e10cSrcweir 			}
950cdf0e10cSrcweir 		}
951cdf0e10cSrcweir 		else
952cdf0e10cSrcweir 		{
953cdf0e10cSrcweir 			if(rCandidate.mpBColors)
954cdf0e10cSrcweir 			{
955cdf0e10cSrcweir 				// we have no TextureCoordiantes, so it's assumed all unused.
956cdf0e10cSrcweir 				bBColorsAreEqual = !rCandidate.mpBColors->isUsed();
957cdf0e10cSrcweir 			}
958cdf0e10cSrcweir 		}
959cdf0e10cSrcweir 
960cdf0e10cSrcweir 		return bBColorsAreEqual;
961cdf0e10cSrcweir 	}
962cdf0e10cSrcweir 
impNormalsAreEqual(const ImplB3DPolygon & rCandidate) const963cdf0e10cSrcweir 	inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const
964cdf0e10cSrcweir 	{
965cdf0e10cSrcweir 		bool bNormalsAreEqual(true);
966cdf0e10cSrcweir 
967cdf0e10cSrcweir 		if(mpNormals)
968cdf0e10cSrcweir 		{
969cdf0e10cSrcweir 			if(rCandidate.mpNormals)
970cdf0e10cSrcweir 			{
971cdf0e10cSrcweir 				bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals);
972cdf0e10cSrcweir 			}
973cdf0e10cSrcweir 			else
974cdf0e10cSrcweir 			{
975cdf0e10cSrcweir 				// candidate has no normals, so it's assumed all unused.
976cdf0e10cSrcweir 				bNormalsAreEqual = !mpNormals->isUsed();
977cdf0e10cSrcweir 			}
978cdf0e10cSrcweir 		}
979cdf0e10cSrcweir 		else
980cdf0e10cSrcweir 		{
981cdf0e10cSrcweir 			if(rCandidate.mpNormals)
982cdf0e10cSrcweir 			{
983cdf0e10cSrcweir 				// we have no normals, so it's assumed all unused.
984cdf0e10cSrcweir 				bNormalsAreEqual = !rCandidate.mpNormals->isUsed();
985cdf0e10cSrcweir 			}
986cdf0e10cSrcweir 		}
987cdf0e10cSrcweir 
988cdf0e10cSrcweir 		return bNormalsAreEqual;
989cdf0e10cSrcweir 	}
990cdf0e10cSrcweir 
impTextureCoordinatesAreEqual(const ImplB3DPolygon & rCandidate) const991cdf0e10cSrcweir 	inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const
992cdf0e10cSrcweir 	{
993cdf0e10cSrcweir 		bool bTextureCoordinatesAreEqual(true);
994cdf0e10cSrcweir 
995cdf0e10cSrcweir 		if(mpTextureCoordiantes)
996cdf0e10cSrcweir 		{
997cdf0e10cSrcweir 			if(rCandidate.mpTextureCoordiantes)
998cdf0e10cSrcweir 			{
999cdf0e10cSrcweir 				bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes);
1000cdf0e10cSrcweir 			}
1001cdf0e10cSrcweir 			else
1002cdf0e10cSrcweir 			{
1003cdf0e10cSrcweir 				// candidate has no TextureCoordinates, so it's assumed all unused.
1004cdf0e10cSrcweir 				bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed();
1005cdf0e10cSrcweir 			}
1006cdf0e10cSrcweir 		}
1007cdf0e10cSrcweir 		else
1008cdf0e10cSrcweir 		{
1009cdf0e10cSrcweir 			if(rCandidate.mpTextureCoordiantes)
1010cdf0e10cSrcweir 			{
1011cdf0e10cSrcweir 				// we have no TextureCoordiantes, so it's assumed all unused.
1012cdf0e10cSrcweir 				bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed();
1013cdf0e10cSrcweir 			}
1014cdf0e10cSrcweir 		}
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir 		return bTextureCoordinatesAreEqual;
1017cdf0e10cSrcweir 	}
1018cdf0e10cSrcweir 
operator ==(const ImplB3DPolygon & rCandidate) const1019cdf0e10cSrcweir 	bool operator==(const ImplB3DPolygon& rCandidate) const
1020cdf0e10cSrcweir 	{
1021cdf0e10cSrcweir 		if(mbIsClosed == rCandidate.mbIsClosed)
1022cdf0e10cSrcweir 		{
1023cdf0e10cSrcweir 			if(maPoints == rCandidate.maPoints)
1024cdf0e10cSrcweir 			{
1025cdf0e10cSrcweir 				if(impBColorsAreEqual(rCandidate))
1026cdf0e10cSrcweir 				{
1027cdf0e10cSrcweir 					if(impNormalsAreEqual(rCandidate))
1028cdf0e10cSrcweir 					{
1029cdf0e10cSrcweir 						if(impTextureCoordinatesAreEqual(rCandidate))
1030cdf0e10cSrcweir 						{
1031cdf0e10cSrcweir 							return true;
1032cdf0e10cSrcweir 						}
1033cdf0e10cSrcweir 					}
1034cdf0e10cSrcweir 				}
1035cdf0e10cSrcweir 			}
1036cdf0e10cSrcweir 		}
1037cdf0e10cSrcweir 
1038cdf0e10cSrcweir 		return false;
1039cdf0e10cSrcweir 	}
1040cdf0e10cSrcweir 
getPoint(sal_uInt32 nIndex) const1041cdf0e10cSrcweir 	const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const
1042cdf0e10cSrcweir 	{
1043cdf0e10cSrcweir 		return maPoints.getCoordinate(nIndex);
1044cdf0e10cSrcweir 	}
1045cdf0e10cSrcweir 
setPoint(sal_uInt32 nIndex,const::basegfx::B3DPoint & rValue)1046cdf0e10cSrcweir 	void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue)
1047cdf0e10cSrcweir 	{
1048cdf0e10cSrcweir 		maPoints.setCoordinate(nIndex, rValue);
1049cdf0e10cSrcweir 		invalidatePlaneNormal();
1050cdf0e10cSrcweir 	}
1051cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const::basegfx::B3DPoint & rPoint,sal_uInt32 nCount)1052cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1053cdf0e10cSrcweir 	{
1054cdf0e10cSrcweir 		if(nCount)
1055cdf0e10cSrcweir 		{
1056cdf0e10cSrcweir 			CoordinateData3D aCoordinate(rPoint);
1057cdf0e10cSrcweir 			maPoints.insert(nIndex, aCoordinate, nCount);
1058cdf0e10cSrcweir 			invalidatePlaneNormal();
1059cdf0e10cSrcweir 
1060cdf0e10cSrcweir 			if(mpBColors)
1061cdf0e10cSrcweir 			{
1062cdf0e10cSrcweir 				mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1063cdf0e10cSrcweir 			}
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir 			if(mpNormals)
1066cdf0e10cSrcweir 			{
1067cdf0e10cSrcweir 				mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1068cdf0e10cSrcweir 			}
1069cdf0e10cSrcweir 
1070cdf0e10cSrcweir 			if(mpTextureCoordiantes)
1071cdf0e10cSrcweir 			{
1072cdf0e10cSrcweir 				mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1073cdf0e10cSrcweir 			}
1074cdf0e10cSrcweir 		}
1075cdf0e10cSrcweir 	}
1076cdf0e10cSrcweir 
getBColor(sal_uInt32 nIndex) const1077cdf0e10cSrcweir 	const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
1078cdf0e10cSrcweir 	{
1079cdf0e10cSrcweir 		if(mpBColors)
1080cdf0e10cSrcweir 		{
1081cdf0e10cSrcweir 			return mpBColors->getBColor(nIndex);
1082cdf0e10cSrcweir 		}
1083cdf0e10cSrcweir 		else
1084cdf0e10cSrcweir 		{
1085cdf0e10cSrcweir 			return ::basegfx::BColor::getEmptyBColor();
1086cdf0e10cSrcweir 		}
1087cdf0e10cSrcweir 	}
1088cdf0e10cSrcweir 
setBColor(sal_uInt32 nIndex,const::basegfx::BColor & rValue)1089cdf0e10cSrcweir 	void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
1090cdf0e10cSrcweir 	{
1091cdf0e10cSrcweir 		if(!mpBColors)
1092cdf0e10cSrcweir 		{
1093cdf0e10cSrcweir 			if(!rValue.equalZero())
1094cdf0e10cSrcweir 			{
1095cdf0e10cSrcweir 				mpBColors = new BColorArray(maPoints.count());
1096cdf0e10cSrcweir 				mpBColors->setBColor(nIndex, rValue);
1097cdf0e10cSrcweir 			}
1098cdf0e10cSrcweir 		}
1099cdf0e10cSrcweir 		else
1100cdf0e10cSrcweir 		{
1101cdf0e10cSrcweir 			mpBColors->setBColor(nIndex, rValue);
1102cdf0e10cSrcweir 
1103cdf0e10cSrcweir 			if(!mpBColors->isUsed())
1104cdf0e10cSrcweir 			{
1105cdf0e10cSrcweir 				delete mpBColors;
1106cdf0e10cSrcweir 				mpBColors = 0L;
1107cdf0e10cSrcweir 			}
1108cdf0e10cSrcweir 		}
1109cdf0e10cSrcweir 	}
1110cdf0e10cSrcweir 
areBColorsUsed() const1111cdf0e10cSrcweir 	bool areBColorsUsed() const
1112cdf0e10cSrcweir 	{
1113cdf0e10cSrcweir 		return (mpBColors && mpBColors->isUsed());
1114cdf0e10cSrcweir 	}
1115cdf0e10cSrcweir 
clearBColors()1116cdf0e10cSrcweir 	void clearBColors()
1117cdf0e10cSrcweir 	{
1118cdf0e10cSrcweir 		if(mpBColors)
1119cdf0e10cSrcweir 		{
1120cdf0e10cSrcweir 			delete mpBColors;
1121cdf0e10cSrcweir 			mpBColors = 0L;
1122cdf0e10cSrcweir 		}
1123cdf0e10cSrcweir 	}
1124cdf0e10cSrcweir 
getNormal() const1125cdf0e10cSrcweir 	const ::basegfx::B3DVector& getNormal() const
1126cdf0e10cSrcweir 	{
1127cdf0e10cSrcweir 		if(!mbPlaneNormalValid)
1128cdf0e10cSrcweir 		{
1129cdf0e10cSrcweir 			const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal();
1130cdf0e10cSrcweir 			const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true;
1131cdf0e10cSrcweir 		}
1132cdf0e10cSrcweir 
1133cdf0e10cSrcweir 		return maPlaneNormal;
1134cdf0e10cSrcweir 	}
1135cdf0e10cSrcweir 
getNormal(sal_uInt32 nIndex) const1136cdf0e10cSrcweir 	const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
1137cdf0e10cSrcweir 	{
1138cdf0e10cSrcweir 		if(mpNormals)
1139cdf0e10cSrcweir 		{
1140cdf0e10cSrcweir 			return mpNormals->getNormal(nIndex);
1141cdf0e10cSrcweir 		}
1142cdf0e10cSrcweir 		else
1143cdf0e10cSrcweir 		{
1144cdf0e10cSrcweir 			return ::basegfx::B3DVector::getEmptyVector();
1145cdf0e10cSrcweir 		}
1146cdf0e10cSrcweir 	}
1147cdf0e10cSrcweir 
setNormal(sal_uInt32 nIndex,const::basegfx::B3DVector & rValue)1148cdf0e10cSrcweir 	void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
1149cdf0e10cSrcweir 	{
1150cdf0e10cSrcweir 		if(!mpNormals)
1151cdf0e10cSrcweir 		{
1152cdf0e10cSrcweir 			if(!rValue.equalZero())
1153cdf0e10cSrcweir 			{
1154cdf0e10cSrcweir 				mpNormals = new NormalsArray3D(maPoints.count());
1155cdf0e10cSrcweir 				mpNormals->setNormal(nIndex, rValue);
1156cdf0e10cSrcweir 			}
1157cdf0e10cSrcweir 		}
1158cdf0e10cSrcweir 		else
1159cdf0e10cSrcweir 		{
1160cdf0e10cSrcweir 			mpNormals->setNormal(nIndex, rValue);
1161cdf0e10cSrcweir 
1162cdf0e10cSrcweir 			if(!mpNormals->isUsed())
1163cdf0e10cSrcweir 			{
1164cdf0e10cSrcweir 				delete mpNormals;
1165cdf0e10cSrcweir 				mpNormals = 0L;
1166cdf0e10cSrcweir 			}
1167cdf0e10cSrcweir 		}
1168cdf0e10cSrcweir 	}
1169cdf0e10cSrcweir 
transformNormals(const::basegfx::B3DHomMatrix & rMatrix)1170cdf0e10cSrcweir 	void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
1171cdf0e10cSrcweir 	{
1172cdf0e10cSrcweir 		if(mpNormals)
1173cdf0e10cSrcweir 		{
1174cdf0e10cSrcweir 			mpNormals->transform(rMatrix);
1175cdf0e10cSrcweir 		}
1176cdf0e10cSrcweir 	}
1177cdf0e10cSrcweir 
areNormalsUsed() const1178cdf0e10cSrcweir 	bool areNormalsUsed() const
1179cdf0e10cSrcweir 	{
1180cdf0e10cSrcweir 		return (mpNormals && mpNormals->isUsed());
1181cdf0e10cSrcweir 	}
1182cdf0e10cSrcweir 
clearNormals()1183cdf0e10cSrcweir 	void clearNormals()
1184cdf0e10cSrcweir 	{
1185cdf0e10cSrcweir 		if(mpNormals)
1186cdf0e10cSrcweir 		{
1187cdf0e10cSrcweir 			delete mpNormals;
1188cdf0e10cSrcweir 			mpNormals = 0L;
1189cdf0e10cSrcweir 		}
1190cdf0e10cSrcweir 	}
1191cdf0e10cSrcweir 
getTextureCoordinate(sal_uInt32 nIndex) const1192cdf0e10cSrcweir 	const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
1193cdf0e10cSrcweir 	{
1194cdf0e10cSrcweir 		if(mpTextureCoordiantes)
1195cdf0e10cSrcweir 		{
1196cdf0e10cSrcweir 			return mpTextureCoordiantes->getTextureCoordinate(nIndex);
1197cdf0e10cSrcweir 		}
1198cdf0e10cSrcweir 		else
1199cdf0e10cSrcweir 		{
1200cdf0e10cSrcweir 			return ::basegfx::B2DPoint::getEmptyPoint();
1201cdf0e10cSrcweir 		}
1202cdf0e10cSrcweir 	}
1203cdf0e10cSrcweir 
setTextureCoordinate(sal_uInt32 nIndex,const::basegfx::B2DPoint & rValue)1204cdf0e10cSrcweir 	void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
1205cdf0e10cSrcweir 	{
1206cdf0e10cSrcweir 		if(!mpTextureCoordiantes)
1207cdf0e10cSrcweir 		{
1208cdf0e10cSrcweir 			if(!rValue.equalZero())
1209cdf0e10cSrcweir 			{
1210cdf0e10cSrcweir 				mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1211cdf0e10cSrcweir 				mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1212cdf0e10cSrcweir 			}
1213cdf0e10cSrcweir 		}
1214cdf0e10cSrcweir 		else
1215cdf0e10cSrcweir 		{
1216cdf0e10cSrcweir 			mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1217cdf0e10cSrcweir 
1218cdf0e10cSrcweir 			if(!mpTextureCoordiantes->isUsed())
1219cdf0e10cSrcweir 			{
1220cdf0e10cSrcweir 				delete mpTextureCoordiantes;
1221cdf0e10cSrcweir 				mpTextureCoordiantes = 0L;
1222cdf0e10cSrcweir 			}
1223cdf0e10cSrcweir 		}
1224cdf0e10cSrcweir 	}
1225cdf0e10cSrcweir 
areTextureCoordinatesUsed() const1226cdf0e10cSrcweir 	bool areTextureCoordinatesUsed() const
1227cdf0e10cSrcweir 	{
1228cdf0e10cSrcweir 		return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed());
1229cdf0e10cSrcweir 	}
1230cdf0e10cSrcweir 
clearTextureCoordinates()1231cdf0e10cSrcweir 	void clearTextureCoordinates()
1232cdf0e10cSrcweir 	{
1233cdf0e10cSrcweir 		if(mpTextureCoordiantes)
1234cdf0e10cSrcweir 		{
1235cdf0e10cSrcweir 			delete mpTextureCoordiantes;
1236cdf0e10cSrcweir 			mpTextureCoordiantes = 0L;
1237cdf0e10cSrcweir 		}
1238cdf0e10cSrcweir 	}
1239cdf0e10cSrcweir 
transformTextureCoordinates(const::basegfx::B2DHomMatrix & rMatrix)1240cdf0e10cSrcweir 	void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
1241cdf0e10cSrcweir 	{
1242cdf0e10cSrcweir 		if(mpTextureCoordiantes)
1243cdf0e10cSrcweir 		{
1244cdf0e10cSrcweir 			mpTextureCoordiantes->transform(rMatrix);
1245cdf0e10cSrcweir 		}
1246cdf0e10cSrcweir 	}
1247cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const ImplB3DPolygon & rSource)1248cdf0e10cSrcweir 	void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource)
1249cdf0e10cSrcweir 	{
1250cdf0e10cSrcweir 		const sal_uInt32 nCount(rSource.maPoints.count());
1251cdf0e10cSrcweir 
1252cdf0e10cSrcweir 		if(nCount)
1253cdf0e10cSrcweir 		{
1254cdf0e10cSrcweir 			maPoints.insert(nIndex, rSource.maPoints);
1255cdf0e10cSrcweir 			invalidatePlaneNormal();
1256cdf0e10cSrcweir 
1257cdf0e10cSrcweir 			if(rSource.mpBColors && rSource.mpBColors->isUsed())
1258cdf0e10cSrcweir 			{
1259cdf0e10cSrcweir 				if(!mpBColors)
1260cdf0e10cSrcweir 				{
1261cdf0e10cSrcweir 					mpBColors = new BColorArray(maPoints.count());
1262cdf0e10cSrcweir 				}
1263cdf0e10cSrcweir 
1264cdf0e10cSrcweir 				mpBColors->insert(nIndex, *rSource.mpBColors);
1265cdf0e10cSrcweir 			}
1266cdf0e10cSrcweir 			else
1267cdf0e10cSrcweir 			{
1268cdf0e10cSrcweir 				if(mpBColors)
1269cdf0e10cSrcweir 				{
1270cdf0e10cSrcweir 					mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1271cdf0e10cSrcweir 				}
1272cdf0e10cSrcweir 			}
1273cdf0e10cSrcweir 
1274cdf0e10cSrcweir 			if(rSource.mpNormals && rSource.mpNormals->isUsed())
1275cdf0e10cSrcweir 			{
1276cdf0e10cSrcweir 				if(!mpNormals)
1277cdf0e10cSrcweir 				{
1278cdf0e10cSrcweir 					mpNormals = new NormalsArray3D(maPoints.count());
1279cdf0e10cSrcweir 				}
1280cdf0e10cSrcweir 
1281cdf0e10cSrcweir 				mpNormals->insert(nIndex, *rSource.mpNormals);
1282cdf0e10cSrcweir 			}
1283cdf0e10cSrcweir 			else
1284cdf0e10cSrcweir 			{
1285cdf0e10cSrcweir 				if(mpNormals)
1286cdf0e10cSrcweir 				{
1287cdf0e10cSrcweir 					mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1288cdf0e10cSrcweir 				}
1289cdf0e10cSrcweir 			}
1290cdf0e10cSrcweir 
1291cdf0e10cSrcweir 			if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed())
1292cdf0e10cSrcweir 			{
1293cdf0e10cSrcweir 				if(!mpTextureCoordiantes)
1294cdf0e10cSrcweir 				{
1295cdf0e10cSrcweir 					mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1296cdf0e10cSrcweir 				}
1297cdf0e10cSrcweir 
1298cdf0e10cSrcweir 				mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes);
1299cdf0e10cSrcweir 			}
1300cdf0e10cSrcweir 			else
1301cdf0e10cSrcweir 			{
1302cdf0e10cSrcweir 				if(mpTextureCoordiantes)
1303cdf0e10cSrcweir 				{
1304cdf0e10cSrcweir 					mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1305cdf0e10cSrcweir 				}
1306cdf0e10cSrcweir 			}
1307cdf0e10cSrcweir 		}
1308cdf0e10cSrcweir 	}
1309cdf0e10cSrcweir 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)1310cdf0e10cSrcweir 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1311cdf0e10cSrcweir 	{
1312cdf0e10cSrcweir 		if(nCount)
1313cdf0e10cSrcweir 		{
1314cdf0e10cSrcweir 			maPoints.remove(nIndex, nCount);
1315cdf0e10cSrcweir 			invalidatePlaneNormal();
1316cdf0e10cSrcweir 
1317cdf0e10cSrcweir 			if(mpBColors)
1318cdf0e10cSrcweir 			{
1319cdf0e10cSrcweir 				mpBColors->remove(nIndex, nCount);
1320cdf0e10cSrcweir 
1321cdf0e10cSrcweir 				if(!mpBColors->isUsed())
1322cdf0e10cSrcweir 				{
1323cdf0e10cSrcweir 					delete mpBColors;
1324cdf0e10cSrcweir 					mpBColors = 0L;
1325cdf0e10cSrcweir 				}
1326cdf0e10cSrcweir 			}
1327cdf0e10cSrcweir 
1328cdf0e10cSrcweir 			if(mpNormals)
1329cdf0e10cSrcweir 			{
1330cdf0e10cSrcweir 				mpNormals->remove(nIndex, nCount);
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir 				if(!mpNormals->isUsed())
1333cdf0e10cSrcweir 				{
1334cdf0e10cSrcweir 					delete mpNormals;
1335cdf0e10cSrcweir 					mpNormals = 0L;
1336cdf0e10cSrcweir 				}
1337cdf0e10cSrcweir 			}
1338cdf0e10cSrcweir 
1339cdf0e10cSrcweir 			if(mpTextureCoordiantes)
1340cdf0e10cSrcweir 			{
1341cdf0e10cSrcweir 				mpTextureCoordiantes->remove(nIndex, nCount);
1342cdf0e10cSrcweir 
1343cdf0e10cSrcweir 				if(!mpTextureCoordiantes->isUsed())
1344cdf0e10cSrcweir 				{
1345cdf0e10cSrcweir 					delete mpTextureCoordiantes;
1346cdf0e10cSrcweir 					mpTextureCoordiantes = 0L;
1347cdf0e10cSrcweir 				}
1348cdf0e10cSrcweir 			}
1349cdf0e10cSrcweir 		}
1350cdf0e10cSrcweir 	}
1351cdf0e10cSrcweir 
flip()1352cdf0e10cSrcweir 	void flip()
1353cdf0e10cSrcweir 	{
1354cdf0e10cSrcweir 		if(maPoints.count() > 1)
1355cdf0e10cSrcweir 		{
1356cdf0e10cSrcweir 			maPoints.flip();
1357cdf0e10cSrcweir 
1358cdf0e10cSrcweir 			if(mbPlaneNormalValid)
1359cdf0e10cSrcweir 			{
1360cdf0e10cSrcweir 				// mirror plane normal
1361cdf0e10cSrcweir 				maPlaneNormal = -maPlaneNormal;
1362cdf0e10cSrcweir 			}
1363cdf0e10cSrcweir 
1364cdf0e10cSrcweir 			if(mpBColors)
1365cdf0e10cSrcweir 			{
1366cdf0e10cSrcweir 				mpBColors->flip();
1367cdf0e10cSrcweir 			}
1368cdf0e10cSrcweir 
1369cdf0e10cSrcweir 			if(mpNormals)
1370cdf0e10cSrcweir 			{
1371cdf0e10cSrcweir 				mpNormals->flip();
1372cdf0e10cSrcweir 			}
1373cdf0e10cSrcweir 
1374cdf0e10cSrcweir 			if(mpTextureCoordiantes)
1375cdf0e10cSrcweir 			{
1376cdf0e10cSrcweir 				mpTextureCoordiantes->flip();
1377cdf0e10cSrcweir 			}
1378cdf0e10cSrcweir 		}
1379cdf0e10cSrcweir 	}
1380cdf0e10cSrcweir 
hasDoublePoints() const1381cdf0e10cSrcweir 	bool hasDoublePoints() const
1382cdf0e10cSrcweir 	{
1383cdf0e10cSrcweir 		if(mbIsClosed)
1384cdf0e10cSrcweir 		{
1385cdf0e10cSrcweir 			// check for same start and end point
1386cdf0e10cSrcweir 			const sal_uInt32 nIndex(maPoints.count() - 1L);
1387cdf0e10cSrcweir 
1388cdf0e10cSrcweir 			if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex))
1389cdf0e10cSrcweir 			{
1390cdf0e10cSrcweir 				const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)));
1391cdf0e10cSrcweir 
1392cdf0e10cSrcweir 				if(bBColorEqual)
1393cdf0e10cSrcweir 				{
1394cdf0e10cSrcweir 					const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)));
1395cdf0e10cSrcweir 
1396cdf0e10cSrcweir 					if(bNormalsEqual)
1397cdf0e10cSrcweir 					{
1398cdf0e10cSrcweir 						const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)));
1399cdf0e10cSrcweir 
1400cdf0e10cSrcweir 						if(bTextureCoordinatesEqual)
1401cdf0e10cSrcweir 						{
1402cdf0e10cSrcweir 							return true;
1403cdf0e10cSrcweir 						}
1404cdf0e10cSrcweir 					}
1405cdf0e10cSrcweir 				}
1406cdf0e10cSrcweir 			}
1407cdf0e10cSrcweir 		}
1408cdf0e10cSrcweir 
1409cdf0e10cSrcweir 		// test for range
1410cdf0e10cSrcweir 		for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++)
1411cdf0e10cSrcweir 		{
1412cdf0e10cSrcweir 			if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L))
1413cdf0e10cSrcweir 			{
1414cdf0e10cSrcweir 				const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L)));
1415cdf0e10cSrcweir 
1416cdf0e10cSrcweir 				if(bBColorEqual)
1417cdf0e10cSrcweir 				{
1418cdf0e10cSrcweir 					const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L)));
1419cdf0e10cSrcweir 
1420cdf0e10cSrcweir 					if(bNormalsEqual)
1421cdf0e10cSrcweir 					{
1422cdf0e10cSrcweir 						const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L)));
1423cdf0e10cSrcweir 
1424cdf0e10cSrcweir 						if(bTextureCoordinatesEqual)
1425cdf0e10cSrcweir 						{
1426cdf0e10cSrcweir 							return true;
1427cdf0e10cSrcweir 						}
1428cdf0e10cSrcweir 					}
1429cdf0e10cSrcweir 				}
1430cdf0e10cSrcweir 			}
1431cdf0e10cSrcweir 		}
1432cdf0e10cSrcweir 
1433cdf0e10cSrcweir 		return false;
1434cdf0e10cSrcweir 	}
1435cdf0e10cSrcweir 
removeDoublePointsAtBeginEnd()1436cdf0e10cSrcweir 	void removeDoublePointsAtBeginEnd()
1437cdf0e10cSrcweir 	{
1438cdf0e10cSrcweir 		// Only remove DoublePoints at Begin and End when poly is closed
1439cdf0e10cSrcweir 		if(mbIsClosed)
1440cdf0e10cSrcweir 		{
1441cdf0e10cSrcweir 			bool bRemove;
1442cdf0e10cSrcweir 
1443cdf0e10cSrcweir 			do
1444cdf0e10cSrcweir 			{
1445cdf0e10cSrcweir 				bRemove = false;
1446cdf0e10cSrcweir 
1447cdf0e10cSrcweir 				if(maPoints.count() > 1L)
1448cdf0e10cSrcweir 				{
1449cdf0e10cSrcweir 					const sal_uInt32 nIndex(maPoints.count() - 1L);
1450cdf0e10cSrcweir 					bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex));
1451cdf0e10cSrcweir 
1452cdf0e10cSrcweir 					if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)))
1453cdf0e10cSrcweir 					{
1454cdf0e10cSrcweir 						bRemove = false;
1455cdf0e10cSrcweir 					}
1456cdf0e10cSrcweir 
1457cdf0e10cSrcweir 					if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)))
1458cdf0e10cSrcweir 					{
1459cdf0e10cSrcweir 						bRemove = false;
1460cdf0e10cSrcweir 					}
1461cdf0e10cSrcweir 
1462cdf0e10cSrcweir 					if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)))
1463cdf0e10cSrcweir 					{
1464cdf0e10cSrcweir 						bRemove = false;
1465cdf0e10cSrcweir 					}
1466cdf0e10cSrcweir 				}
1467cdf0e10cSrcweir 
1468cdf0e10cSrcweir 				if(bRemove)
1469cdf0e10cSrcweir 				{
1470cdf0e10cSrcweir 					const sal_uInt32 nIndex(maPoints.count() - 1L);
1471cdf0e10cSrcweir 					remove(nIndex, 1L);
1472cdf0e10cSrcweir 				}
1473cdf0e10cSrcweir 			} while(bRemove);
1474cdf0e10cSrcweir 		}
1475cdf0e10cSrcweir 	}
1476cdf0e10cSrcweir 
removeDoublePointsWholeTrack()1477cdf0e10cSrcweir 	void removeDoublePointsWholeTrack()
1478cdf0e10cSrcweir 	{
1479cdf0e10cSrcweir 		sal_uInt32 nIndex(0L);
1480cdf0e10cSrcweir 
1481cdf0e10cSrcweir 		// test as long as there are at least two points and as long as the index
1482cdf0e10cSrcweir 		// is smaller or equal second last point
1483cdf0e10cSrcweir 		while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L))
1484cdf0e10cSrcweir 		{
1485cdf0e10cSrcweir 			const sal_uInt32 nNextIndex(nIndex + 1L);
1486cdf0e10cSrcweir 			bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex));
1487cdf0e10cSrcweir 
1488cdf0e10cSrcweir 			if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex)))
1489cdf0e10cSrcweir 			{
1490cdf0e10cSrcweir 				bRemove = false;
1491cdf0e10cSrcweir 			}
1492cdf0e10cSrcweir 
1493cdf0e10cSrcweir 			if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex)))
1494cdf0e10cSrcweir 			{
1495cdf0e10cSrcweir 				bRemove = false;
1496cdf0e10cSrcweir 			}
1497cdf0e10cSrcweir 
1498cdf0e10cSrcweir 			if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex)))
1499cdf0e10cSrcweir 			{
1500cdf0e10cSrcweir 				bRemove = false;
1501cdf0e10cSrcweir 			}
1502cdf0e10cSrcweir 
1503cdf0e10cSrcweir 			if(bRemove)
1504cdf0e10cSrcweir 			{
1505cdf0e10cSrcweir 				// if next is same as index and the control vectors are unused, delete index
1506cdf0e10cSrcweir 				remove(nIndex, 1L);
1507cdf0e10cSrcweir 			}
1508cdf0e10cSrcweir 			else
1509cdf0e10cSrcweir 			{
1510cdf0e10cSrcweir 				// if different, step forward
1511cdf0e10cSrcweir 				nIndex++;
1512cdf0e10cSrcweir 			}
1513cdf0e10cSrcweir 		}
1514cdf0e10cSrcweir 	}
1515cdf0e10cSrcweir 
transform(const::basegfx::B3DHomMatrix & rMatrix)1516cdf0e10cSrcweir 	void transform(const ::basegfx::B3DHomMatrix& rMatrix)
1517cdf0e10cSrcweir 	{
1518cdf0e10cSrcweir 		maPoints.transform(rMatrix);
1519cdf0e10cSrcweir 
1520cdf0e10cSrcweir 		// Here, it seems to be possible to transform a valid plane normal and to avoid
1521cdf0e10cSrcweir 		// invalidation, but it's not true. If the transformation contains shears or e.g.
1522cdf0e10cSrcweir 		// perspective projection, the orthogonality to the transformed plane will not
1523cdf0e10cSrcweir 		// be preserved. It may be possible to test that at the matrix to not invalidate in
1524cdf0e10cSrcweir 		// all cases or to extract a matrix which does not 'shear' the vector which is
1525cdf0e10cSrcweir 		// a normal in this case. As long as this is not sure, i will just invalidate.
1526cdf0e10cSrcweir 		invalidatePlaneNormal();
1527cdf0e10cSrcweir 	}
1528cdf0e10cSrcweir };
1529cdf0e10cSrcweir 
1530cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1531cdf0e10cSrcweir 
1532cdf0e10cSrcweir namespace basegfx
1533cdf0e10cSrcweir {
1534cdf0e10cSrcweir     namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType,
1535cdf0e10cSrcweir                                                             DefaultPolygon > {}; }
1536cdf0e10cSrcweir 
B3DPolygon()1537cdf0e10cSrcweir 	B3DPolygon::B3DPolygon() :
1538cdf0e10cSrcweir         mpPolygon(DefaultPolygon::get())
1539cdf0e10cSrcweir 	{
1540cdf0e10cSrcweir 	}
1541cdf0e10cSrcweir 
B3DPolygon(const B3DPolygon & rPolygon)1542cdf0e10cSrcweir 	B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) :
1543cdf0e10cSrcweir         mpPolygon(rPolygon.mpPolygon)
1544cdf0e10cSrcweir 	{
1545cdf0e10cSrcweir 	}
1546cdf0e10cSrcweir 
B3DPolygon(const B3DPolygon & rPolygon,sal_uInt32 nIndex,sal_uInt32 nCount)1547cdf0e10cSrcweir 	B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount) :
1548cdf0e10cSrcweir         mpPolygon(ImplB3DPolygon(*rPolygon.mpPolygon, nIndex, nCount))
1549cdf0e10cSrcweir 	{
1550cdf0e10cSrcweir         // TODO(P2): one extra temporary here (cow_wrapper copies
1551cdf0e10cSrcweir         // given ImplB3DPolygon into its internal impl_t wrapper type)
1552cdf0e10cSrcweir 		OSL_ENSURE(nIndex + nCount > rPolygon.mpPolygon->count(), "B3DPolygon constructor outside range (!)");
1553cdf0e10cSrcweir 	}
1554cdf0e10cSrcweir 
~B3DPolygon()1555cdf0e10cSrcweir 	B3DPolygon::~B3DPolygon()
1556cdf0e10cSrcweir 	{
1557cdf0e10cSrcweir 	}
1558cdf0e10cSrcweir 
operator =(const B3DPolygon & rPolygon)1559cdf0e10cSrcweir 	B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon)
1560cdf0e10cSrcweir 	{
1561cdf0e10cSrcweir 		mpPolygon = rPolygon.mpPolygon;
1562cdf0e10cSrcweir 		return *this;
1563cdf0e10cSrcweir 	}
1564cdf0e10cSrcweir 
makeUnique()1565cdf0e10cSrcweir     void B3DPolygon::makeUnique()
1566cdf0e10cSrcweir     {
1567cdf0e10cSrcweir         mpPolygon.make_unique();
1568cdf0e10cSrcweir     }
1569cdf0e10cSrcweir 
operator ==(const B3DPolygon & rPolygon) const1570cdf0e10cSrcweir 	bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const
1571cdf0e10cSrcweir 	{
1572cdf0e10cSrcweir 		if(mpPolygon.same_object(rPolygon.mpPolygon))
1573cdf0e10cSrcweir 			return true;
1574cdf0e10cSrcweir 
1575cdf0e10cSrcweir 		return (*mpPolygon == *rPolygon.mpPolygon);
1576cdf0e10cSrcweir 	}
1577cdf0e10cSrcweir 
operator !=(const B3DPolygon & rPolygon) const1578cdf0e10cSrcweir 	bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const
1579cdf0e10cSrcweir 	{
1580cdf0e10cSrcweir         return !(*this == rPolygon);
1581cdf0e10cSrcweir 	}
1582cdf0e10cSrcweir 
count() const1583cdf0e10cSrcweir 	sal_uInt32 B3DPolygon::count() const
1584cdf0e10cSrcweir 	{
1585cdf0e10cSrcweir 		return mpPolygon->count();
1586cdf0e10cSrcweir 	}
1587cdf0e10cSrcweir 
getB3DPoint(sal_uInt32 nIndex) const1588cdf0e10cSrcweir 	basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const
1589cdf0e10cSrcweir 	{
1590cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1591cdf0e10cSrcweir 
1592cdf0e10cSrcweir 		return mpPolygon->getPoint(nIndex);
1593cdf0e10cSrcweir 	}
1594cdf0e10cSrcweir 
setB3DPoint(sal_uInt32 nIndex,const basegfx::B3DPoint & rValue)1595cdf0e10cSrcweir 	void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
1596cdf0e10cSrcweir 	{
1597cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1598cdf0e10cSrcweir 
1599cdf0e10cSrcweir 		if(getB3DPoint(nIndex) != rValue)
1600cdf0e10cSrcweir 			mpPolygon->setPoint(nIndex, rValue);
1601cdf0e10cSrcweir 	}
1602cdf0e10cSrcweir 
getBColor(sal_uInt32 nIndex) const1603cdf0e10cSrcweir 	BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const
1604cdf0e10cSrcweir 	{
1605cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1606cdf0e10cSrcweir 
1607cdf0e10cSrcweir 		return mpPolygon->getBColor(nIndex);
1608cdf0e10cSrcweir 	}
1609cdf0e10cSrcweir 
setBColor(sal_uInt32 nIndex,const BColor & rValue)1610cdf0e10cSrcweir 	void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue)
1611cdf0e10cSrcweir 	{
1612cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1613cdf0e10cSrcweir 
1614cdf0e10cSrcweir 		if(mpPolygon->getBColor(nIndex) != rValue)
1615cdf0e10cSrcweir 			mpPolygon->setBColor(nIndex, rValue);
1616cdf0e10cSrcweir 	}
1617cdf0e10cSrcweir 
areBColorsUsed() const1618cdf0e10cSrcweir 	bool B3DPolygon::areBColorsUsed() const
1619cdf0e10cSrcweir 	{
1620cdf0e10cSrcweir 		return mpPolygon->areBColorsUsed();
1621cdf0e10cSrcweir 	}
1622cdf0e10cSrcweir 
clearBColors()1623cdf0e10cSrcweir 	void B3DPolygon::clearBColors()
1624cdf0e10cSrcweir 	{
1625cdf0e10cSrcweir 		if(mpPolygon->areBColorsUsed())
1626cdf0e10cSrcweir 			mpPolygon->clearBColors();
1627cdf0e10cSrcweir 	}
1628cdf0e10cSrcweir 
getNormal() const1629cdf0e10cSrcweir 	B3DVector B3DPolygon::getNormal() const
1630cdf0e10cSrcweir 	{
1631cdf0e10cSrcweir 		return mpPolygon->getNormal();
1632cdf0e10cSrcweir 	}
1633cdf0e10cSrcweir 
getNormal(sal_uInt32 nIndex) const1634cdf0e10cSrcweir 	B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const
1635cdf0e10cSrcweir 	{
1636cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1637cdf0e10cSrcweir 
1638cdf0e10cSrcweir 		return mpPolygon->getNormal(nIndex);
1639cdf0e10cSrcweir 	}
1640cdf0e10cSrcweir 
setNormal(sal_uInt32 nIndex,const B3DVector & rValue)1641cdf0e10cSrcweir 	void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue)
1642cdf0e10cSrcweir 	{
1643cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1644cdf0e10cSrcweir 
1645cdf0e10cSrcweir 		if(mpPolygon->getNormal(nIndex) != rValue)
1646cdf0e10cSrcweir 			mpPolygon->setNormal(nIndex, rValue);
1647cdf0e10cSrcweir 	}
1648cdf0e10cSrcweir 
transformNormals(const B3DHomMatrix & rMatrix)1649cdf0e10cSrcweir 	void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix)
1650cdf0e10cSrcweir 	{
1651cdf0e10cSrcweir 		if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity())
1652cdf0e10cSrcweir 			mpPolygon->transformNormals(rMatrix);
1653cdf0e10cSrcweir 	}
1654cdf0e10cSrcweir 
areNormalsUsed() const1655cdf0e10cSrcweir 	bool B3DPolygon::areNormalsUsed() const
1656cdf0e10cSrcweir 	{
1657cdf0e10cSrcweir 		return mpPolygon->areNormalsUsed();
1658cdf0e10cSrcweir 	}
1659cdf0e10cSrcweir 
clearNormals()1660cdf0e10cSrcweir 	void B3DPolygon::clearNormals()
1661cdf0e10cSrcweir 	{
1662cdf0e10cSrcweir 		if(mpPolygon->areNormalsUsed())
1663cdf0e10cSrcweir 			mpPolygon->clearNormals();
1664cdf0e10cSrcweir 	}
1665cdf0e10cSrcweir 
getTextureCoordinate(sal_uInt32 nIndex) const1666cdf0e10cSrcweir 	B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const
1667cdf0e10cSrcweir 	{
1668cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1669cdf0e10cSrcweir 
1670cdf0e10cSrcweir 		return mpPolygon->getTextureCoordinate(nIndex);
1671cdf0e10cSrcweir 	}
1672cdf0e10cSrcweir 
setTextureCoordinate(sal_uInt32 nIndex,const B2DPoint & rValue)1673cdf0e10cSrcweir 	void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue)
1674cdf0e10cSrcweir 	{
1675cdf0e10cSrcweir 		OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1676cdf0e10cSrcweir 
1677cdf0e10cSrcweir 		if(mpPolygon->getTextureCoordinate(nIndex) != rValue)
1678cdf0e10cSrcweir 			mpPolygon->setTextureCoordinate(nIndex, rValue);
1679cdf0e10cSrcweir 	}
1680cdf0e10cSrcweir 
transformTextureCoordiantes(const B2DHomMatrix & rMatrix)1681cdf0e10cSrcweir 	void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
1682cdf0e10cSrcweir 	{
1683cdf0e10cSrcweir 		if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity())
1684cdf0e10cSrcweir 			mpPolygon->transformTextureCoordinates(rMatrix);
1685cdf0e10cSrcweir 	}
1686cdf0e10cSrcweir 
areTextureCoordinatesUsed() const1687cdf0e10cSrcweir 	bool B3DPolygon::areTextureCoordinatesUsed() const
1688cdf0e10cSrcweir 	{
1689cdf0e10cSrcweir 		return mpPolygon->areTextureCoordinatesUsed();
1690cdf0e10cSrcweir 	}
1691cdf0e10cSrcweir 
clearTextureCoordinates()1692cdf0e10cSrcweir 	void B3DPolygon::clearTextureCoordinates()
1693cdf0e10cSrcweir 	{
1694cdf0e10cSrcweir 		if(mpPolygon->areTextureCoordinatesUsed())
1695cdf0e10cSrcweir 			mpPolygon->clearTextureCoordinates();
1696cdf0e10cSrcweir 	}
1697cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const::basegfx::B3DPoint & rPoint,sal_uInt32 nCount)1698cdf0e10cSrcweir 	void B3DPolygon::insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1699cdf0e10cSrcweir 	{
1700cdf0e10cSrcweir 		OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1701cdf0e10cSrcweir 
1702cdf0e10cSrcweir 		if(nCount)
1703cdf0e10cSrcweir 			mpPolygon->insert(nIndex, rPoint, nCount);
1704cdf0e10cSrcweir 	}
1705cdf0e10cSrcweir 
append(const basegfx::B3DPoint & rPoint,sal_uInt32 nCount)1706cdf0e10cSrcweir 	void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1707cdf0e10cSrcweir 	{
1708cdf0e10cSrcweir 		if(nCount)
1709cdf0e10cSrcweir 			mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1710cdf0e10cSrcweir 	}
1711cdf0e10cSrcweir 
insert(sal_uInt32 nIndex,const B3DPolygon & rPoly,sal_uInt32 nIndex2,sal_uInt32 nCount)1712cdf0e10cSrcweir 	void B3DPolygon::insert(sal_uInt32 nIndex, const B3DPolygon& rPoly, sal_uInt32 nIndex2, sal_uInt32 nCount)
1713cdf0e10cSrcweir 	{
1714cdf0e10cSrcweir 		OSL_ENSURE(nIndex <= mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1715cdf0e10cSrcweir 
1716cdf0e10cSrcweir 		if(rPoly.count())
1717cdf0e10cSrcweir 		{
1718cdf0e10cSrcweir 			if(!nCount)
1719cdf0e10cSrcweir 			{
1720cdf0e10cSrcweir 				nCount = rPoly.count();
1721cdf0e10cSrcweir 			}
1722cdf0e10cSrcweir 
1723cdf0e10cSrcweir 			if(0L == nIndex2 && nCount == rPoly.count())
1724cdf0e10cSrcweir 			{
1725cdf0e10cSrcweir 				mpPolygon->insert(nIndex, *rPoly.mpPolygon);
1726cdf0e10cSrcweir 			}
1727cdf0e10cSrcweir 			else
1728cdf0e10cSrcweir 			{
1729cdf0e10cSrcweir 				OSL_ENSURE(nIndex2 + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Insert outside range (!)");
1730cdf0e10cSrcweir 				ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex2, nCount);
1731cdf0e10cSrcweir 				mpPolygon->insert(nIndex, aTempPoly);
1732cdf0e10cSrcweir 			}
1733cdf0e10cSrcweir 		}
1734cdf0e10cSrcweir 	}
1735cdf0e10cSrcweir 
append(const B3DPolygon & rPoly,sal_uInt32 nIndex,sal_uInt32 nCount)1736cdf0e10cSrcweir 	void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
1737cdf0e10cSrcweir 	{
1738cdf0e10cSrcweir 		if(rPoly.count())
1739cdf0e10cSrcweir 		{
1740cdf0e10cSrcweir 			if(!nCount)
1741cdf0e10cSrcweir 			{
1742cdf0e10cSrcweir 				nCount = rPoly.count();
1743cdf0e10cSrcweir 			}
1744cdf0e10cSrcweir 
1745cdf0e10cSrcweir 			if(0L == nIndex && nCount == rPoly.count())
1746cdf0e10cSrcweir 			{
1747cdf0e10cSrcweir 				mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
1748cdf0e10cSrcweir 			}
1749cdf0e10cSrcweir 			else
1750cdf0e10cSrcweir 			{
1751cdf0e10cSrcweir 				OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)");
1752cdf0e10cSrcweir 				ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
1753cdf0e10cSrcweir 				mpPolygon->insert(mpPolygon->count(), aTempPoly);
1754cdf0e10cSrcweir 			}
1755cdf0e10cSrcweir 		}
1756cdf0e10cSrcweir 	}
1757cdf0e10cSrcweir 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)1758cdf0e10cSrcweir 	void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1759cdf0e10cSrcweir 	{
1760cdf0e10cSrcweir 		OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)");
1761cdf0e10cSrcweir 
1762cdf0e10cSrcweir 		if(nCount)
1763cdf0e10cSrcweir 			mpPolygon->remove(nIndex, nCount);
1764cdf0e10cSrcweir 	}
1765cdf0e10cSrcweir 
clear()1766cdf0e10cSrcweir 	void B3DPolygon::clear()
1767cdf0e10cSrcweir 	{
1768cdf0e10cSrcweir 		mpPolygon = DefaultPolygon::get();
1769cdf0e10cSrcweir 	}
1770cdf0e10cSrcweir 
isClosed() const1771cdf0e10cSrcweir 	bool B3DPolygon::isClosed() const
1772cdf0e10cSrcweir 	{
1773cdf0e10cSrcweir 		return mpPolygon->isClosed();
1774cdf0e10cSrcweir 	}
1775cdf0e10cSrcweir 
setClosed(bool bNew)1776cdf0e10cSrcweir 	void B3DPolygon::setClosed(bool bNew)
1777cdf0e10cSrcweir 	{
1778cdf0e10cSrcweir 		if(isClosed() != bNew)
1779cdf0e10cSrcweir 			mpPolygon->setClosed(bNew);
1780cdf0e10cSrcweir 	}
1781cdf0e10cSrcweir 
flip()1782cdf0e10cSrcweir 	void B3DPolygon::flip()
1783cdf0e10cSrcweir 	{
1784cdf0e10cSrcweir 		if(count() > 1)
1785cdf0e10cSrcweir 			mpPolygon->flip();
1786cdf0e10cSrcweir 	}
1787cdf0e10cSrcweir 
hasDoublePoints() const1788cdf0e10cSrcweir 	bool B3DPolygon::hasDoublePoints() const
1789cdf0e10cSrcweir 	{
1790cdf0e10cSrcweir 		return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints());
1791cdf0e10cSrcweir 	}
1792cdf0e10cSrcweir 
removeDoublePoints()1793cdf0e10cSrcweir 	void B3DPolygon::removeDoublePoints()
1794cdf0e10cSrcweir 	{
1795cdf0e10cSrcweir 		if(hasDoublePoints())
1796cdf0e10cSrcweir 		{
1797cdf0e10cSrcweir 			mpPolygon->removeDoublePointsAtBeginEnd();
1798cdf0e10cSrcweir 			mpPolygon->removeDoublePointsWholeTrack();
1799cdf0e10cSrcweir 		}
1800cdf0e10cSrcweir 	}
1801cdf0e10cSrcweir 
transform(const basegfx::B3DHomMatrix & rMatrix)1802cdf0e10cSrcweir 	void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix)
1803cdf0e10cSrcweir 	{
1804cdf0e10cSrcweir 		if(mpPolygon->count() && !rMatrix.isIdentity())
1805cdf0e10cSrcweir 		{
1806cdf0e10cSrcweir 			mpPolygon->transform(rMatrix);
1807cdf0e10cSrcweir 		}
1808cdf0e10cSrcweir 	}
1809cdf0e10cSrcweir } // end of namespace basegfx
1810cdf0e10cSrcweir 
1811cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1812cdf0e10cSrcweir // eof
1813