1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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>
39 #include <basegfx/matrix/b3dhommatrix.hxx>
40 #include <basegfx/numeric/ftools.hxx>
41 #include <osl/mutex.hxx>
43 //////////////////////////////////////////////////////////////////////////////
49 // B3DPolyPolygon tools
50 B3DRange
getRange(const B3DPolyPolygon
& rCandidate
)
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
));
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
));
83 pLineTarget
? &aLineTarget
: 0,
84 pGapTarget
? &aGapTarget
: 0,
89 pLineTarget
->append(aLineTarget
);
94 pGapTarget
->append(aGapTarget
);
100 B3DPolyPolygon
createUnitCubePolyPolygon()
102 static B3DPolyPolygon aRetval
;
103 ::osl::Mutex m_mutex
;
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
);
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
);
124 aTemp
.append(B3DPoint(0.0, 0.0, 0.0));
125 aTemp
.append(B3DPoint(0.0, 0.0, 1.0));
126 aRetval
.append(aTemp
);
129 aTemp
.append(B3DPoint(0.0, 1.0, 0.0));
130 aTemp
.append(B3DPoint(0.0, 1.0, 1.0));
131 aRetval
.append(aTemp
);
134 aTemp
.append(B3DPoint(1.0, 1.0, 0.0));
135 aTemp
.append(B3DPoint(1.0, 1.0, 1.0));
136 aRetval
.append(aTemp
);
139 aTemp
.append(B3DPoint(1.0, 0.0, 0.0));
140 aTemp
.append(B3DPoint(1.0, 0.0, 1.0));
141 aRetval
.append(aTemp
);
147 B3DPolyPolygon
createUnitCubeFillPolyPolygon()
149 static B3DPolyPolygon aRetval
;
150 ::osl::Mutex m_mutex
;
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);
171 aTemp
.setClosed(true);
172 aRetval
.append(aTemp
);
180 aTemp
.setClosed(true);
181 aRetval
.append(aTemp
);
189 aTemp
.setClosed(true);
190 aRetval
.append(aTemp
);
198 aTemp
.setClosed(true);
199 aRetval
.append(aTemp
);
207 aTemp
.setClosed(true);
208 aRetval
.append(aTemp
);
216 aTemp
.setClosed(true);
217 aRetval
.append(aTemp
);
223 B3DPolyPolygon
createCubePolyPolygonFromB3DRange( const B3DRange
& rRange
)
225 B3DPolyPolygon aRetval
;
227 if(!rRange
.isEmpty())
229 aRetval
= createUnitCubePolyPolygon();
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();
240 B3DPolyPolygon
createCubeFillPolyPolygonFromB3DRange( const B3DRange
& rRange
)
242 B3DPolyPolygon aRetval
;
244 if(!rRange
.isEmpty())
246 aRetval
= createUnitCubeFillPolyPolygon();
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();
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
;
275 nHorSeg
= fround(fabs(fHorStop
- fHorStart
) / (F_2PI
/ 24.0));
285 nVerSeg
= fround(fabs(fVerStop
- fVerStart
) / (F_2PI
/ 24.0));
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
));
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
));
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
));
339 aNew
.append(B3DPoint(0.0, -1.0, 0.0));
342 aRetval
.append(aNew
);
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
));
357 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
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
);
368 B3DPolyPolygon
createUnitSphereFillPolyPolygon(
369 sal_uInt32 nHorSeg
, sal_uInt32 nVerSeg
,
371 double fVerStart
, double fVerStop
,
372 double fHorStart
, double fHorStop
)
374 B3DPolyPolygon aRetval
;
378 nHorSeg
= fround(fabs(fHorStop
- fHorStart
) / (F_2PI
/ 24.0));
388 nVerSeg
= fround(fabs(fVerStop
- fVerStart
) / (F_2PI
/ 24.0));
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
));
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
));
409 aNew
.append(getPointFromCartesian(fHor
, fVer
));
410 aNew
.append(getPointFromCartesian(fHor2
, fVer
));
411 aNew
.append(getPointFromCartesian(fHor2
, fVer2
));
412 aNew
.append(getPointFromCartesian(fHor
, fVer2
));
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
);
430 B3DPolyPolygon
createSphereFillPolyPolygonFromB3DRange( const B3DRange
& rRange
,
431 sal_uInt32 nHorSeg
, sal_uInt32 nVerSeg
,
433 double fVerStart
, double fVerStop
,
434 double fHorStart
, double fHorStop
)
436 B3DPolyPolygon
aRetval(createUnitSphereFillPolyPolygon(nHorSeg
, nVerSeg
, bNormals
, fVerStart
, fVerStop
, fHorStart
, fHorStop
));
440 // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions
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
);
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
));
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
)));
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
));
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
));
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
);
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
));
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())
536 for(sal_uInt32
a(0); a
< nPolygonCount
; a
++)
538 const B3DPolygon
aCandidate(rCandidateA
.getB3DPolygon(a
));
540 if(!equal(aCandidate
, rCandidateB
.getB3DPolygon(a
), rfSmallValue
))
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 //////////////////////////////////////////////////////////////////////////////