merged tag ooo/OOO330_m14
[LibreOffice.git] / basegfx / source / polygon / b3dpolypolygontools.cxx
blobd86a4526acfd76f90cad0a26c0c7c2d1475c4967
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basegfx.hxx"
30 #include <basegfx/polygon/b3dpolypolygontools.hxx>
31 #include <basegfx/range/b3drange.hxx>
32 #include <basegfx/polygon/b3dpolypolygon.hxx>
33 #include <basegfx/polygon/b3dpolygon.hxx>
34 #include <basegfx/polygon/b3dpolygontools.hxx>
35 #include <numeric>
36 #include <basegfx/matrix/b3dhommatrix.hxx>
37 #include <basegfx/numeric/ftools.hxx>
38 #include <osl/mutex.hxx>
40 //////////////////////////////////////////////////////////////////////////////
42 namespace basegfx
44 namespace tools
46 // B3DPolyPolygon tools
47 B3DRange getRange(const B3DPolyPolygon& rCandidate)
49 B3DRange aRetval;
50 const sal_uInt32 nPolygonCount(rCandidate.count());
52 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
54 B3DPolygon aCandidate = rCandidate.getB3DPolygon(a);
55 aRetval.expand(getRange(aCandidate));
58 return aRetval;
61 void applyLineDashing(const B3DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B3DPolyPolygon* pLineTarget, B3DPolyPolygon* pGapTarget, double fFullDashDotLen)
63 if(0.0 == fFullDashDotLen && rDotDashArray.size())
65 // calculate fFullDashDotLen from rDotDashArray
66 fFullDashDotLen = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
69 if(rCandidate.count() && fFullDashDotLen > 0.0)
71 B3DPolyPolygon aLineTarget, aGapTarget;
73 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
75 const B3DPolygon aCandidate(rCandidate.getB3DPolygon(a));
77 applyLineDashing(
78 aCandidate,
79 rDotDashArray,
80 pLineTarget ? &aLineTarget : 0,
81 pGapTarget ? &aGapTarget : 0,
82 fFullDashDotLen);
84 if(pLineTarget)
86 pLineTarget->append(aLineTarget);
89 if(pGapTarget)
91 pGapTarget->append(aGapTarget);
97 B3DPolyPolygon createUnitCubePolyPolygon()
99 static B3DPolyPolygon aRetval;
100 ::osl::Mutex m_mutex;
102 if(!aRetval.count())
104 B3DPolygon aTemp;
105 aTemp.append(B3DPoint(0.0, 0.0, 1.0));
106 aTemp.append(B3DPoint(0.0, 1.0, 1.0));
107 aTemp.append(B3DPoint(1.0, 1.0, 1.0));
108 aTemp.append(B3DPoint(1.0, 0.0, 1.0));
109 aTemp.setClosed(true);
110 aRetval.append(aTemp);
112 aTemp.clear();
113 aTemp.append(B3DPoint(0.0, 0.0, 0.0));
114 aTemp.append(B3DPoint(0.0, 1.0, 0.0));
115 aTemp.append(B3DPoint(1.0, 1.0, 0.0));
116 aTemp.append(B3DPoint(1.0, 0.0, 0.0));
117 aTemp.setClosed(true);
118 aRetval.append(aTemp);
120 aTemp.clear();
121 aTemp.append(B3DPoint(0.0, 0.0, 0.0));
122 aTemp.append(B3DPoint(0.0, 0.0, 1.0));
123 aRetval.append(aTemp);
125 aTemp.clear();
126 aTemp.append(B3DPoint(0.0, 1.0, 0.0));
127 aTemp.append(B3DPoint(0.0, 1.0, 1.0));
128 aRetval.append(aTemp);
130 aTemp.clear();
131 aTemp.append(B3DPoint(1.0, 1.0, 0.0));
132 aTemp.append(B3DPoint(1.0, 1.0, 1.0));
133 aRetval.append(aTemp);
135 aTemp.clear();
136 aTemp.append(B3DPoint(1.0, 0.0, 0.0));
137 aTemp.append(B3DPoint(1.0, 0.0, 1.0));
138 aRetval.append(aTemp);
141 return aRetval;
144 B3DPolyPolygon createUnitCubeFillPolyPolygon()
146 static B3DPolyPolygon aRetval;
147 ::osl::Mutex m_mutex;
149 if(!aRetval.count())
151 B3DPolygon aTemp;
153 // all points
154 const B3DPoint A(0.0, 0.0, 0.0);
155 const B3DPoint B(0.0, 1.0, 0.0);
156 const B3DPoint C(1.0, 1.0, 0.0);
157 const B3DPoint D(1.0, 0.0, 0.0);
158 const B3DPoint E(0.0, 0.0, 1.0);
159 const B3DPoint F(0.0, 1.0, 1.0);
160 const B3DPoint G(1.0, 1.0, 1.0);
161 const B3DPoint H(1.0, 0.0, 1.0);
163 // create bottom
164 aTemp.append(D);
165 aTemp.append(A);
166 aTemp.append(E);
167 aTemp.append(H);
168 aTemp.setClosed(true);
169 aRetval.append(aTemp);
171 // create front
172 aTemp.clear();
173 aTemp.append(B);
174 aTemp.append(A);
175 aTemp.append(D);
176 aTemp.append(C);
177 aTemp.setClosed(true);
178 aRetval.append(aTemp);
180 // create left
181 aTemp.clear();
182 aTemp.append(E);
183 aTemp.append(A);
184 aTemp.append(B);
185 aTemp.append(F);
186 aTemp.setClosed(true);
187 aRetval.append(aTemp);
189 // create top
190 aTemp.clear();
191 aTemp.append(C);
192 aTemp.append(G);
193 aTemp.append(F);
194 aTemp.append(B);
195 aTemp.setClosed(true);
196 aRetval.append(aTemp);
198 // create right
199 aTemp.clear();
200 aTemp.append(H);
201 aTemp.append(G);
202 aTemp.append(C);
203 aTemp.append(D);
204 aTemp.setClosed(true);
205 aRetval.append(aTemp);
207 // create back
208 aTemp.clear();
209 aTemp.append(F);
210 aTemp.append(G);
211 aTemp.append(H);
212 aTemp.append(E);
213 aTemp.setClosed(true);
214 aRetval.append(aTemp);
217 return aRetval;
220 B3DPolyPolygon createCubePolyPolygonFromB3DRange( const B3DRange& rRange)
222 B3DPolyPolygon aRetval;
224 if(!rRange.isEmpty())
226 aRetval = createUnitCubePolyPolygon();
227 B3DHomMatrix aTrans;
228 aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
229 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
230 aRetval.transform(aTrans);
231 aRetval.removeDoublePoints();
234 return aRetval;
237 B3DPolyPolygon createCubeFillPolyPolygonFromB3DRange( const B3DRange& rRange)
239 B3DPolyPolygon aRetval;
241 if(!rRange.isEmpty())
243 aRetval = createUnitCubeFillPolyPolygon();
244 B3DHomMatrix aTrans;
245 aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
246 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
247 aRetval.transform(aTrans);
248 aRetval.removeDoublePoints();
251 return aRetval;
254 // helper for getting the 3D Point from given cartesian coordiantes. fVer is defined from
255 // [F_PI2 .. -F_PI2], fHor from [0.0 .. F_2PI]
256 inline B3DPoint getPointFromCartesian(double fVer, double fHor)
258 const double fCosHor(cos(fHor));
259 return B3DPoint(fCosHor * cos(fVer), sin(fHor), fCosHor * -sin(fVer));
262 B3DPolyPolygon createUnitSpherePolyPolygon(
263 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
264 double fVerStart, double fVerStop,
265 double fHorStart, double fHorStop)
267 B3DPolyPolygon aRetval;
268 sal_uInt32 a, b;
270 if(!nHorSeg)
272 nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
275 if(!nHorSeg)
277 nHorSeg = 1L;
280 if(!nVerSeg)
282 nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
285 if(!nVerSeg)
287 nVerSeg = 1L;
290 // create constants
291 const double fVerDiffPerStep((fVerStop - fVerStart) / (double)nVerSeg);
292 const double fHorDiffPerStep((fHorStop - fHorStart) / (double)nHorSeg);
293 bool bHorClosed(fTools::equal(fHorStop - fHorStart, F_2PI));
294 bool bVerFromTop(fTools::equal(fVerStart, F_PI2));
295 bool bVerToBottom(fTools::equal(fVerStop, -F_PI2));
297 // create horizontal rings
298 const sal_uInt32 nLoopVerInit(bVerFromTop ? 1L : 0L);
299 const sal_uInt32 nLoopVerLimit(bVerToBottom ? nVerSeg : nVerSeg + 1L);
300 const sal_uInt32 nLoopHorLimit(bHorClosed ? nHorSeg : nHorSeg + 1L);
302 for(a = nLoopVerInit; a < nLoopVerLimit; a++)
304 const double fVer(fVerStart + ((double)(a) * fVerDiffPerStep));
305 B3DPolygon aNew;
307 for(b = 0L; b < nLoopHorLimit; b++)
309 const double fHor(fHorStart + ((double)(b) * fHorDiffPerStep));
310 aNew.append(getPointFromCartesian(fHor, fVer));
313 aNew.setClosed(bHorClosed);
314 aRetval.append(aNew);
317 // create vertical half-rings
318 for(a = 0L; a < nLoopHorLimit; a++)
320 const double fHor(fHorStart + ((double)(a) * fHorDiffPerStep));
321 B3DPolygon aNew;
323 if(bVerFromTop)
325 aNew.append(B3DPoint(0.0, 1.0, 0.0));
328 for(b = nLoopVerInit; b < nLoopVerLimit; b++)
330 const double fVer(fVerStart + ((double)(b) * fVerDiffPerStep));
331 aNew.append(getPointFromCartesian(fHor, fVer));
334 if(bVerToBottom)
336 aNew.append(B3DPoint(0.0, -1.0, 0.0));
339 aRetval.append(aNew);
342 return aRetval;
345 B3DPolyPolygon createSpherePolyPolygonFromB3DRange( const B3DRange& rRange,
346 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
347 double fVerStart, double fVerStop,
348 double fHorStart, double fHorStop)
350 B3DPolyPolygon aRetval(createUnitSpherePolyPolygon(nHorSeg, nVerSeg, fVerStart, fVerStop, fHorStart, fHorStop));
352 if(aRetval.count())
354 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
355 B3DHomMatrix aTrans;
356 aTrans.translate(1.0, 1.0, 1.0);
357 aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
358 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
359 aRetval.transform(aTrans);
362 return aRetval;
365 B3DPolyPolygon createUnitSphereFillPolyPolygon(
366 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
367 bool bNormals,
368 double fVerStart, double fVerStop,
369 double fHorStart, double fHorStop)
371 B3DPolyPolygon aRetval;
373 if(!nHorSeg)
375 nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
378 if(!nHorSeg)
380 nHorSeg = 1L;
383 if(!nVerSeg)
385 nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
388 if(!nVerSeg)
390 nVerSeg = 1L;
393 // vertical loop
394 for(sal_uInt32 a(0L); a < nVerSeg; a++)
396 const double fVer(fVerStart + (((fVerStop - fVerStart) * a) / nVerSeg));
397 const double fVer2(fVerStart + (((fVerStop - fVerStart) * (a + 1)) / nVerSeg));
399 // horizontal loop
400 for(sal_uInt32 b(0L); b < nHorSeg; b++)
402 const double fHor(fHorStart + (((fHorStop - fHorStart) * b) / nHorSeg));
403 const double fHor2(fHorStart + (((fHorStop - fHorStart) * (b + 1)) / nHorSeg));
404 B3DPolygon aNew;
406 aNew.append(getPointFromCartesian(fHor, fVer));
407 aNew.append(getPointFromCartesian(fHor2, fVer));
408 aNew.append(getPointFromCartesian(fHor2, fVer2));
409 aNew.append(getPointFromCartesian(fHor, fVer2));
411 if(bNormals)
413 for(sal_uInt32 c(0L); c < aNew.count(); c++)
415 aNew.setNormal(c, ::basegfx::B3DVector(aNew.getB3DPoint(c)));
419 aNew.setClosed(true);
420 aRetval.append(aNew);
424 return aRetval;
427 B3DPolyPolygon createSphereFillPolyPolygonFromB3DRange( const B3DRange& rRange,
428 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
429 bool bNormals,
430 double fVerStart, double fVerStop,
431 double fHorStart, double fHorStop)
433 B3DPolyPolygon aRetval(createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, bNormals, fVerStart, fVerStop, fHorStart, fHorStop));
435 if(aRetval.count())
437 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
438 B3DHomMatrix aTrans;
439 aTrans.translate(1.0, 1.0, 1.0);
440 aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
441 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
442 aRetval.transform(aTrans);
445 return aRetval;
448 B3DPolyPolygon applyDefaultNormalsSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter)
450 B3DPolyPolygon aRetval;
452 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
454 aRetval.append(applyDefaultNormalsSphere(rCandidate.getB3DPolygon(a), rCenter));
457 return aRetval;
460 B3DPolyPolygon invertNormals( const B3DPolyPolygon& rCandidate)
462 B3DPolyPolygon aRetval;
464 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
466 aRetval.append(invertNormals(rCandidate.getB3DPolygon(a)));
469 return aRetval;
472 B3DPolyPolygon applyDefaultTextureCoordinatesParallel( const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bChangeX, bool bChangeY)
474 B3DPolyPolygon aRetval;
476 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
478 aRetval.append(applyDefaultTextureCoordinatesParallel(rCandidate.getB3DPolygon(a), rRange, bChangeX, bChangeY));
481 return aRetval;
484 B3DPolyPolygon applyDefaultTextureCoordinatesSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX, bool bChangeY)
486 B3DPolyPolygon aRetval;
488 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
490 aRetval.append(applyDefaultTextureCoordinatesSphere(rCandidate.getB3DPolygon(a), rCenter, bChangeX, bChangeY));
493 return aRetval;
496 bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder)
498 const sal_uInt32 nPolygonCount(rCandidate.count());
500 if(1L == nPolygonCount)
502 return isInside(rCandidate.getB3DPolygon(0), rPoint, bWithBorder);
504 else
506 sal_Int32 nInsideCount(0);
508 for(sal_uInt32 a(0); a < nPolygonCount; a++)
510 const B3DPolygon aPolygon(rCandidate.getB3DPolygon(a));
511 const bool bInside(isInside(aPolygon, rPoint, bWithBorder));
513 if(bInside)
515 nInsideCount++;
519 return (nInsideCount % 2L);
523 //////////////////////////////////////////////////////////////////////
524 // comparators with tolerance for 3D PolyPolygons
526 bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB, const double& rfSmallValue)
528 const sal_uInt32 nPolygonCount(rCandidateA.count());
530 if(nPolygonCount != rCandidateB.count())
531 return false;
533 for(sal_uInt32 a(0); a < nPolygonCount; a++)
535 const B3DPolygon aCandidate(rCandidateA.getB3DPolygon(a));
537 if(!equal(aCandidate, rCandidateB.getB3DPolygon(a), rfSmallValue))
538 return false;
541 return true;
544 bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB)
546 const double fSmallValue(fTools::getSmallValue());
548 return equal(rCandidateA, rCandidateB, fSmallValue);
551 } // end of namespace tools
552 } // end of namespace basegfx
554 //////////////////////////////////////////////////////////////////////////////
556 // eof