fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / basegfx / source / polygon / b3dpolypolygontools.cxx
blobdd7fa412235ec62fd27ed5fbb63107f00039b7fe
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <rtl/instance.hxx>
21 #include <basegfx/polygon/b3dpolypolygontools.hxx>
22 #include <basegfx/range/b3drange.hxx>
23 #include <basegfx/polygon/b3dpolypolygon.hxx>
24 #include <basegfx/polygon/b3dpolygon.hxx>
25 #include <basegfx/polygon/b3dpolygontools.hxx>
26 #include <numeric>
27 #include <basegfx/matrix/b3dhommatrix.hxx>
28 #include <basegfx/numeric/ftools.hxx>
30 //////////////////////////////////////////////////////////////////////////////
31 // predefines
32 #define nMinSegments sal_uInt32(1)
33 #define nMaxSegments sal_uInt32(512)
35 //////////////////////////////////////////////////////////////////////////////
37 namespace basegfx
39 namespace tools
41 // B3DPolyPolygon tools
42 B3DRange getRange(const B3DPolyPolygon& rCandidate)
44 B3DRange aRetval;
45 const sal_uInt32 nPolygonCount(rCandidate.count());
47 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
49 B3DPolygon aCandidate = rCandidate.getB3DPolygon(a);
50 aRetval.expand(getRange(aCandidate));
53 return aRetval;
56 namespace
58 struct theUnitCubePolyPolygon : public rtl::StaticWithInit<B3DPolyPolygon,
59 theUnitCubePolyPolygon>
61 B3DPolyPolygon operator()()
63 B3DPolyPolygon aRetval;
64 B3DPolygon aTemp;
65 aTemp.append(B3DPoint(0.0, 0.0, 1.0));
66 aTemp.append(B3DPoint(0.0, 1.0, 1.0));
67 aTemp.append(B3DPoint(1.0, 1.0, 1.0));
68 aTemp.append(B3DPoint(1.0, 0.0, 1.0));
69 aTemp.setClosed(true);
70 aRetval.append(aTemp);
72 aTemp.clear();
73 aTemp.append(B3DPoint(0.0, 0.0, 0.0));
74 aTemp.append(B3DPoint(0.0, 1.0, 0.0));
75 aTemp.append(B3DPoint(1.0, 1.0, 0.0));
76 aTemp.append(B3DPoint(1.0, 0.0, 0.0));
77 aTemp.setClosed(true);
78 aRetval.append(aTemp);
80 aTemp.clear();
81 aTemp.append(B3DPoint(0.0, 0.0, 0.0));
82 aTemp.append(B3DPoint(0.0, 0.0, 1.0));
83 aRetval.append(aTemp);
85 aTemp.clear();
86 aTemp.append(B3DPoint(0.0, 1.0, 0.0));
87 aTemp.append(B3DPoint(0.0, 1.0, 1.0));
88 aRetval.append(aTemp);
90 aTemp.clear();
91 aTemp.append(B3DPoint(1.0, 1.0, 0.0));
92 aTemp.append(B3DPoint(1.0, 1.0, 1.0));
93 aRetval.append(aTemp);
95 aTemp.clear();
96 aTemp.append(B3DPoint(1.0, 0.0, 0.0));
97 aTemp.append(B3DPoint(1.0, 0.0, 1.0));
98 aRetval.append(aTemp);
99 return aRetval;
104 B3DPolyPolygon createUnitCubePolyPolygon()
106 return theUnitCubePolyPolygon::get();
109 namespace
111 struct theUnitCubeFillPolyPolygon : public rtl::StaticWithInit<B3DPolyPolygon,
112 theUnitCubeFillPolyPolygon>
114 B3DPolyPolygon operator()()
116 B3DPolyPolygon aRetval;
117 B3DPolygon aTemp;
119 // all points
120 const B3DPoint A(0.0, 0.0, 0.0);
121 const B3DPoint B(0.0, 1.0, 0.0);
122 const B3DPoint C(1.0, 1.0, 0.0);
123 const B3DPoint D(1.0, 0.0, 0.0);
124 const B3DPoint E(0.0, 0.0, 1.0);
125 const B3DPoint F(0.0, 1.0, 1.0);
126 const B3DPoint G(1.0, 1.0, 1.0);
127 const B3DPoint H(1.0, 0.0, 1.0);
129 // create bottom
130 aTemp.append(D);
131 aTemp.append(A);
132 aTemp.append(E);
133 aTemp.append(H);
134 aTemp.setClosed(true);
135 aRetval.append(aTemp);
137 // create front
138 aTemp.clear();
139 aTemp.append(B);
140 aTemp.append(A);
141 aTemp.append(D);
142 aTemp.append(C);
143 aTemp.setClosed(true);
144 aRetval.append(aTemp);
146 // create left
147 aTemp.clear();
148 aTemp.append(E);
149 aTemp.append(A);
150 aTemp.append(B);
151 aTemp.append(F);
152 aTemp.setClosed(true);
153 aRetval.append(aTemp);
155 // create top
156 aTemp.clear();
157 aTemp.append(C);
158 aTemp.append(G);
159 aTemp.append(F);
160 aTemp.append(B);
161 aTemp.setClosed(true);
162 aRetval.append(aTemp);
164 // create right
165 aTemp.clear();
166 aTemp.append(H);
167 aTemp.append(G);
168 aTemp.append(C);
169 aTemp.append(D);
170 aTemp.setClosed(true);
171 aRetval.append(aTemp);
173 // create back
174 aTemp.clear();
175 aTemp.append(F);
176 aTemp.append(G);
177 aTemp.append(H);
178 aTemp.append(E);
179 aTemp.setClosed(true);
180 aRetval.append(aTemp);
181 return aRetval;
186 B3DPolyPolygon createUnitCubeFillPolyPolygon()
188 return theUnitCubeFillPolyPolygon::get();
191 B3DPolyPolygon createCubePolyPolygonFromB3DRange( const B3DRange& rRange)
193 B3DPolyPolygon aRetval;
195 if(!rRange.isEmpty())
197 aRetval = createUnitCubePolyPolygon();
198 B3DHomMatrix aTrans;
199 aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
200 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
201 aRetval.transform(aTrans);
202 aRetval.removeDoublePoints();
205 return aRetval;
208 B3DPolyPolygon createCubeFillPolyPolygonFromB3DRange( const B3DRange& rRange)
210 B3DPolyPolygon aRetval;
212 if(!rRange.isEmpty())
214 aRetval = createUnitCubeFillPolyPolygon();
215 B3DHomMatrix aTrans;
216 aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth());
217 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
218 aRetval.transform(aTrans);
219 aRetval.removeDoublePoints();
222 return aRetval;
225 // helper for getting the 3D Point from given cartesian coordiantes. fVer is defined from
226 // [F_PI2 .. -F_PI2], fHor from [0.0 .. F_2PI]
227 inline B3DPoint getPointFromCartesian(double fVer, double fHor)
229 const double fCosHor(cos(fHor));
230 return B3DPoint(fCosHor * cos(fVer), sin(fHor), fCosHor * -sin(fVer));
233 B3DPolyPolygon createUnitSpherePolyPolygon(
234 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
235 double fVerStart, double fVerStop,
236 double fHorStart, double fHorStop)
238 B3DPolyPolygon aRetval;
239 sal_uInt32 a, b;
241 if(!nHorSeg)
243 nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
246 // min/max limitations
247 nHorSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nHorSeg));
249 if(!nVerSeg)
251 nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
254 // min/max limitations
255 nVerSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nVerSeg));
257 // create constants
258 const double fVerDiffPerStep((fVerStop - fVerStart) / (double)nVerSeg);
259 const double fHorDiffPerStep((fHorStop - fHorStart) / (double)nHorSeg);
260 bool bHorClosed(fTools::equal(fHorStop - fHorStart, F_2PI));
261 bool bVerFromTop(fTools::equal(fVerStart, F_PI2));
262 bool bVerToBottom(fTools::equal(fVerStop, -F_PI2));
264 // create horizontal rings
265 const sal_uInt32 nLoopVerInit(bVerFromTop ? 1L : 0L);
266 const sal_uInt32 nLoopVerLimit(bVerToBottom ? nVerSeg : nVerSeg + 1L);
267 const sal_uInt32 nLoopHorLimit(bHorClosed ? nHorSeg : nHorSeg + 1L);
269 for(a = nLoopVerInit; a < nLoopVerLimit; a++)
271 const double fVer(fVerStart + ((double)(a) * fVerDiffPerStep));
272 B3DPolygon aNew;
274 for(b = 0L; b < nLoopHorLimit; b++)
276 const double fHor(fHorStart + ((double)(b) * fHorDiffPerStep));
277 aNew.append(getPointFromCartesian(fHor, fVer));
280 aNew.setClosed(bHorClosed);
281 aRetval.append(aNew);
284 // create vertical half-rings
285 for(a = 0L; a < nLoopHorLimit; a++)
287 const double fHor(fHorStart + ((double)(a) * fHorDiffPerStep));
288 B3DPolygon aNew;
290 if(bVerFromTop)
292 aNew.append(B3DPoint(0.0, 1.0, 0.0));
295 for(b = nLoopVerInit; b < nLoopVerLimit; b++)
297 const double fVer(fVerStart + ((double)(b) * fVerDiffPerStep));
298 aNew.append(getPointFromCartesian(fHor, fVer));
301 if(bVerToBottom)
303 aNew.append(B3DPoint(0.0, -1.0, 0.0));
306 aRetval.append(aNew);
309 return aRetval;
312 B3DPolyPolygon createSpherePolyPolygonFromB3DRange( const B3DRange& rRange,
313 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
314 double fVerStart, double fVerStop,
315 double fHorStart, double fHorStop)
317 B3DPolyPolygon aRetval(createUnitSpherePolyPolygon(nHorSeg, nVerSeg, fVerStart, fVerStop, fHorStart, fHorStop));
319 if(aRetval.count())
321 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
322 B3DHomMatrix aTrans;
323 aTrans.translate(1.0, 1.0, 1.0);
324 aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
325 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
326 aRetval.transform(aTrans);
329 return aRetval;
332 B3DPolyPolygon createUnitSphereFillPolyPolygon(
333 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
334 bool bNormals,
335 double fVerStart, double fVerStop,
336 double fHorStart, double fHorStop)
338 B3DPolyPolygon aRetval;
340 if(!nHorSeg)
342 nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
345 // min/max limitations
346 nHorSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nHorSeg));
348 if(!nVerSeg)
350 nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
353 // min/max limitations
354 nVerSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nVerSeg));
356 // vertical loop
357 for(sal_uInt32 a(0L); a < nVerSeg; a++)
359 const double fVer(fVerStart + (((fVerStop - fVerStart) * a) / nVerSeg));
360 const double fVer2(fVerStart + (((fVerStop - fVerStart) * (a + 1)) / nVerSeg));
362 // horizontal loop
363 for(sal_uInt32 b(0L); b < nHorSeg; b++)
365 const double fHor(fHorStart + (((fHorStop - fHorStart) * b) / nHorSeg));
366 const double fHor2(fHorStart + (((fHorStop - fHorStart) * (b + 1)) / nHorSeg));
367 B3DPolygon aNew;
369 aNew.append(getPointFromCartesian(fHor, fVer));
370 aNew.append(getPointFromCartesian(fHor2, fVer));
371 aNew.append(getPointFromCartesian(fHor2, fVer2));
372 aNew.append(getPointFromCartesian(fHor, fVer2));
374 if(bNormals)
376 for(sal_uInt32 c(0L); c < aNew.count(); c++)
378 aNew.setNormal(c, ::basegfx::B3DVector(aNew.getB3DPoint(c)));
382 aNew.setClosed(true);
383 aRetval.append(aNew);
387 return aRetval;
390 B3DPolyPolygon createSphereFillPolyPolygonFromB3DRange( const B3DRange& rRange,
391 sal_uInt32 nHorSeg, sal_uInt32 nVerSeg,
392 bool bNormals,
393 double fVerStart, double fVerStop,
394 double fHorStart, double fHorStop)
396 B3DPolyPolygon aRetval(createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, bNormals, fVerStart, fVerStop, fHorStart, fHorStop));
398 if(aRetval.count())
400 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
401 B3DHomMatrix aTrans;
402 aTrans.translate(1.0, 1.0, 1.0);
403 aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0);
404 aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ());
405 aRetval.transform(aTrans);
408 return aRetval;
411 B3DPolyPolygon applyDefaultNormalsSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter)
413 B3DPolyPolygon aRetval;
415 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
417 aRetval.append(applyDefaultNormalsSphere(rCandidate.getB3DPolygon(a), rCenter));
420 return aRetval;
423 B3DPolyPolygon invertNormals( const B3DPolyPolygon& rCandidate)
425 B3DPolyPolygon aRetval;
427 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
429 aRetval.append(invertNormals(rCandidate.getB3DPolygon(a)));
432 return aRetval;
435 B3DPolyPolygon applyDefaultTextureCoordinatesParallel( const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bChangeX, bool bChangeY)
437 B3DPolyPolygon aRetval;
439 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
441 aRetval.append(applyDefaultTextureCoordinatesParallel(rCandidate.getB3DPolygon(a), rRange, bChangeX, bChangeY));
444 return aRetval;
447 B3DPolyPolygon applyDefaultTextureCoordinatesSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX, bool bChangeY)
449 B3DPolyPolygon aRetval;
451 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
453 aRetval.append(applyDefaultTextureCoordinatesSphere(rCandidate.getB3DPolygon(a), rCenter, bChangeX, bChangeY));
456 return aRetval;
459 bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder)
461 const sal_uInt32 nPolygonCount(rCandidate.count());
463 if(1L == nPolygonCount)
465 return isInside(rCandidate.getB3DPolygon(0), rPoint, bWithBorder);
467 else
469 sal_Int32 nInsideCount(0);
471 for(sal_uInt32 a(0); a < nPolygonCount; a++)
473 const B3DPolygon aPolygon(rCandidate.getB3DPolygon(a));
474 const bool bInside(isInside(aPolygon, rPoint, bWithBorder));
476 if(bInside)
478 nInsideCount++;
482 return (nInsideCount % 2L);
486 } // end of namespace tools
487 } // end of namespace basegfx
489 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */