merge the formfield patch from ooo-build
[ooovba.git] / basegfx / source / polygon / b3dpolypolygontools.cxx
blob76ec8ae50e49ee63385d19fefbff7fe65c061dcc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: b3dpolypolygontools.cxx,v $
10 * $Revision: 1.8.4.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basegfx.hxx"
33 #include <basegfx/polygon/b3dpolypolygontools.hxx>
34 #include <basegfx/range/b3drange.hxx>
35 #include <basegfx/polygon/b3dpolypolygon.hxx>
36 #include <basegfx/polygon/b3dpolygon.hxx>
37 #include <basegfx/polygon/b3dpolygontools.hxx>
38 #include <numeric>
39 #include <basegfx/matrix/b3dhommatrix.hxx>
40 #include <basegfx/numeric/ftools.hxx>
41 #include <osl/mutex.hxx>
43 //////////////////////////////////////////////////////////////////////////////
45 namespace basegfx
47 namespace tools
49 // B3DPolyPolygon tools
50 B3DRange getRange(const B3DPolyPolygon& rCandidate)
52 B3DRange aRetval;
53 const sal_uInt32 nPolygonCount(rCandidate.count());
55 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
57 B3DPolygon aCandidate = rCandidate.getB3DPolygon(a);
58 aRetval.expand(getRange(aCandidate));
61 return aRetval;
64 void applyLineDashing(const B3DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B3DPolyPolygon* pLineTarget, B3DPolyPolygon* pGapTarget, double fFullDashDotLen)
66 if(0.0 == fFullDashDotLen && rDotDashArray.size())
68 // calculate fFullDashDotLen from rDotDashArray
69 fFullDashDotLen = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
72 if(rCandidate.count() && fFullDashDotLen > 0.0)
74 B3DPolyPolygon aLineTarget, aGapTarget;
76 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
78 const B3DPolygon aCandidate(rCandidate.getB3DPolygon(a));
80 applyLineDashing(
81 aCandidate,
82 rDotDashArray,
83 pLineTarget ? &aLineTarget : 0,
84 pGapTarget ? &aGapTarget : 0,
85 fFullDashDotLen);
87 if(pLineTarget)
89 pLineTarget->append(aLineTarget);
92 if(pGapTarget)
94 pGapTarget->append(aGapTarget);
100 B3DPolyPolygon createUnitCubePolyPolygon()
102 static B3DPolyPolygon aRetval;
103 ::osl::Mutex m_mutex;
105 if(!aRetval.count())
107 B3DPolygon aTemp;
108 aTemp.append(B3DPoint(0.0, 0.0, 1.0));
109 aTemp.append(B3DPoint(0.0, 1.0, 1.0));
110 aTemp.append(B3DPoint(1.0, 1.0, 1.0));
111 aTemp.append(B3DPoint(1.0, 0.0, 1.0));
112 aTemp.setClosed(true);
113 aRetval.append(aTemp);
115 aTemp.clear();
116 aTemp.append(B3DPoint(0.0, 0.0, 0.0));
117 aTemp.append(B3DPoint(0.0, 1.0, 0.0));
118 aTemp.append(B3DPoint(1.0, 1.0, 0.0));
119 aTemp.append(B3DPoint(1.0, 0.0, 0.0));
120 aTemp.setClosed(true);
121 aRetval.append(aTemp);
123 aTemp.clear();
124 aTemp.append(B3DPoint(0.0, 0.0, 0.0));
125 aTemp.append(B3DPoint(0.0, 0.0, 1.0));
126 aRetval.append(aTemp);
128 aTemp.clear();
129 aTemp.append(B3DPoint(0.0, 1.0, 0.0));
130 aTemp.append(B3DPoint(0.0, 1.0, 1.0));
131 aRetval.append(aTemp);
133 aTemp.clear();
134 aTemp.append(B3DPoint(1.0, 1.0, 0.0));
135 aTemp.append(B3DPoint(1.0, 1.0, 1.0));
136 aRetval.append(aTemp);
138 aTemp.clear();
139 aTemp.append(B3DPoint(1.0, 0.0, 0.0));
140 aTemp.append(B3DPoint(1.0, 0.0, 1.0));
141 aRetval.append(aTemp);
144 return aRetval;
147 B3DPolyPolygon createUnitCubeFillPolyPolygon()
149 static B3DPolyPolygon aRetval;
150 ::osl::Mutex m_mutex;
152 if(!aRetval.count())
154 B3DPolygon aTemp;
156 // all points
157 const B3DPoint A(0.0, 0.0, 0.0);
158 const B3DPoint B(0.0, 1.0, 0.0);
159 const B3DPoint C(1.0, 1.0, 0.0);
160 const B3DPoint D(1.0, 0.0, 0.0);
161 const B3DPoint E(0.0, 0.0, 1.0);
162 const B3DPoint F(0.0, 1.0, 1.0);
163 const B3DPoint G(1.0, 1.0, 1.0);
164 const B3DPoint H(1.0, 0.0, 1.0);
166 // create bottom
167 aTemp.append(D);
168 aTemp.append(A);
169 aTemp.append(E);
170 aTemp.append(H);
171 aTemp.setClosed(true);
172 aRetval.append(aTemp);
174 // create front
175 aTemp.clear();
176 aTemp.append(B);
177 aTemp.append(A);
178 aTemp.append(D);
179 aTemp.append(C);
180 aTemp.setClosed(true);
181 aRetval.append(aTemp);
183 // create left
184 aTemp.clear();
185 aTemp.append(E);
186 aTemp.append(A);
187 aTemp.append(B);
188 aTemp.append(F);
189 aTemp.setClosed(true);
190 aRetval.append(aTemp);
192 // create top
193 aTemp.clear();
194 aTemp.append(C);
195 aTemp.append(G);
196 aTemp.append(F);
197 aTemp.append(B);
198 aTemp.setClosed(true);
199 aRetval.append(aTemp);
201 // create right
202 aTemp.clear();
203 aTemp.append(H);
204 aTemp.append(G);
205 aTemp.append(C);
206 aTemp.append(D);
207 aTemp.setClosed(true);
208 aRetval.append(aTemp);
210 // create back
211 aTemp.clear();
212 aTemp.append(F);
213 aTemp.append(G);
214 aTemp.append(H);
215 aTemp.append(E);
216 aTemp.setClosed(true);
217 aRetval.append(aTemp);
220 return aRetval;
223 B3DPolyPolygon createCubePolyPolygonFromB3DRange( const B3DRange& rRange)
225 B3DPolyPolygon aRetval;
227 if(!rRange.isEmpty())
229 aRetval = createUnitCubePolyPolygon();
230 B3DHomMatrix aTrans;
231 aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
232 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
233 aRetval.transform(aTrans);
234 aRetval.removeDoublePoints();
237 return aRetval;
240 B3DPolyPolygon createCubeFillPolyPolygonFromB3DRange( const B3DRange& rRange)
242 B3DPolyPolygon aRetval;
244 if(!rRange.isEmpty())
246 aRetval = createUnitCubeFillPolyPolygon();
247 B3DHomMatrix aTrans;
248 aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
249 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
250 aRetval.transform(aTrans);
251 aRetval.removeDoublePoints();
254 return aRetval;
257 // helper for getting the 3D Point from given cartesian coordiantes. fVer is defined from
258 // [F_PI2 .. -F_PI2], fHor from [0.0 .. F_2PI]
259 inline B3DPoint getPointFromCartesian(double fVer, double fHor)
261 const double fCosHor(cos(fHor));
262 return B3DPoint(fCosHor * cos(fVer), sin(fHor), fCosHor * -sin(fVer));
265 B3DPolyPolygon createUnitSpherePolyPolygon(
266 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
267 double fVerStart, double fVerStop,
268 double fHorStart, double fHorStop)
270 B3DPolyPolygon aRetval;
271 sal_uInt32 a, b;
273 if(!nHorSeg)
275 nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
278 if(!nHorSeg)
280 nHorSeg = 1L;
283 if(!nVerSeg)
285 nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
288 if(!nVerSeg)
290 nVerSeg = 1L;
293 // create constants
294 const double fVerDiffPerStep((fVerStop - fVerStart) / (double)nVerSeg);
295 const double fHorDiffPerStep((fHorStop - fHorStart) / (double)nHorSeg);
296 bool bHorClosed(fTools::equal(fHorStop - fHorStart, F_2PI));
297 bool bVerFromTop(fTools::equal(fVerStart, F_PI2));
298 bool bVerToBottom(fTools::equal(fVerStop, -F_PI2));
300 // create horizontal rings
301 const sal_uInt32 nLoopVerInit(bVerFromTop ? 1L : 0L);
302 const sal_uInt32 nLoopVerLimit(bVerToBottom ? nVerSeg : nVerSeg + 1L);
303 const sal_uInt32 nLoopHorLimit(bHorClosed ? nHorSeg : nHorSeg + 1L);
305 for(a = nLoopVerInit; a < nLoopVerLimit; a++)
307 const double fVer(fVerStart + ((double)(a) * fVerDiffPerStep));
308 B3DPolygon aNew;
310 for(b = 0L; b < nLoopHorLimit; b++)
312 const double fHor(fHorStart + ((double)(b) * fHorDiffPerStep));
313 aNew.append(getPointFromCartesian(fHor, fVer));
316 aNew.setClosed(bHorClosed);
317 aRetval.append(aNew);
320 // create vertical half-rings
321 for(a = 0L; a < nLoopHorLimit; a++)
323 const double fHor(fHorStart + ((double)(a) * fHorDiffPerStep));
324 B3DPolygon aNew;
326 if(bVerFromTop)
328 aNew.append(B3DPoint(0.0, 1.0, 0.0));
331 for(b = nLoopVerInit; b < nLoopVerLimit; b++)
333 const double fVer(fVerStart + ((double)(b) * fVerDiffPerStep));
334 aNew.append(getPointFromCartesian(fHor, fVer));
337 if(bVerToBottom)
339 aNew.append(B3DPoint(0.0, -1.0, 0.0));
342 aRetval.append(aNew);
345 return aRetval;
348 B3DPolyPolygon createSpherePolyPolygonFromB3DRange( const B3DRange& rRange,
349 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
350 double fVerStart, double fVerStop,
351 double fHorStart, double fHorStop)
353 B3DPolyPolygon aRetval(createUnitSpherePolyPolygon(nHorSeg, nVerSeg, fVerStart, fVerStop, fHorStart, fHorStop));
355 if(aRetval.count())
357 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
358 B3DHomMatrix aTrans;
359 aTrans.translate(1.0, 1.0, 1.0);
360 aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
361 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
362 aRetval.transform(aTrans);
365 return aRetval;
368 B3DPolyPolygon createUnitSphereFillPolyPolygon(
369 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
370 bool bNormals,
371 double fVerStart, double fVerStop,
372 double fHorStart, double fHorStop)
374 B3DPolyPolygon aRetval;
376 if(!nHorSeg)
378 nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
381 if(!nHorSeg)
383 nHorSeg = 1L;
386 if(!nVerSeg)
388 nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
391 if(!nVerSeg)
393 nVerSeg = 1L;
396 // vertical loop
397 for(sal_uInt32 a(0L); a < nVerSeg; a++)
399 const double fVer(fVerStart + (((fVerStop - fVerStart) * a) / nVerSeg));
400 const double fVer2(fVerStart + (((fVerStop - fVerStart) * (a + 1)) / nVerSeg));
402 // horizontal loop
403 for(sal_uInt32 b(0L); b < nHorSeg; b++)
405 const double fHor(fHorStart + (((fHorStop - fHorStart) * b) / nHorSeg));
406 const double fHor2(fHorStart + (((fHorStop - fHorStart) * (b + 1)) / nHorSeg));
407 B3DPolygon aNew;
409 aNew.append(getPointFromCartesian(fHor, fVer));
410 aNew.append(getPointFromCartesian(fHor2, fVer));
411 aNew.append(getPointFromCartesian(fHor2, fVer2));
412 aNew.append(getPointFromCartesian(fHor, fVer2));
414 if(bNormals)
416 for(sal_uInt32 c(0L); c < aNew.count(); c++)
418 aNew.setNormal(c, ::basegfx::B3DVector(aNew.getB3DPoint(c)));
422 aNew.setClosed(true);
423 aRetval.append(aNew);
427 return aRetval;
430 B3DPolyPolygon createSphereFillPolyPolygonFromB3DRange( const B3DRange& rRange,
431 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
432 bool bNormals,
433 double fVerStart, double fVerStop,
434 double fHorStart, double fHorStop)
436 B3DPolyPolygon aRetval(createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, bNormals, fVerStart, fVerStop, fHorStart, fHorStop));
438 if(aRetval.count())
440 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
441 B3DHomMatrix aTrans;
442 aTrans.translate(1.0, 1.0, 1.0);
443 aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
444 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
445 aRetval.transform(aTrans);
448 return aRetval;
451 B3DPolyPolygon applyDefaultNormalsSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter)
453 B3DPolyPolygon aRetval;
455 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
457 aRetval.append(applyDefaultNormalsSphere(rCandidate.getB3DPolygon(a), rCenter));
460 return aRetval;
463 B3DPolyPolygon invertNormals( const B3DPolyPolygon& rCandidate)
465 B3DPolyPolygon aRetval;
467 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
469 aRetval.append(invertNormals(rCandidate.getB3DPolygon(a)));
472 return aRetval;
475 B3DPolyPolygon applyDefaultTextureCoordinatesParallel( const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bChangeX, bool bChangeY)
477 B3DPolyPolygon aRetval;
479 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
481 aRetval.append(applyDefaultTextureCoordinatesParallel(rCandidate.getB3DPolygon(a), rRange, bChangeX, bChangeY));
484 return aRetval;
487 B3DPolyPolygon applyDefaultTextureCoordinatesSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX, bool bChangeY)
489 B3DPolyPolygon aRetval;
491 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
493 aRetval.append(applyDefaultTextureCoordinatesSphere(rCandidate.getB3DPolygon(a), rCenter, bChangeX, bChangeY));
496 return aRetval;
499 bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder)
501 const sal_uInt32 nPolygonCount(rCandidate.count());
503 if(1L == nPolygonCount)
505 return isInside(rCandidate.getB3DPolygon(0), rPoint, bWithBorder);
507 else
509 sal_Int32 nInsideCount(0);
511 for(sal_uInt32 a(0); a < nPolygonCount; a++)
513 const B3DPolygon aPolygon(rCandidate.getB3DPolygon(a));
514 const bool bInside(isInside(aPolygon, rPoint, bWithBorder));
516 if(bInside)
518 nInsideCount++;
522 return (nInsideCount % 2L);
526 //////////////////////////////////////////////////////////////////////
527 // comparators with tolerance for 3D PolyPolygons
529 bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB, const double& rfSmallValue)
531 const sal_uInt32 nPolygonCount(rCandidateA.count());
533 if(nPolygonCount != rCandidateB.count())
534 return false;
536 for(sal_uInt32 a(0); a < nPolygonCount; a++)
538 const B3DPolygon aCandidate(rCandidateA.getB3DPolygon(a));
540 if(!equal(aCandidate, rCandidateB.getB3DPolygon(a), rfSmallValue))
541 return false;
544 return true;
547 bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB)
549 const double fSmallValue(fTools::getSmallValue());
551 return equal(rCandidateA, rCandidateB, fSmallValue);
554 } // end of namespace tools
555 } // end of namespace basegfx
557 //////////////////////////////////////////////////////////////////////////////
559 // eof