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