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>
36 #include <basegfx/matrix/b3dhommatrix.hxx>
37 #include <basegfx/numeric/ftools.hxx>
38 #include <osl/mutex.hxx>
40 //////////////////////////////////////////////////////////////////////////////
46 // B3DPolyPolygon tools
47 B3DRange
getRange(const B3DPolyPolygon
& rCandidate
)
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
));
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
));
80 pLineTarget
? &aLineTarget
: 0,
81 pGapTarget
? &aGapTarget
: 0,
86 pLineTarget
->append(aLineTarget
);
91 pGapTarget
->append(aGapTarget
);
97 B3DPolyPolygon
createUnitCubePolyPolygon()
99 static B3DPolyPolygon aRetval
;
100 ::osl::Mutex m_mutex
;
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
);
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
);
121 aTemp
.append(B3DPoint(0.0, 0.0, 0.0));
122 aTemp
.append(B3DPoint(0.0, 0.0, 1.0));
123 aRetval
.append(aTemp
);
126 aTemp
.append(B3DPoint(0.0, 1.0, 0.0));
127 aTemp
.append(B3DPoint(0.0, 1.0, 1.0));
128 aRetval
.append(aTemp
);
131 aTemp
.append(B3DPoint(1.0, 1.0, 0.0));
132 aTemp
.append(B3DPoint(1.0, 1.0, 1.0));
133 aRetval
.append(aTemp
);
136 aTemp
.append(B3DPoint(1.0, 0.0, 0.0));
137 aTemp
.append(B3DPoint(1.0, 0.0, 1.0));
138 aRetval
.append(aTemp
);
144 B3DPolyPolygon
createUnitCubeFillPolyPolygon()
146 static B3DPolyPolygon aRetval
;
147 ::osl::Mutex m_mutex
;
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);
168 aTemp
.setClosed(true);
169 aRetval
.append(aTemp
);
177 aTemp
.setClosed(true);
178 aRetval
.append(aTemp
);
186 aTemp
.setClosed(true);
187 aRetval
.append(aTemp
);
195 aTemp
.setClosed(true);
196 aRetval
.append(aTemp
);
204 aTemp
.setClosed(true);
205 aRetval
.append(aTemp
);
213 aTemp
.setClosed(true);
214 aRetval
.append(aTemp
);
220 B3DPolyPolygon
createCubePolyPolygonFromB3DRange( const B3DRange
& rRange
)
222 B3DPolyPolygon aRetval
;
224 if(!rRange
.isEmpty())
226 aRetval
= createUnitCubePolyPolygon();
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();
237 B3DPolyPolygon
createCubeFillPolyPolygonFromB3DRange( const B3DRange
& rRange
)
239 B3DPolyPolygon aRetval
;
241 if(!rRange
.isEmpty())
243 aRetval
= createUnitCubeFillPolyPolygon();
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();
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
;
272 nHorSeg
= fround(fabs(fHorStop
- fHorStart
) / (F_2PI
/ 24.0));
282 nVerSeg
= fround(fabs(fVerStop
- fVerStart
) / (F_2PI
/ 24.0));
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
));
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
));
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
));
336 aNew
.append(B3DPoint(0.0, -1.0, 0.0));
339 aRetval
.append(aNew
);
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
));
354 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
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
);
365 B3DPolyPolygon
createUnitSphereFillPolyPolygon(
366 sal_uInt32 nHorSeg
, sal_uInt32 nVerSeg
,
368 double fVerStart
, double fVerStop
,
369 double fHorStart
, double fHorStop
)
371 B3DPolyPolygon aRetval
;
375 nHorSeg
= fround(fabs(fHorStop
- fHorStart
) / (F_2PI
/ 24.0));
385 nVerSeg
= fround(fabs(fVerStop
- fVerStart
) / (F_2PI
/ 24.0));
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
));
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
));
406 aNew
.append(getPointFromCartesian(fHor
, fVer
));
407 aNew
.append(getPointFromCartesian(fHor2
, fVer
));
408 aNew
.append(getPointFromCartesian(fHor2
, fVer2
));
409 aNew
.append(getPointFromCartesian(fHor
, fVer2
));
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
);
427 B3DPolyPolygon
createSphereFillPolyPolygonFromB3DRange( const B3DRange
& rRange
,
428 sal_uInt32 nHorSeg
, sal_uInt32 nVerSeg
,
430 double fVerStart
, double fVerStop
,
431 double fHorStart
, double fHorStop
)
433 B3DPolyPolygon
aRetval(createUnitSphereFillPolyPolygon(nHorSeg
, nVerSeg
, bNormals
, fVerStart
, fVerStop
, fHorStart
, fHorStop
));
437 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
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
);
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
));
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
)));
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
));
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
));
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
);
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
));
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())
533 for(sal_uInt32
a(0); a
< nPolygonCount
; a
++)
535 const B3DPolygon
aCandidate(rCandidateA
.getB3DPolygon(a
));
537 if(!equal(aCandidate
, rCandidateB
.getB3DPolygon(a
), rfSmallValue
))
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 //////////////////////////////////////////////////////////////////////////////