109dbbe93SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
309dbbe93SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
409dbbe93SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
509dbbe93SAndrew Rist  * distributed with this work for additional information
609dbbe93SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
709dbbe93SAndrew Rist  * to you under the Apache License, Version 2.0 (the
809dbbe93SAndrew Rist  * "License"); you may not use this file except in compliance
909dbbe93SAndrew Rist  * with the License.  You may obtain a copy of the License at
1009dbbe93SAndrew Rist  *
1109dbbe93SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1209dbbe93SAndrew Rist  *
1309dbbe93SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1409dbbe93SAndrew Rist  * software distributed under the License is distributed on an
1509dbbe93SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1609dbbe93SAndrew Rist  * KIND, either express or implied.  See the License for the
1709dbbe93SAndrew Rist  * specific language governing permissions and limitations
1809dbbe93SAndrew Rist  * under the License.
1909dbbe93SAndrew Rist  *
2009dbbe93SAndrew Rist  *************************************************************/
2109dbbe93SAndrew Rist 
2209dbbe93SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basegfx.hxx"
26cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygontools.hxx>
27cdf0e10cSrcweir #include <basegfx/range/b3drange.hxx>
28cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygon.hxx>
29cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygon.hxx>
30cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygontools.hxx>
31cdf0e10cSrcweir #include <numeric>
32cdf0e10cSrcweir #include <basegfx/matrix/b3dhommatrix.hxx>
33cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
34cdf0e10cSrcweir #include <osl/mutex.hxx>
35cdf0e10cSrcweir 
36*5aaf853bSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
37*5aaf853bSArmin Le Grand // predefines
38*5aaf853bSArmin Le Grand #define nMinSegments sal_uInt32(1)
39*5aaf853bSArmin Le Grand #define nMaxSegments sal_uInt32(512)
40*5aaf853bSArmin Le Grand 
41cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
42cdf0e10cSrcweir 
43cdf0e10cSrcweir namespace basegfx
44cdf0e10cSrcweir {
45cdf0e10cSrcweir 	namespace tools
46cdf0e10cSrcweir 	{
47cdf0e10cSrcweir 		// B3DPolyPolygon tools
48cdf0e10cSrcweir 		B3DRange getRange(const B3DPolyPolygon& rCandidate)
49cdf0e10cSrcweir 		{
50cdf0e10cSrcweir 			B3DRange aRetval;
51cdf0e10cSrcweir 			const sal_uInt32 nPolygonCount(rCandidate.count());
52cdf0e10cSrcweir 
53cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < nPolygonCount; a++)
54cdf0e10cSrcweir 			{
55cdf0e10cSrcweir 				B3DPolygon aCandidate = rCandidate.getB3DPolygon(a);
56cdf0e10cSrcweir 				aRetval.expand(getRange(aCandidate));
57cdf0e10cSrcweir 			}
58cdf0e10cSrcweir 
59cdf0e10cSrcweir 			return aRetval;
60cdf0e10cSrcweir 		}
61cdf0e10cSrcweir 
62cdf0e10cSrcweir 		void applyLineDashing(const B3DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B3DPolyPolygon* pLineTarget, B3DPolyPolygon* pGapTarget, double fFullDashDotLen)
63cdf0e10cSrcweir 		{
64cdf0e10cSrcweir 			if(0.0 == fFullDashDotLen && rDotDashArray.size())
65cdf0e10cSrcweir 			{
66cdf0e10cSrcweir 				// calculate fFullDashDotLen from rDotDashArray
67cdf0e10cSrcweir 				fFullDashDotLen = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
68cdf0e10cSrcweir 			}
69cdf0e10cSrcweir 
70cdf0e10cSrcweir 			if(rCandidate.count() && fFullDashDotLen > 0.0)
71cdf0e10cSrcweir 			{
72cdf0e10cSrcweir 				B3DPolyPolygon aLineTarget, aGapTarget;
73cdf0e10cSrcweir 
74cdf0e10cSrcweir 				for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
75cdf0e10cSrcweir 				{
76cdf0e10cSrcweir 					const B3DPolygon aCandidate(rCandidate.getB3DPolygon(a));
77cdf0e10cSrcweir 
78cdf0e10cSrcweir 					applyLineDashing(
79cdf0e10cSrcweir 						aCandidate,
80cdf0e10cSrcweir 						rDotDashArray,
81cdf0e10cSrcweir 						pLineTarget ? &aLineTarget : 0,
82cdf0e10cSrcweir 						pGapTarget ? &aGapTarget : 0,
83cdf0e10cSrcweir 						fFullDashDotLen);
84cdf0e10cSrcweir 
85cdf0e10cSrcweir 					if(pLineTarget)
86cdf0e10cSrcweir 					{
87cdf0e10cSrcweir 						pLineTarget->append(aLineTarget);
88cdf0e10cSrcweir 					}
89cdf0e10cSrcweir 
90cdf0e10cSrcweir 					if(pGapTarget)
91cdf0e10cSrcweir 					{
92cdf0e10cSrcweir 						pGapTarget->append(aGapTarget);
93cdf0e10cSrcweir 					}
94cdf0e10cSrcweir 				}
95cdf0e10cSrcweir 			}
96cdf0e10cSrcweir 		}
97cdf0e10cSrcweir 
98cdf0e10cSrcweir 		B3DPolyPolygon createUnitCubePolyPolygon()
99cdf0e10cSrcweir 		{
100cdf0e10cSrcweir 			static B3DPolyPolygon aRetval;
101cdf0e10cSrcweir 		    ::osl::Mutex m_mutex;
102cdf0e10cSrcweir 
103cdf0e10cSrcweir 			if(!aRetval.count())
104cdf0e10cSrcweir 			{
105cdf0e10cSrcweir 				B3DPolygon aTemp;
106cdf0e10cSrcweir 				aTemp.append(B3DPoint(0.0, 0.0, 1.0));
107cdf0e10cSrcweir 				aTemp.append(B3DPoint(0.0, 1.0, 1.0));
108cdf0e10cSrcweir 				aTemp.append(B3DPoint(1.0, 1.0, 1.0));
109cdf0e10cSrcweir 				aTemp.append(B3DPoint(1.0, 0.0, 1.0));
110cdf0e10cSrcweir 				aTemp.setClosed(true);
111cdf0e10cSrcweir 				aRetval.append(aTemp);
112cdf0e10cSrcweir 
113cdf0e10cSrcweir 				aTemp.clear();
114cdf0e10cSrcweir 				aTemp.append(B3DPoint(0.0, 0.0, 0.0));
115cdf0e10cSrcweir 				aTemp.append(B3DPoint(0.0, 1.0, 0.0));
116cdf0e10cSrcweir 				aTemp.append(B3DPoint(1.0, 1.0, 0.0));
117cdf0e10cSrcweir 				aTemp.append(B3DPoint(1.0, 0.0, 0.0));
118cdf0e10cSrcweir 				aTemp.setClosed(true);
119cdf0e10cSrcweir 				aRetval.append(aTemp);
120cdf0e10cSrcweir 
121cdf0e10cSrcweir 				aTemp.clear();
122cdf0e10cSrcweir 				aTemp.append(B3DPoint(0.0, 0.0, 0.0));
123cdf0e10cSrcweir 				aTemp.append(B3DPoint(0.0, 0.0, 1.0));
124cdf0e10cSrcweir 				aRetval.append(aTemp);
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 				aTemp.clear();
127cdf0e10cSrcweir 				aTemp.append(B3DPoint(0.0, 1.0, 0.0));
128cdf0e10cSrcweir 				aTemp.append(B3DPoint(0.0, 1.0, 1.0));
129cdf0e10cSrcweir 				aRetval.append(aTemp);
130cdf0e10cSrcweir 
131cdf0e10cSrcweir 				aTemp.clear();
132cdf0e10cSrcweir 				aTemp.append(B3DPoint(1.0, 1.0, 0.0));
133cdf0e10cSrcweir 				aTemp.append(B3DPoint(1.0, 1.0, 1.0));
134cdf0e10cSrcweir 				aRetval.append(aTemp);
135cdf0e10cSrcweir 
136cdf0e10cSrcweir 				aTemp.clear();
137cdf0e10cSrcweir 				aTemp.append(B3DPoint(1.0, 0.0, 0.0));
138cdf0e10cSrcweir 				aTemp.append(B3DPoint(1.0, 0.0, 1.0));
139cdf0e10cSrcweir 				aRetval.append(aTemp);
140cdf0e10cSrcweir 			}
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 			return aRetval;
143cdf0e10cSrcweir 		}
144cdf0e10cSrcweir 
145cdf0e10cSrcweir 		B3DPolyPolygon createUnitCubeFillPolyPolygon()
146cdf0e10cSrcweir 		{
147cdf0e10cSrcweir 			static B3DPolyPolygon aRetval;
148cdf0e10cSrcweir 		    ::osl::Mutex m_mutex;
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 			if(!aRetval.count())
151cdf0e10cSrcweir 			{
152cdf0e10cSrcweir 				B3DPolygon aTemp;
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 				// all points
155cdf0e10cSrcweir 				const B3DPoint A(0.0, 0.0, 0.0);
156cdf0e10cSrcweir 				const B3DPoint B(0.0, 1.0, 0.0);
157cdf0e10cSrcweir 				const B3DPoint C(1.0, 1.0, 0.0);
158cdf0e10cSrcweir 				const B3DPoint D(1.0, 0.0, 0.0);
159cdf0e10cSrcweir 				const B3DPoint E(0.0, 0.0, 1.0);
160cdf0e10cSrcweir 				const B3DPoint F(0.0, 1.0, 1.0);
161cdf0e10cSrcweir 				const B3DPoint G(1.0, 1.0, 1.0);
162cdf0e10cSrcweir 				const B3DPoint H(1.0, 0.0, 1.0);
163cdf0e10cSrcweir 
164cdf0e10cSrcweir 				// create bottom
165cdf0e10cSrcweir 				aTemp.append(D);
166cdf0e10cSrcweir 				aTemp.append(A);
167cdf0e10cSrcweir 				aTemp.append(E);
168cdf0e10cSrcweir 				aTemp.append(H);
169cdf0e10cSrcweir 				aTemp.setClosed(true);
170cdf0e10cSrcweir 				aRetval.append(aTemp);
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 				// create front
173cdf0e10cSrcweir 				aTemp.clear();
174cdf0e10cSrcweir 				aTemp.append(B);
175cdf0e10cSrcweir 				aTemp.append(A);
176cdf0e10cSrcweir 				aTemp.append(D);
177cdf0e10cSrcweir 				aTemp.append(C);
178cdf0e10cSrcweir 				aTemp.setClosed(true);
179cdf0e10cSrcweir 				aRetval.append(aTemp);
180cdf0e10cSrcweir 
181cdf0e10cSrcweir 				// create left
182cdf0e10cSrcweir 				aTemp.clear();
183cdf0e10cSrcweir 				aTemp.append(E);
184cdf0e10cSrcweir 				aTemp.append(A);
185cdf0e10cSrcweir 				aTemp.append(B);
186cdf0e10cSrcweir 				aTemp.append(F);
187cdf0e10cSrcweir 				aTemp.setClosed(true);
188cdf0e10cSrcweir 				aRetval.append(aTemp);
189cdf0e10cSrcweir 
190cdf0e10cSrcweir 				// create top
191cdf0e10cSrcweir 				aTemp.clear();
192cdf0e10cSrcweir 				aTemp.append(C);
193cdf0e10cSrcweir 				aTemp.append(G);
194cdf0e10cSrcweir 				aTemp.append(F);
195cdf0e10cSrcweir 				aTemp.append(B);
196cdf0e10cSrcweir 				aTemp.setClosed(true);
197cdf0e10cSrcweir 				aRetval.append(aTemp);
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 				// create right
200cdf0e10cSrcweir 				aTemp.clear();
201cdf0e10cSrcweir 				aTemp.append(H);
202cdf0e10cSrcweir 				aTemp.append(G);
203cdf0e10cSrcweir 				aTemp.append(C);
204cdf0e10cSrcweir 				aTemp.append(D);
205cdf0e10cSrcweir 				aTemp.setClosed(true);
206cdf0e10cSrcweir 				aRetval.append(aTemp);
207cdf0e10cSrcweir 
208cdf0e10cSrcweir 				// create back
209cdf0e10cSrcweir 				aTemp.clear();
210cdf0e10cSrcweir 				aTemp.append(F);
211cdf0e10cSrcweir 				aTemp.append(G);
212cdf0e10cSrcweir 				aTemp.append(H);
213cdf0e10cSrcweir 				aTemp.append(E);
214cdf0e10cSrcweir 				aTemp.setClosed(true);
215cdf0e10cSrcweir 				aRetval.append(aTemp);
216cdf0e10cSrcweir 			}
217cdf0e10cSrcweir 
218cdf0e10cSrcweir 			return aRetval;
219cdf0e10cSrcweir 		}
220cdf0e10cSrcweir 
221cdf0e10cSrcweir 		B3DPolyPolygon createCubePolyPolygonFromB3DRange( const B3DRange& rRange)
222cdf0e10cSrcweir 		{
223cdf0e10cSrcweir 			B3DPolyPolygon aRetval;
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 			if(!rRange.isEmpty())
226cdf0e10cSrcweir 			{
227cdf0e10cSrcweir 				aRetval = createUnitCubePolyPolygon();
228cdf0e10cSrcweir 				B3DHomMatrix aTrans;
229cdf0e10cSrcweir 				aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
230cdf0e10cSrcweir 				aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
231cdf0e10cSrcweir 				aRetval.transform(aTrans);
232cdf0e10cSrcweir 				aRetval.removeDoublePoints();
233cdf0e10cSrcweir 			}
234cdf0e10cSrcweir 
235cdf0e10cSrcweir 			return aRetval;
236cdf0e10cSrcweir 		}
237cdf0e10cSrcweir 
238cdf0e10cSrcweir 		B3DPolyPolygon createCubeFillPolyPolygonFromB3DRange( const B3DRange& rRange)
239cdf0e10cSrcweir 		{
240cdf0e10cSrcweir 			B3DPolyPolygon aRetval;
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 			if(!rRange.isEmpty())
243cdf0e10cSrcweir 			{
244cdf0e10cSrcweir 				aRetval = createUnitCubeFillPolyPolygon();
245cdf0e10cSrcweir 				B3DHomMatrix aTrans;
246cdf0e10cSrcweir 				aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
247cdf0e10cSrcweir 				aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
248cdf0e10cSrcweir 				aRetval.transform(aTrans);
249cdf0e10cSrcweir 				aRetval.removeDoublePoints();
250cdf0e10cSrcweir 			}
251cdf0e10cSrcweir 
252cdf0e10cSrcweir 			return aRetval;
253cdf0e10cSrcweir 		}
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 		// helper for getting the 3D Point from given cartesian coordiantes. fVer is defined from
256cdf0e10cSrcweir 		// [F_PI2 .. -F_PI2], fHor from [0.0 .. F_2PI]
257cdf0e10cSrcweir 		inline B3DPoint getPointFromCartesian(double fVer, double fHor)
258cdf0e10cSrcweir 		{
259cdf0e10cSrcweir 			const double fCosHor(cos(fHor));
260cdf0e10cSrcweir 			return B3DPoint(fCosHor * cos(fVer), sin(fHor), fCosHor * -sin(fVer));
261cdf0e10cSrcweir 		}
262cdf0e10cSrcweir 
263cdf0e10cSrcweir 		B3DPolyPolygon createUnitSpherePolyPolygon(
264cdf0e10cSrcweir 			sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
265cdf0e10cSrcweir 			double fVerStart, double fVerStop,
266cdf0e10cSrcweir 			double fHorStart, double fHorStop)
267cdf0e10cSrcweir 		{
268cdf0e10cSrcweir 			B3DPolyPolygon aRetval;
269cdf0e10cSrcweir 			sal_uInt32 a, b;
270cdf0e10cSrcweir 
271cdf0e10cSrcweir 			if(!nHorSeg)
272cdf0e10cSrcweir 			{
273cdf0e10cSrcweir 				nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
274cdf0e10cSrcweir 			}
275cdf0e10cSrcweir 
276*5aaf853bSArmin Le Grand             // min/max limitations
277*5aaf853bSArmin Le Grand             nHorSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nHorSeg));
278cdf0e10cSrcweir 
279cdf0e10cSrcweir 			if(!nVerSeg)
280cdf0e10cSrcweir 			{
281cdf0e10cSrcweir 				nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
282cdf0e10cSrcweir 			}
283cdf0e10cSrcweir 
284*5aaf853bSArmin Le Grand             // min/max limitations
285*5aaf853bSArmin Le Grand             nVerSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nVerSeg));
286cdf0e10cSrcweir 
287cdf0e10cSrcweir 			// create constants
288cdf0e10cSrcweir 			const double fVerDiffPerStep((fVerStop - fVerStart) / (double)nVerSeg);
289cdf0e10cSrcweir 			const double fHorDiffPerStep((fHorStop - fHorStart) / (double)nHorSeg);
290cdf0e10cSrcweir 			bool bHorClosed(fTools::equal(fHorStop - fHorStart, F_2PI));
291cdf0e10cSrcweir 			bool bVerFromTop(fTools::equal(fVerStart, F_PI2));
292cdf0e10cSrcweir 			bool bVerToBottom(fTools::equal(fVerStop, -F_PI2));
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 			// create horizontal rings
295cdf0e10cSrcweir 			const sal_uInt32 nLoopVerInit(bVerFromTop ? 1L : 0L);
296cdf0e10cSrcweir 			const sal_uInt32 nLoopVerLimit(bVerToBottom ? nVerSeg : nVerSeg + 1L);
297cdf0e10cSrcweir 			const sal_uInt32 nLoopHorLimit(bHorClosed ? nHorSeg : nHorSeg + 1L);
298cdf0e10cSrcweir 
299cdf0e10cSrcweir 			for(a = nLoopVerInit; a < nLoopVerLimit; a++)
300cdf0e10cSrcweir 			{
301cdf0e10cSrcweir 				const double fVer(fVerStart + ((double)(a) * fVerDiffPerStep));
302cdf0e10cSrcweir 				B3DPolygon aNew;
303cdf0e10cSrcweir 
304cdf0e10cSrcweir 				for(b = 0L; b < nLoopHorLimit; b++)
305cdf0e10cSrcweir 				{
306cdf0e10cSrcweir 					const double fHor(fHorStart + ((double)(b) * fHorDiffPerStep));
307cdf0e10cSrcweir 					aNew.append(getPointFromCartesian(fHor, fVer));
308cdf0e10cSrcweir 				}
309cdf0e10cSrcweir 
310cdf0e10cSrcweir 				aNew.setClosed(bHorClosed);
311cdf0e10cSrcweir 				aRetval.append(aNew);
312cdf0e10cSrcweir 			}
313cdf0e10cSrcweir 
314cdf0e10cSrcweir 			// create vertical half-rings
315cdf0e10cSrcweir 			for(a = 0L; a < nLoopHorLimit; a++)
316cdf0e10cSrcweir 			{
317cdf0e10cSrcweir 				const double fHor(fHorStart + ((double)(a) * fHorDiffPerStep));
318cdf0e10cSrcweir 				B3DPolygon aNew;
319cdf0e10cSrcweir 
320cdf0e10cSrcweir 				if(bVerFromTop)
321cdf0e10cSrcweir 				{
322cdf0e10cSrcweir 					aNew.append(B3DPoint(0.0, 1.0, 0.0));
323cdf0e10cSrcweir 				}
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 				for(b = nLoopVerInit; b < nLoopVerLimit; b++)
326cdf0e10cSrcweir 				{
327cdf0e10cSrcweir 					const double fVer(fVerStart + ((double)(b) * fVerDiffPerStep));
328cdf0e10cSrcweir 					aNew.append(getPointFromCartesian(fHor, fVer));
329cdf0e10cSrcweir 				}
330cdf0e10cSrcweir 
331cdf0e10cSrcweir 				if(bVerToBottom)
332cdf0e10cSrcweir 				{
333cdf0e10cSrcweir 					aNew.append(B3DPoint(0.0, -1.0, 0.0));
334cdf0e10cSrcweir 				}
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 				aRetval.append(aNew);
337cdf0e10cSrcweir 			}
338cdf0e10cSrcweir 
339cdf0e10cSrcweir 			return aRetval;
340cdf0e10cSrcweir 		}
341cdf0e10cSrcweir 
342cdf0e10cSrcweir 		B3DPolyPolygon createSpherePolyPolygonFromB3DRange( const B3DRange& rRange,
343cdf0e10cSrcweir 			sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
344cdf0e10cSrcweir 			double fVerStart, double fVerStop,
345cdf0e10cSrcweir 			double fHorStart, double fHorStop)
346cdf0e10cSrcweir 		{
347cdf0e10cSrcweir 			B3DPolyPolygon aRetval(createUnitSpherePolyPolygon(nHorSeg, nVerSeg, fVerStart, fVerStop, fHorStart, fHorStop));
348cdf0e10cSrcweir 
349cdf0e10cSrcweir 			if(aRetval.count())
350cdf0e10cSrcweir 			{
351cdf0e10cSrcweir 				// move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
352cdf0e10cSrcweir 				B3DHomMatrix aTrans;
353cdf0e10cSrcweir 				aTrans.translate(1.0, 1.0, 1.0);
354cdf0e10cSrcweir 				aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
355cdf0e10cSrcweir 				aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
356cdf0e10cSrcweir 				aRetval.transform(aTrans);
357cdf0e10cSrcweir 			}
358cdf0e10cSrcweir 
359cdf0e10cSrcweir 			return aRetval;
360cdf0e10cSrcweir 		}
361cdf0e10cSrcweir 
362cdf0e10cSrcweir 		B3DPolyPolygon createUnitSphereFillPolyPolygon(
363cdf0e10cSrcweir 			sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
364cdf0e10cSrcweir 			bool bNormals,
365cdf0e10cSrcweir 			double fVerStart, double fVerStop,
366cdf0e10cSrcweir 			double fHorStart, double fHorStop)
367cdf0e10cSrcweir 		{
368cdf0e10cSrcweir 			B3DPolyPolygon aRetval;
369cdf0e10cSrcweir 
370cdf0e10cSrcweir 			if(!nHorSeg)
371cdf0e10cSrcweir 			{
372cdf0e10cSrcweir 				nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
373cdf0e10cSrcweir 			}
374cdf0e10cSrcweir 
375*5aaf853bSArmin Le Grand             // min/max limitations
376*5aaf853bSArmin Le Grand             nHorSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nHorSeg));
377cdf0e10cSrcweir 
378cdf0e10cSrcweir 			if(!nVerSeg)
379cdf0e10cSrcweir 			{
380cdf0e10cSrcweir 				nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
381cdf0e10cSrcweir 			}
382cdf0e10cSrcweir 
383*5aaf853bSArmin Le Grand             // min/max limitations
384*5aaf853bSArmin Le Grand             nVerSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nVerSeg));
385cdf0e10cSrcweir 
386cdf0e10cSrcweir 			// vertical loop
387cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < nVerSeg; a++)
388cdf0e10cSrcweir 			{
389cdf0e10cSrcweir 				const double fVer(fVerStart + (((fVerStop - fVerStart) * a) / nVerSeg));
390cdf0e10cSrcweir 				const double fVer2(fVerStart + (((fVerStop - fVerStart) * (a + 1)) / nVerSeg));
391cdf0e10cSrcweir 
392cdf0e10cSrcweir 				// horizontal loop
393cdf0e10cSrcweir 				for(sal_uInt32 b(0L); b < nHorSeg; b++)
394cdf0e10cSrcweir 				{
395cdf0e10cSrcweir 					const double fHor(fHorStart + (((fHorStop - fHorStart) * b) / nHorSeg));
396cdf0e10cSrcweir 					const double fHor2(fHorStart + (((fHorStop - fHorStart) * (b + 1)) / nHorSeg));
397cdf0e10cSrcweir 					B3DPolygon aNew;
398cdf0e10cSrcweir 
399cdf0e10cSrcweir 					aNew.append(getPointFromCartesian(fHor, fVer));
400cdf0e10cSrcweir 					aNew.append(getPointFromCartesian(fHor2, fVer));
401cdf0e10cSrcweir 					aNew.append(getPointFromCartesian(fHor2, fVer2));
402cdf0e10cSrcweir 					aNew.append(getPointFromCartesian(fHor, fVer2));
403cdf0e10cSrcweir 
404cdf0e10cSrcweir 					if(bNormals)
405cdf0e10cSrcweir 					{
406cdf0e10cSrcweir 						for(sal_uInt32 c(0L); c < aNew.count(); c++)
407cdf0e10cSrcweir 						{
408cdf0e10cSrcweir 							aNew.setNormal(c, ::basegfx::B3DVector(aNew.getB3DPoint(c)));
409cdf0e10cSrcweir 						}
410cdf0e10cSrcweir 					}
411cdf0e10cSrcweir 
412cdf0e10cSrcweir 					aNew.setClosed(true);
413cdf0e10cSrcweir 					aRetval.append(aNew);
414cdf0e10cSrcweir 				}
415cdf0e10cSrcweir 			}
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 			return aRetval;
418cdf0e10cSrcweir 		}
419cdf0e10cSrcweir 
420cdf0e10cSrcweir 		B3DPolyPolygon createSphereFillPolyPolygonFromB3DRange( const B3DRange& rRange,
421cdf0e10cSrcweir 			sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
422cdf0e10cSrcweir 			bool bNormals,
423cdf0e10cSrcweir 			double fVerStart, double fVerStop,
424cdf0e10cSrcweir 			double fHorStart, double fHorStop)
425cdf0e10cSrcweir 		{
426cdf0e10cSrcweir 			B3DPolyPolygon aRetval(createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, bNormals, fVerStart, fVerStop, fHorStart, fHorStop));
427cdf0e10cSrcweir 
428cdf0e10cSrcweir 			if(aRetval.count())
429cdf0e10cSrcweir 			{
430cdf0e10cSrcweir 				// move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
431cdf0e10cSrcweir 				B3DHomMatrix aTrans;
432cdf0e10cSrcweir 				aTrans.translate(1.0, 1.0, 1.0);
433cdf0e10cSrcweir 				aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
434cdf0e10cSrcweir 				aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
435cdf0e10cSrcweir 				aRetval.transform(aTrans);
436cdf0e10cSrcweir 			}
437cdf0e10cSrcweir 
438cdf0e10cSrcweir 			return aRetval;
439cdf0e10cSrcweir 		}
440cdf0e10cSrcweir 
441cdf0e10cSrcweir 		B3DPolyPolygon applyDefaultNormalsSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter)
442cdf0e10cSrcweir 		{
443cdf0e10cSrcweir 			B3DPolyPolygon aRetval;
444cdf0e10cSrcweir 
445cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
446cdf0e10cSrcweir 			{
447cdf0e10cSrcweir 				aRetval.append(applyDefaultNormalsSphere(rCandidate.getB3DPolygon(a), rCenter));
448cdf0e10cSrcweir 			}
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 			return aRetval;
451cdf0e10cSrcweir 		}
452cdf0e10cSrcweir 
453cdf0e10cSrcweir 		B3DPolyPolygon invertNormals( const B3DPolyPolygon& rCandidate)
454cdf0e10cSrcweir 		{
455cdf0e10cSrcweir 			B3DPolyPolygon aRetval;
456cdf0e10cSrcweir 
457cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
458cdf0e10cSrcweir 			{
459cdf0e10cSrcweir 				aRetval.append(invertNormals(rCandidate.getB3DPolygon(a)));
460cdf0e10cSrcweir 			}
461cdf0e10cSrcweir 
462cdf0e10cSrcweir 			return aRetval;
463cdf0e10cSrcweir 		}
464cdf0e10cSrcweir 
465cdf0e10cSrcweir 		B3DPolyPolygon applyDefaultTextureCoordinatesParallel( const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bChangeX, bool bChangeY)
466cdf0e10cSrcweir 		{
467cdf0e10cSrcweir 			B3DPolyPolygon aRetval;
468cdf0e10cSrcweir 
469cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
470cdf0e10cSrcweir 			{
471cdf0e10cSrcweir 				aRetval.append(applyDefaultTextureCoordinatesParallel(rCandidate.getB3DPolygon(a), rRange, bChangeX, bChangeY));
472cdf0e10cSrcweir 			}
473cdf0e10cSrcweir 
474cdf0e10cSrcweir 			return aRetval;
475cdf0e10cSrcweir 		}
476cdf0e10cSrcweir 
477cdf0e10cSrcweir 		B3DPolyPolygon applyDefaultTextureCoordinatesSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX, bool bChangeY)
478cdf0e10cSrcweir 		{
479cdf0e10cSrcweir 			B3DPolyPolygon aRetval;
480cdf0e10cSrcweir 
481cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
482cdf0e10cSrcweir 			{
483cdf0e10cSrcweir 				aRetval.append(applyDefaultTextureCoordinatesSphere(rCandidate.getB3DPolygon(a), rCenter, bChangeX, bChangeY));
484cdf0e10cSrcweir 			}
485cdf0e10cSrcweir 
486cdf0e10cSrcweir 			return aRetval;
487cdf0e10cSrcweir 		}
488cdf0e10cSrcweir 
489cdf0e10cSrcweir 		bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder)
490cdf0e10cSrcweir 		{
491cdf0e10cSrcweir 			const sal_uInt32 nPolygonCount(rCandidate.count());
492cdf0e10cSrcweir 
493cdf0e10cSrcweir 			if(1L == nPolygonCount)
494cdf0e10cSrcweir 			{
495cdf0e10cSrcweir 				return isInside(rCandidate.getB3DPolygon(0), rPoint, bWithBorder);
496cdf0e10cSrcweir 			}
497cdf0e10cSrcweir 			else
498cdf0e10cSrcweir 			{
499cdf0e10cSrcweir 				sal_Int32 nInsideCount(0);
500cdf0e10cSrcweir 
501cdf0e10cSrcweir 				for(sal_uInt32 a(0); a < nPolygonCount; a++)
502cdf0e10cSrcweir 				{
503cdf0e10cSrcweir 					const B3DPolygon aPolygon(rCandidate.getB3DPolygon(a));
504cdf0e10cSrcweir 					const bool bInside(isInside(aPolygon, rPoint, bWithBorder));
505cdf0e10cSrcweir 
506cdf0e10cSrcweir 					if(bInside)
507cdf0e10cSrcweir 					{
508cdf0e10cSrcweir 						nInsideCount++;
509cdf0e10cSrcweir 					}
510cdf0e10cSrcweir 				}
511cdf0e10cSrcweir 
512cdf0e10cSrcweir 				return (nInsideCount % 2L);
513cdf0e10cSrcweir 			}
514cdf0e10cSrcweir 		}
515cdf0e10cSrcweir 
516cdf0e10cSrcweir 		//////////////////////////////////////////////////////////////////////
517cdf0e10cSrcweir 		// comparators with tolerance for 3D PolyPolygons
518cdf0e10cSrcweir 
519cdf0e10cSrcweir 		bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB, const double& rfSmallValue)
520cdf0e10cSrcweir 		{
521cdf0e10cSrcweir 			const sal_uInt32 nPolygonCount(rCandidateA.count());
522cdf0e10cSrcweir 
523cdf0e10cSrcweir 			if(nPolygonCount != rCandidateB.count())
524cdf0e10cSrcweir 				return false;
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 			for(sal_uInt32 a(0); a < nPolygonCount; a++)
527cdf0e10cSrcweir 			{
528cdf0e10cSrcweir 				const B3DPolygon aCandidate(rCandidateA.getB3DPolygon(a));
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 				if(!equal(aCandidate, rCandidateB.getB3DPolygon(a), rfSmallValue))
531cdf0e10cSrcweir 					return false;
532cdf0e10cSrcweir 			}
533cdf0e10cSrcweir 
534cdf0e10cSrcweir 			return true;
535cdf0e10cSrcweir 		}
536cdf0e10cSrcweir 
537cdf0e10cSrcweir 		bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB)
538cdf0e10cSrcweir 		{
539cdf0e10cSrcweir 			const double fSmallValue(fTools::getSmallValue());
540cdf0e10cSrcweir 
541cdf0e10cSrcweir 			return equal(rCandidateA, rCandidateB, fSmallValue);
542cdf0e10cSrcweir 		}
543cdf0e10cSrcweir 
544cdf0e10cSrcweir 	} // end of namespace tools
545cdf0e10cSrcweir } // end of namespace basegfx
546cdf0e10cSrcweir 
547cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
548cdf0e10cSrcweir 
549cdf0e10cSrcweir // eof
550