/src/libreoffice/basegfx/source/polygon/b3dpolypolygontools.cxx
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <basegfx/polygon/b3dpolypolygontools.hxx> |
21 | | #include <basegfx/range/b3drange.hxx> |
22 | | #include <basegfx/polygon/b3dpolypolygon.hxx> |
23 | | #include <basegfx/polygon/b3dpolygon.hxx> |
24 | | #include <basegfx/polygon/b3dpolygontools.hxx> |
25 | | #include <basegfx/matrix/b3dhommatrix.hxx> |
26 | | #include <basegfx/numeric/ftools.hxx> |
27 | | #include <com/sun/star/drawing/DoubleSequence.hpp> |
28 | | #include <com/sun/star/drawing/PolyPolygonShape3D.hpp> |
29 | | |
30 | | // predefines |
31 | 0 | #define nMinSegments sal_uInt32(1) |
32 | 0 | #define nMaxSegments sal_uInt32(512) |
33 | | |
34 | | namespace basegfx::utils |
35 | | { |
36 | | // B3DPolyPolygon tools |
37 | | B3DRange getRange(const B3DPolyPolygon& rCandidate) |
38 | 0 | { |
39 | 0 | B3DRange aRetval; |
40 | |
|
41 | 0 | for(const auto& rPolygon : rCandidate ) |
42 | 0 | { |
43 | 0 | aRetval.expand(getRange(rPolygon)); |
44 | 0 | } |
45 | |
|
46 | 0 | return aRetval; |
47 | 0 | } |
48 | | |
49 | | B3DPolyPolygon const & createUnitCubePolyPolygon() |
50 | 0 | { |
51 | 0 | static auto const singleton = [] { |
52 | 0 | B3DPolyPolygon aRetval; |
53 | 0 | B3DPolygon aTemp; |
54 | 0 | aTemp.append(B3DPoint(0.0, 0.0, 1.0)); |
55 | 0 | aTemp.append(B3DPoint(0.0, 1.0, 1.0)); |
56 | 0 | aTemp.append(B3DPoint(1.0, 1.0, 1.0)); |
57 | 0 | aTemp.append(B3DPoint(1.0, 0.0, 1.0)); |
58 | 0 | aTemp.setClosed(true); |
59 | 0 | aRetval.append(aTemp); |
60 | |
|
61 | 0 | aTemp.clear(); |
62 | 0 | aTemp.append(B3DPoint(0.0, 0.0, 0.0)); |
63 | 0 | aTemp.append(B3DPoint(0.0, 1.0, 0.0)); |
64 | 0 | aTemp.append(B3DPoint(1.0, 1.0, 0.0)); |
65 | 0 | aTemp.append(B3DPoint(1.0, 0.0, 0.0)); |
66 | 0 | aTemp.setClosed(true); |
67 | 0 | aRetval.append(aTemp); |
68 | |
|
69 | 0 | aTemp.clear(); |
70 | 0 | aTemp.append(B3DPoint(0.0, 0.0, 0.0)); |
71 | 0 | aTemp.append(B3DPoint(0.0, 0.0, 1.0)); |
72 | 0 | aRetval.append(aTemp); |
73 | |
|
74 | 0 | aTemp.clear(); |
75 | 0 | aTemp.append(B3DPoint(0.0, 1.0, 0.0)); |
76 | 0 | aTemp.append(B3DPoint(0.0, 1.0, 1.0)); |
77 | 0 | aRetval.append(aTemp); |
78 | |
|
79 | 0 | aTemp.clear(); |
80 | 0 | aTemp.append(B3DPoint(1.0, 1.0, 0.0)); |
81 | 0 | aTemp.append(B3DPoint(1.0, 1.0, 1.0)); |
82 | 0 | aRetval.append(aTemp); |
83 | |
|
84 | 0 | aTemp.clear(); |
85 | 0 | aTemp.append(B3DPoint(1.0, 0.0, 0.0)); |
86 | 0 | aTemp.append(B3DPoint(1.0, 0.0, 1.0)); |
87 | 0 | aRetval.append(aTemp); |
88 | 0 | return aRetval; |
89 | 0 | }(); |
90 | 0 | return singleton; |
91 | 0 | } |
92 | | |
93 | | B3DPolyPolygon const & createUnitCubeFillPolyPolygon() |
94 | 0 | { |
95 | 0 | static auto const singleton = [] { |
96 | 0 | B3DPolyPolygon aRetval; |
97 | 0 | B3DPolygon aTemp; |
98 | | |
99 | | // all points |
100 | 0 | const B3DPoint A(0.0, 0.0, 0.0); |
101 | 0 | const B3DPoint B(0.0, 1.0, 0.0); |
102 | 0 | const B3DPoint C(1.0, 1.0, 0.0); |
103 | 0 | const B3DPoint D(1.0, 0.0, 0.0); |
104 | 0 | const B3DPoint E(0.0, 0.0, 1.0); |
105 | 0 | const B3DPoint F(0.0, 1.0, 1.0); |
106 | 0 | const B3DPoint G(1.0, 1.0, 1.0); |
107 | 0 | const B3DPoint H(1.0, 0.0, 1.0); |
108 | | |
109 | | // create bottom |
110 | 0 | aTemp.append(D); |
111 | 0 | aTemp.append(A); |
112 | 0 | aTemp.append(E); |
113 | 0 | aTemp.append(H); |
114 | 0 | aTemp.setClosed(true); |
115 | 0 | aRetval.append(aTemp); |
116 | | |
117 | | // create front |
118 | 0 | aTemp.clear(); |
119 | 0 | aTemp.append(B); |
120 | 0 | aTemp.append(A); |
121 | 0 | aTemp.append(D); |
122 | 0 | aTemp.append(C); |
123 | 0 | aTemp.setClosed(true); |
124 | 0 | aRetval.append(aTemp); |
125 | | |
126 | | // create left |
127 | 0 | aTemp.clear(); |
128 | 0 | aTemp.append(E); |
129 | 0 | aTemp.append(A); |
130 | 0 | aTemp.append(B); |
131 | 0 | aTemp.append(F); |
132 | 0 | aTemp.setClosed(true); |
133 | 0 | aRetval.append(aTemp); |
134 | | |
135 | | // create top |
136 | 0 | aTemp.clear(); |
137 | 0 | aTemp.append(C); |
138 | 0 | aTemp.append(G); |
139 | 0 | aTemp.append(F); |
140 | 0 | aTemp.append(B); |
141 | 0 | aTemp.setClosed(true); |
142 | 0 | aRetval.append(aTemp); |
143 | | |
144 | | // create right |
145 | 0 | aTemp.clear(); |
146 | 0 | aTemp.append(H); |
147 | 0 | aTemp.append(G); |
148 | 0 | aTemp.append(C); |
149 | 0 | aTemp.append(D); |
150 | 0 | aTemp.setClosed(true); |
151 | 0 | aRetval.append(aTemp); |
152 | | |
153 | | // create back |
154 | 0 | aTemp.clear(); |
155 | 0 | aTemp.append(F); |
156 | 0 | aTemp.append(G); |
157 | 0 | aTemp.append(H); |
158 | 0 | aTemp.append(E); |
159 | 0 | aTemp.setClosed(true); |
160 | 0 | aRetval.append(aTemp); |
161 | 0 | return aRetval; |
162 | 0 | }(); |
163 | 0 | return singleton; |
164 | 0 | } |
165 | | |
166 | | B3DPolyPolygon createCubePolyPolygonFromB3DRange( const B3DRange& rRange) |
167 | 0 | { |
168 | 0 | B3DPolyPolygon aRetval; |
169 | |
|
170 | 0 | if(!rRange.isEmpty()) |
171 | 0 | { |
172 | 0 | aRetval = createUnitCubePolyPolygon(); |
173 | 0 | B3DHomMatrix aTrans; |
174 | 0 | aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth()); |
175 | 0 | aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ()); |
176 | 0 | aRetval.transform(aTrans); |
177 | 0 | aRetval.removeDoublePoints(); |
178 | 0 | } |
179 | |
|
180 | 0 | return aRetval; |
181 | 0 | } |
182 | | |
183 | | B3DPolyPolygon createCubeFillPolyPolygonFromB3DRange( const B3DRange& rRange) |
184 | 0 | { |
185 | 0 | B3DPolyPolygon aRetval; |
186 | |
|
187 | 0 | if(!rRange.isEmpty()) |
188 | 0 | { |
189 | 0 | aRetval = createUnitCubeFillPolyPolygon(); |
190 | 0 | B3DHomMatrix aTrans; |
191 | 0 | aTrans.scale(rRange.getWidth(), rRange.getHeight(), rRange.getDepth()); |
192 | 0 | aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ()); |
193 | 0 | aRetval.transform(aTrans); |
194 | 0 | aRetval.removeDoublePoints(); |
195 | 0 | } |
196 | |
|
197 | 0 | return aRetval; |
198 | 0 | } |
199 | | |
200 | | // helper for getting the 3D Point from given cartesian coordinates. fHor is defined from |
201 | | // [M_PI_2 .. -M_PI_2], fVer from [0.0 .. 2PI] |
202 | | static B3DPoint getPointFromCartesian(double fHor, double fVer) |
203 | 0 | { |
204 | 0 | const double fCosVer(cos(fVer)); |
205 | 0 | return B3DPoint(fCosVer * cos(fHor), sin(fVer), fCosVer * -sin(fHor)); |
206 | 0 | } |
207 | | |
208 | | B3DPolyPolygon createUnitSpherePolyPolygon( |
209 | | sal_uInt32 nHorSeg, sal_uInt32 nVerSeg, |
210 | | double fVerStart, double fVerStop, |
211 | | double fHorStart, double fHorStop) |
212 | 0 | { |
213 | 0 | B3DPolyPolygon aRetval; |
214 | 0 | sal_uInt32 a, b; |
215 | |
|
216 | 0 | if(!nHorSeg) |
217 | 0 | { |
218 | 0 | nHorSeg = fround(fabs(fHorStop - fHorStart) / (M_PI / 12.0)); |
219 | 0 | } |
220 | | |
221 | | // min/max limitations |
222 | 0 | nHorSeg = std::clamp(nHorSeg, nMinSegments, nMaxSegments); |
223 | |
|
224 | 0 | if(!nVerSeg) |
225 | 0 | { |
226 | 0 | nVerSeg = fround(fabs(fVerStop - fVerStart) / (M_PI / 12.0)); |
227 | 0 | } |
228 | | |
229 | | // min/max limitations |
230 | 0 | nVerSeg = std::clamp(nVerSeg, nMinSegments, nMaxSegments); |
231 | | |
232 | | // create constants |
233 | 0 | const double fVerDiffPerStep((fVerStop - fVerStart) / static_cast<double>(nVerSeg)); |
234 | 0 | const double fHorDiffPerStep((fHorStop - fHorStart) / static_cast<double>(nHorSeg)); |
235 | 0 | bool bHorClosed(fTools::equal(fHorStop - fHorStart, 2 * M_PI)); |
236 | 0 | bool bVerFromTop(fTools::equal(fVerStart, M_PI_2)); |
237 | 0 | bool bVerToBottom(fTools::equal(fVerStop, -M_PI_2)); |
238 | | |
239 | | // create horizontal rings |
240 | 0 | const sal_uInt32 nLoopVerInit(bVerFromTop ? 1 : 0); |
241 | 0 | const sal_uInt32 nLoopVerLimit(bVerToBottom ? nVerSeg : nVerSeg + 1); |
242 | 0 | const sal_uInt32 nLoopHorLimit(bHorClosed ? nHorSeg : nHorSeg + 1); |
243 | |
|
244 | 0 | for(a = nLoopVerInit; a < nLoopVerLimit; a++) |
245 | 0 | { |
246 | 0 | const double fVer(fVerStart + (static_cast<double>(a) * fVerDiffPerStep)); |
247 | 0 | B3DPolygon aNew; |
248 | |
|
249 | 0 | for(b = 0; b < nLoopHorLimit; b++) |
250 | 0 | { |
251 | 0 | const double fHor(fHorStart + (static_cast<double>(b) * fHorDiffPerStep)); |
252 | 0 | aNew.append(getPointFromCartesian(fHor, fVer)); |
253 | 0 | } |
254 | |
|
255 | 0 | aNew.setClosed(bHorClosed); |
256 | 0 | aRetval.append(aNew); |
257 | 0 | } |
258 | | |
259 | | // create vertical half-rings |
260 | 0 | for(a = 0; a < nLoopHorLimit; a++) |
261 | 0 | { |
262 | 0 | const double fHor(fHorStart + (static_cast<double>(a) * fHorDiffPerStep)); |
263 | 0 | B3DPolygon aNew; |
264 | |
|
265 | 0 | if(bVerFromTop) |
266 | 0 | { |
267 | 0 | aNew.append(B3DPoint(0.0, 1.0, 0.0)); |
268 | 0 | } |
269 | |
|
270 | 0 | for(b = nLoopVerInit; b < nLoopVerLimit; b++) |
271 | 0 | { |
272 | 0 | const double fVer(fVerStart + (static_cast<double>(b) * fVerDiffPerStep)); |
273 | 0 | aNew.append(getPointFromCartesian(fHor, fVer)); |
274 | 0 | } |
275 | |
|
276 | 0 | if(bVerToBottom) |
277 | 0 | { |
278 | 0 | aNew.append(B3DPoint(0.0, -1.0, 0.0)); |
279 | 0 | } |
280 | |
|
281 | 0 | aRetval.append(aNew); |
282 | 0 | } |
283 | |
|
284 | 0 | return aRetval; |
285 | 0 | } |
286 | | |
287 | | B3DPolyPolygon createSpherePolyPolygonFromB3DRange( const B3DRange& rRange, |
288 | | sal_uInt32 nHorSeg, sal_uInt32 nVerSeg, |
289 | | double fVerStart, double fVerStop, |
290 | | double fHorStart, double fHorStop) |
291 | 0 | { |
292 | 0 | B3DPolyPolygon aRetval(createUnitSpherePolyPolygon(nHorSeg, nVerSeg, fVerStart, fVerStop, fHorStart, fHorStop)); |
293 | |
|
294 | 0 | if(aRetval.count()) |
295 | 0 | { |
296 | | // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions |
297 | 0 | B3DHomMatrix aTrans; |
298 | 0 | aTrans.translate(1.0, 1.0, 1.0); |
299 | 0 | aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0); |
300 | 0 | aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ()); |
301 | 0 | aRetval.transform(aTrans); |
302 | 0 | } |
303 | |
|
304 | 0 | return aRetval; |
305 | 0 | } |
306 | | |
307 | | B3DPolyPolygon createUnitSphereFillPolyPolygon( |
308 | | sal_uInt32 nHorSeg, sal_uInt32 nVerSeg, |
309 | | bool bNormals, |
310 | | double fVerStart, double fVerStop, |
311 | | double fHorStart, double fHorStop) |
312 | 0 | { |
313 | 0 | B3DPolyPolygon aRetval; |
314 | |
|
315 | 0 | if(!nHorSeg) |
316 | 0 | { |
317 | 0 | nHorSeg = fround(fabs(fHorStop - fHorStart) / (M_PI / 12.0)); |
318 | 0 | } |
319 | | |
320 | | // min/max limitations |
321 | 0 | nHorSeg = std::clamp(nHorSeg, nMinSegments, nMaxSegments); |
322 | |
|
323 | 0 | if(!nVerSeg) |
324 | 0 | { |
325 | 0 | nVerSeg = fround(fabs(fVerStop - fVerStart) / (M_PI / 12.0)); |
326 | 0 | } |
327 | | |
328 | | // min/max limitations |
329 | 0 | nVerSeg = std::clamp(nVerSeg, nMinSegments, nMaxSegments); |
330 | | |
331 | | // vertical loop |
332 | 0 | for(sal_uInt32 a(0); a < nVerSeg; a++) |
333 | 0 | { |
334 | 0 | const double fVer1(fVerStart + (((fVerStop - fVerStart) * a) / nVerSeg)); |
335 | 0 | const double fVer2(fVerStart + (((fVerStop - fVerStart) * (a + 1)) / nVerSeg)); |
336 | | |
337 | | // horizontal loop |
338 | 0 | for(sal_uInt32 b(0); b < nHorSeg; b++) |
339 | 0 | { |
340 | 0 | const double fHor1(fHorStart + (((fHorStop - fHorStart) * b) / nHorSeg)); |
341 | 0 | const double fHor2(fHorStart + (((fHorStop - fHorStart) * (b + 1)) / nHorSeg)); |
342 | 0 | B3DPolygon aNew; |
343 | |
|
344 | 0 | aNew.append(getPointFromCartesian(fHor1, fVer1)); |
345 | 0 | aNew.append(getPointFromCartesian(fHor2, fVer1)); |
346 | 0 | aNew.append(getPointFromCartesian(fHor2, fVer2)); |
347 | 0 | aNew.append(getPointFromCartesian(fHor1, fVer2)); |
348 | |
|
349 | 0 | if(bNormals) |
350 | 0 | { |
351 | 0 | for(sal_uInt32 c(0); c < aNew.count(); c++) |
352 | 0 | { |
353 | 0 | aNew.setNormal(c, ::basegfx::B3DVector(aNew.getB3DPoint(c))); |
354 | 0 | } |
355 | 0 | } |
356 | |
|
357 | 0 | aNew.setClosed(true); |
358 | 0 | aRetval.append(aNew); |
359 | 0 | } |
360 | 0 | } |
361 | |
|
362 | 0 | return aRetval; |
363 | 0 | } |
364 | | |
365 | | B3DPolyPolygon createSphereFillPolyPolygonFromB3DRange( const B3DRange& rRange, |
366 | | sal_uInt32 nHorSeg, sal_uInt32 nVerSeg, |
367 | | bool bNormals, |
368 | | double fVerStart, double fVerStop, |
369 | | double fHorStart, double fHorStop) |
370 | 0 | { |
371 | 0 | B3DPolyPolygon aRetval(createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, bNormals, fVerStart, fVerStop, fHorStart, fHorStop)); |
372 | |
|
373 | 0 | if(aRetval.count()) |
374 | 0 | { |
375 | | // move and scale whole construct which is now in [-1.0 .. 1.0] in all directions |
376 | 0 | B3DHomMatrix aTrans; |
377 | 0 | aTrans.translate(1.0, 1.0, 1.0); |
378 | 0 | aTrans.scale(rRange.getWidth() / 2.0, rRange.getHeight() / 2.0, rRange.getDepth() / 2.0); |
379 | 0 | aTrans.translate(rRange.getMinX(), rRange.getMinY(), rRange.getMinZ()); |
380 | 0 | aRetval.transform(aTrans); |
381 | 0 | } |
382 | |
|
383 | 0 | return aRetval; |
384 | 0 | } |
385 | | |
386 | | B3DPolyPolygon applyDefaultNormalsSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter) |
387 | 0 | { |
388 | 0 | B3DPolyPolygon aRetval; |
389 | |
|
390 | 0 | for( const auto& rB3DPolygon : rCandidate) |
391 | 0 | { |
392 | 0 | aRetval.append(applyDefaultNormalsSphere(rB3DPolygon, rCenter)); |
393 | 0 | } |
394 | |
|
395 | 0 | return aRetval; |
396 | 0 | } |
397 | | |
398 | | B3DPolyPolygon invertNormals( const B3DPolyPolygon& rCandidate) |
399 | 0 | { |
400 | 0 | B3DPolyPolygon aRetval; |
401 | |
|
402 | 0 | for( const auto& rB3DPolygon : rCandidate ) |
403 | 0 | { |
404 | 0 | aRetval.append(invertNormals(rB3DPolygon)); |
405 | 0 | } |
406 | |
|
407 | 0 | return aRetval; |
408 | 0 | } |
409 | | |
410 | | B3DPolyPolygon applyDefaultTextureCoordinatesParallel( const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bChangeX, bool bChangeY) |
411 | 0 | { |
412 | 0 | B3DPolyPolygon aRetval; |
413 | |
|
414 | 0 | for( const auto& rB3DPolygon : rCandidate) |
415 | 0 | { |
416 | 0 | aRetval.append(applyDefaultTextureCoordinatesParallel(rB3DPolygon, rRange, bChangeX, bChangeY)); |
417 | 0 | } |
418 | |
|
419 | 0 | return aRetval; |
420 | 0 | } |
421 | | |
422 | | B3DPolyPolygon applyDefaultTextureCoordinatesSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX, bool bChangeY) |
423 | 0 | { |
424 | 0 | B3DPolyPolygon aRetval; |
425 | |
|
426 | 0 | for( const auto& rB3DPolygon : rCandidate ) |
427 | 0 | { |
428 | 0 | aRetval.append(applyDefaultTextureCoordinatesSphere(rB3DPolygon, rCenter, bChangeX, bChangeY)); |
429 | 0 | } |
430 | |
|
431 | 0 | return aRetval; |
432 | 0 | } |
433 | | |
434 | | bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint) |
435 | 0 | { |
436 | 0 | const sal_uInt32 nPolygonCount(rCandidate.count()); |
437 | |
|
438 | 0 | if(nPolygonCount == 1) |
439 | 0 | { |
440 | 0 | return isInside(rCandidate.getB3DPolygon(0), rPoint, false/*bWithBorder*/); |
441 | 0 | } |
442 | 0 | else |
443 | 0 | { |
444 | 0 | sal_Int32 nInsideCount(0); |
445 | |
|
446 | 0 | for(const auto& rPolygon : rCandidate ) |
447 | 0 | { |
448 | 0 | const bool bInside(isInside(rPolygon, rPoint, false/*bWithBorder*/)); |
449 | |
|
450 | 0 | if(bInside) |
451 | 0 | { |
452 | 0 | nInsideCount++; |
453 | 0 | } |
454 | 0 | } |
455 | |
|
456 | 0 | return (nInsideCount % 2); |
457 | 0 | } |
458 | 0 | } |
459 | | |
460 | | /// converters for css::drawing::PolyPolygonShape3D |
461 | | B3DPolyPolygon UnoPolyPolygonShape3DToB3DPolyPolygon( |
462 | | const css::drawing::PolyPolygonShape3D& rPolyPolygonShape3DSource) |
463 | 0 | { |
464 | 0 | B3DPolyPolygon aRetval; |
465 | 0 | const sal_Int32 nOuterSequenceCount(rPolyPolygonShape3DSource.SequenceX.getLength()); |
466 | |
|
467 | 0 | if(nOuterSequenceCount) |
468 | 0 | { |
469 | 0 | assert(nOuterSequenceCount == rPolyPolygonShape3DSource.SequenceY.getLength() |
470 | 0 | && nOuterSequenceCount |
471 | 0 | == rPolyPolygonShape3DSource.SequenceZ.getLength()&& |
472 | 0 | "UnoPolyPolygonShape3DToB3DPolygon: Not all double sequences have the same " |
473 | 0 | "length (!)" ); |
474 | |
|
475 | 0 | for(sal_Int32 a(0); a < nOuterSequenceCount; a++) |
476 | 0 | { |
477 | 0 | basegfx::B3DPolygon aNewPolygon; |
478 | |
|
479 | 0 | auto& rInnerSequenceX = rPolyPolygonShape3DSource.SequenceX[a]; |
480 | 0 | auto& rInnerSequenceY = rPolyPolygonShape3DSource.SequenceY[a]; |
481 | 0 | auto& rInnerSequenceZ = rPolyPolygonShape3DSource.SequenceZ[a]; |
482 | |
|
483 | 0 | const sal_Int32 nInnerSequenceCount(rInnerSequenceX.getLength()); |
484 | 0 | assert(nInnerSequenceCount == rInnerSequenceY.getLength() |
485 | 0 | && nInnerSequenceCount == rInnerSequenceZ.getLength() |
486 | 0 | && "UnoPolyPolygonShape3DToB3DPolygon: Not all double sequences have " |
487 | 0 | "the same length (!)"); |
488 | |
|
489 | 0 | for(sal_Int32 b(0); b < nInnerSequenceCount; b++) |
490 | 0 | { |
491 | 0 | aNewPolygon.append(basegfx::B3DPoint(rInnerSequenceX[b], rInnerSequenceY[b], rInnerSequenceZ[b])); |
492 | 0 | } |
493 | | |
494 | | // #i101520# correction is needed for imported polygons of old format, |
495 | | // see callers |
496 | 0 | basegfx::utils::checkClosed(aNewPolygon); |
497 | |
|
498 | 0 | aRetval.append(aNewPolygon); |
499 | 0 | } |
500 | 0 | } |
501 | |
|
502 | 0 | return aRetval; |
503 | 0 | } |
504 | | |
505 | | void B3DPolyPolygonToUnoPolyPolygonShape3D( |
506 | | const B3DPolyPolygon& rPolyPolygonSource, |
507 | | css::drawing::PolyPolygonShape3D& rPolyPolygonShape3DRetval) |
508 | 0 | { |
509 | 0 | const sal_uInt32 nPolygonCount(rPolyPolygonSource.count()); |
510 | |
|
511 | 0 | if(nPolygonCount) |
512 | 0 | { |
513 | 0 | rPolyPolygonShape3DRetval.SequenceX.realloc(nPolygonCount); |
514 | 0 | rPolyPolygonShape3DRetval.SequenceY.realloc(nPolygonCount); |
515 | 0 | rPolyPolygonShape3DRetval.SequenceZ.realloc(nPolygonCount); |
516 | |
|
517 | 0 | css::drawing::DoubleSequence* pOuterSequenceX = rPolyPolygonShape3DRetval.SequenceX.getArray(); |
518 | 0 | css::drawing::DoubleSequence* pOuterSequenceY = rPolyPolygonShape3DRetval.SequenceY.getArray(); |
519 | 0 | css::drawing::DoubleSequence* pOuterSequenceZ = rPolyPolygonShape3DRetval.SequenceZ.getArray(); |
520 | |
|
521 | 0 | for(sal_uInt32 a(0); a < nPolygonCount; a++) |
522 | 0 | { |
523 | 0 | const basegfx::B3DPolygon& aPoly(rPolyPolygonSource.getB3DPolygon(a)); |
524 | 0 | const sal_uInt32 nPointCount(aPoly.count()); |
525 | |
|
526 | 0 | if(nPointCount) |
527 | 0 | { |
528 | 0 | const bool bIsClosed(aPoly.isClosed()); |
529 | 0 | const sal_uInt32 nTargetCount(bIsClosed ? nPointCount + 1 : nPointCount); |
530 | 0 | pOuterSequenceX->realloc(nTargetCount); |
531 | 0 | pOuterSequenceY->realloc(nTargetCount); |
532 | 0 | pOuterSequenceZ->realloc(nTargetCount); |
533 | |
|
534 | 0 | double* pInnerSequenceX = pOuterSequenceX->getArray(); |
535 | 0 | double* pInnerSequenceY = pOuterSequenceY->getArray(); |
536 | 0 | double* pInnerSequenceZ = pOuterSequenceZ->getArray(); |
537 | |
|
538 | 0 | for(sal_uInt32 b(0); b < nPointCount; b++) |
539 | 0 | { |
540 | 0 | const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(b)); |
541 | |
|
542 | 0 | *pInnerSequenceX++ = aPoint.getX(); |
543 | 0 | *pInnerSequenceY++ = aPoint.getY(); |
544 | 0 | *pInnerSequenceZ++ = aPoint.getZ(); |
545 | 0 | } |
546 | |
|
547 | 0 | if(bIsClosed) |
548 | 0 | { |
549 | 0 | const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(0)); |
550 | |
|
551 | 0 | *pInnerSequenceX++ = aPoint.getX(); |
552 | 0 | *pInnerSequenceY++ = aPoint.getY(); |
553 | 0 | *pInnerSequenceZ++ = aPoint.getZ(); |
554 | 0 | } |
555 | 0 | } |
556 | 0 | else |
557 | 0 | { |
558 | 0 | pOuterSequenceX->realloc(0); |
559 | 0 | pOuterSequenceY->realloc(0); |
560 | 0 | pOuterSequenceZ->realloc(0); |
561 | 0 | } |
562 | |
|
563 | 0 | pOuterSequenceX++; |
564 | 0 | pOuterSequenceY++; |
565 | 0 | pOuterSequenceZ++; |
566 | 0 | } |
567 | 0 | } |
568 | 0 | else |
569 | 0 | { |
570 | 0 | rPolyPolygonShape3DRetval.SequenceX.realloc(0); |
571 | 0 | rPolyPolygonShape3DRetval.SequenceY.realloc(0); |
572 | 0 | rPolyPolygonShape3DRetval.SequenceZ.realloc(0); |
573 | 0 | } |
574 | 0 | } |
575 | | |
576 | | } // end of namespace |
577 | | |
578 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |