Line data Source code
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 <osl/diagnose.h>
21 : #include <basegfx/polygon/b3dpolygon.hxx>
22 : #include <basegfx/point/b3dpoint.hxx>
23 : #include <basegfx/matrix/b3dhommatrix.hxx>
24 : #include <rtl/instance.hxx>
25 : #include <basegfx/point/b2dpoint.hxx>
26 : #include <basegfx/color/bcolor.hxx>
27 : #include <basegfx/matrix/b2dhommatrix.hxx>
28 : #include <vector>
29 : #include <algorithm>
30 :
31 : //////////////////////////////////////////////////////////////////////////////
32 :
33 260270 : class CoordinateData3D
34 : {
35 : basegfx::B3DPoint maPoint;
36 :
37 : public:
38 0 : CoordinateData3D()
39 0 : : maPoint()
40 : {
41 0 : }
42 :
43 33482 : explicit CoordinateData3D(const basegfx::B3DPoint& rData)
44 33482 : : maPoint(rData)
45 : {
46 33482 : }
47 :
48 148056 : const basegfx::B3DPoint& getCoordinate() const
49 : {
50 148056 : return maPoint;
51 : }
52 :
53 0 : void setCoordinate(const basegfx::B3DPoint& rValue)
54 : {
55 0 : if(rValue != maPoint)
56 0 : maPoint = rValue;
57 0 : }
58 :
59 42080 : bool operator==(const CoordinateData3D& rData) const
60 : {
61 42080 : return (maPoint == rData.getCoordinate());
62 : }
63 :
64 16870 : void transform(const basegfx::B3DHomMatrix& rMatrix)
65 : {
66 16870 : maPoint *= rMatrix;
67 16870 : }
68 : };
69 :
70 : //////////////////////////////////////////////////////////////////////////////
71 :
72 : class CoordinateDataArray3D
73 : {
74 : typedef ::std::vector< CoordinateData3D > CoordinateData3DVector;
75 :
76 : CoordinateData3DVector maVector;
77 :
78 : public:
79 1 : explicit CoordinateDataArray3D(sal_uInt32 nCount)
80 1 : : maVector(nCount)
81 : {
82 1 : }
83 :
84 15314 : explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal)
85 15314 : : maVector(rOriginal.maVector)
86 : {
87 15314 : }
88 :
89 0 : CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
90 0 : : maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
91 : {
92 0 : }
93 :
94 15315 : ~CoordinateDataArray3D()
95 15315 : {
96 15315 : }
97 :
98 628 : ::basegfx::B3DVector getNormal() const
99 : {
100 628 : ::basegfx::B3DVector aRetval;
101 628 : const sal_uInt32 nPointCount(maVector.size());
102 :
103 628 : if(nPointCount > 2)
104 : {
105 628 : sal_uInt32 nISmallest(0);
106 628 : sal_uInt32 a(0);
107 628 : const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate());
108 628 : const basegfx::B3DPoint* pNext(0);
109 628 : const basegfx::B3DPoint* pPrev(0);
110 :
111 : // To guarantee a correctly oriented point, choose an outmost one
112 : // which then cannot be concave
113 2512 : for(a = 1; a < nPointCount; a++)
114 : {
115 1884 : const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
116 :
117 3768 : if((rCandidate.getX() < pSmallest->getX())
118 1419 : || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY())
119 3285 : || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ()))
120 : {
121 602 : nISmallest = a;
122 602 : pSmallest = &rCandidate;
123 : }
124 : }
125 :
126 : // look for a next point different from minimal one
127 628 : for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount)
128 : {
129 628 : const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
130 :
131 628 : if(!rCandidate.equal(*pSmallest))
132 : {
133 628 : pNext = &rCandidate;
134 628 : break;
135 : }
136 : }
137 :
138 : // look for a previous point different from minimal one
139 628 : for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount)
140 : {
141 628 : const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
142 :
143 628 : if(!rCandidate.equal(*pSmallest))
144 : {
145 628 : pPrev = &rCandidate;
146 628 : break;
147 : }
148 : }
149 :
150 : // we always have a minimal point. If we also have a different next and previous,
151 : // we can calculate the normal
152 628 : if(pNext && pPrev)
153 : {
154 628 : const basegfx::B3DVector aPrev(*pPrev - *pSmallest);
155 1256 : const basegfx::B3DVector aNext(*pNext - *pSmallest);
156 :
157 628 : aRetval = cross(aPrev, aNext);
158 1256 : aRetval.normalize();
159 : }
160 : }
161 :
162 628 : return aRetval;
163 : }
164 :
165 132293 : sal_uInt32 count() const
166 : {
167 132293 : return maVector.size();
168 : }
169 :
170 10520 : bool operator==(const CoordinateDataArray3D& rCandidate) const
171 : {
172 10520 : return (maVector == rCandidate.maVector);
173 : }
174 :
175 102208 : const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const
176 : {
177 102208 : return maVector[nIndex].getCoordinate();
178 : }
179 :
180 0 : void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
181 : {
182 0 : maVector[nIndex].setCoordinate(rValue);
183 0 : }
184 :
185 33482 : void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount)
186 : {
187 33482 : if(nCount)
188 : {
189 : // add nCount copies of rValue
190 33482 : CoordinateData3DVector::iterator aIndex(maVector.begin());
191 33482 : aIndex += nIndex;
192 33482 : maVector.insert(aIndex, nCount, rValue);
193 : }
194 33482 : }
195 :
196 0 : void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource)
197 : {
198 0 : const sal_uInt32 nCount(rSource.maVector.size());
199 :
200 0 : if(nCount)
201 : {
202 : // insert data
203 0 : CoordinateData3DVector::iterator aIndex(maVector.begin());
204 0 : aIndex += nIndex;
205 0 : CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin());
206 0 : CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end());
207 0 : maVector.insert(aIndex, aStart, aEnd);
208 : }
209 0 : }
210 :
211 842 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
212 : {
213 842 : if(nCount)
214 : {
215 : // remove point data
216 842 : CoordinateData3DVector::iterator aStart(maVector.begin());
217 842 : aStart += nIndex;
218 842 : const CoordinateData3DVector::iterator aEnd(aStart + nCount);
219 842 : maVector.erase(aStart, aEnd);
220 : }
221 842 : }
222 :
223 5216 : void flip()
224 : {
225 5216 : if(maVector.size() > 1)
226 : {
227 5216 : const sal_uInt32 nHalfSize(maVector.size() >> 1L);
228 5216 : CoordinateData3DVector::iterator aStart(maVector.begin());
229 5216 : CoordinateData3DVector::iterator aEnd(maVector.end() - 1L);
230 :
231 15648 : for(sal_uInt32 a(0); a < nHalfSize; a++)
232 : {
233 10432 : ::std::swap(*aStart, *aEnd);
234 10432 : ++aStart;
235 10432 : --aEnd;
236 : }
237 : }
238 5216 : }
239 :
240 5217 : void transform(const ::basegfx::B3DHomMatrix& rMatrix)
241 : {
242 5217 : CoordinateData3DVector::iterator aStart(maVector.begin());
243 5217 : CoordinateData3DVector::iterator aEnd(maVector.end());
244 :
245 22087 : for(; aStart != aEnd; ++aStart)
246 : {
247 16870 : aStart->transform(rMatrix);
248 : }
249 5217 : }
250 : };
251 :
252 : //////////////////////////////////////////////////////////////////////////////
253 :
254 : class BColorArray
255 : {
256 : typedef ::std::vector< ::basegfx::BColor > BColorDataVector;
257 :
258 : BColorDataVector maVector;
259 : sal_uInt32 mnUsedEntries;
260 :
261 : public:
262 66 : explicit BColorArray(sal_uInt32 nCount)
263 : : maVector(nCount),
264 66 : mnUsedEntries(0L)
265 : {
266 66 : }
267 :
268 0 : explicit BColorArray(const BColorArray& rOriginal)
269 : : maVector(rOriginal.maVector),
270 0 : mnUsedEntries(rOriginal.mnUsedEntries)
271 : {
272 0 : }
273 :
274 0 : BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
275 : : maVector(),
276 0 : mnUsedEntries(0L)
277 : {
278 0 : BColorDataVector::const_iterator aStart(rOriginal.maVector.begin());
279 0 : aStart += nIndex;
280 0 : BColorDataVector::const_iterator aEnd(aStart);
281 : assert(nCount <= rOriginal.maVector.size());
282 0 : aEnd += nCount;
283 0 : maVector.reserve(nCount);
284 :
285 0 : for(; aStart != aEnd; ++aStart)
286 : {
287 0 : if(!aStart->equalZero())
288 0 : mnUsedEntries++;
289 :
290 0 : maVector.push_back(*aStart);
291 : }
292 0 : }
293 :
294 66 : ~BColorArray()
295 66 : {
296 66 : }
297 :
298 : sal_uInt32 count() const
299 : {
300 : return maVector.size();
301 : }
302 :
303 0 : bool operator==(const BColorArray& rCandidate) const
304 : {
305 0 : return (maVector == rCandidate.maVector);
306 : }
307 :
308 528 : bool isUsed() const
309 : {
310 528 : return (0L != mnUsedEntries);
311 : }
312 :
313 726 : const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
314 : {
315 726 : return maVector[nIndex];
316 : }
317 :
318 264 : void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
319 : {
320 264 : bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
321 264 : bool bIsUsed(!rValue.equalZero());
322 :
323 264 : if(bWasUsed)
324 : {
325 0 : if(bIsUsed)
326 : {
327 0 : maVector[nIndex] = rValue;
328 : }
329 : else
330 : {
331 0 : maVector[nIndex] = ::basegfx::BColor::getEmptyBColor();
332 0 : mnUsedEntries--;
333 : }
334 : }
335 : else
336 : {
337 264 : if(bIsUsed)
338 : {
339 264 : maVector[nIndex] = rValue;
340 264 : mnUsedEntries++;
341 : }
342 : }
343 264 : }
344 :
345 0 : void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount)
346 : {
347 0 : if(nCount)
348 : {
349 : // add nCount copies of rValue
350 0 : BColorDataVector::iterator aIndex(maVector.begin());
351 0 : aIndex += nIndex;
352 0 : maVector.insert(aIndex, nCount, rValue);
353 :
354 0 : if(!rValue.equalZero())
355 0 : mnUsedEntries += nCount;
356 : }
357 0 : }
358 :
359 0 : void insert(sal_uInt32 nIndex, const BColorArray& rSource)
360 : {
361 0 : const sal_uInt32 nCount(rSource.maVector.size());
362 :
363 0 : if(nCount)
364 : {
365 : // insert data
366 0 : BColorDataVector::iterator aIndex(maVector.begin());
367 0 : aIndex += nIndex;
368 0 : BColorDataVector::const_iterator aStart(rSource.maVector.begin());
369 0 : BColorDataVector::const_iterator aEnd(rSource.maVector.end());
370 0 : maVector.insert(aIndex, aStart, aEnd);
371 :
372 0 : for(; aStart != aEnd; ++aStart)
373 : {
374 0 : if(!aStart->equalZero())
375 0 : mnUsedEntries++;
376 : }
377 : }
378 0 : }
379 :
380 0 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
381 : {
382 0 : if(nCount)
383 : {
384 0 : const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex);
385 0 : const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount);
386 0 : BColorDataVector::const_iterator aStart(aDeleteStart);
387 :
388 0 : for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
389 : {
390 0 : if(!aStart->equalZero())
391 0 : mnUsedEntries--;
392 : }
393 :
394 : // remove point data
395 0 : maVector.erase(aDeleteStart, aDeleteEnd);
396 : }
397 0 : }
398 :
399 0 : void flip()
400 : {
401 0 : if(maVector.size() > 1)
402 : {
403 0 : const sal_uInt32 nHalfSize(maVector.size() >> 1L);
404 0 : BColorDataVector::iterator aStart(maVector.begin());
405 0 : BColorDataVector::iterator aEnd(maVector.end() - 1L);
406 :
407 0 : for(sal_uInt32 a(0); a < nHalfSize; a++)
408 : {
409 0 : ::std::swap(*aStart, *aEnd);
410 0 : ++aStart;
411 0 : --aEnd;
412 : }
413 : }
414 0 : }
415 : };
416 :
417 : //////////////////////////////////////////////////////////////////////////////
418 :
419 : class NormalsArray3D
420 : {
421 : typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector;
422 :
423 : NormalsData3DVector maVector;
424 : sal_uInt32 mnUsedEntries;
425 :
426 : public:
427 5384 : explicit NormalsArray3D(sal_uInt32 nCount)
428 : : maVector(nCount),
429 5384 : mnUsedEntries(0L)
430 : {
431 5384 : }
432 :
433 529 : explicit NormalsArray3D(const NormalsArray3D& rOriginal)
434 : : maVector(rOriginal.maVector),
435 529 : mnUsedEntries(rOriginal.mnUsedEntries)
436 : {
437 529 : }
438 :
439 0 : NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
440 : : maVector(),
441 0 : mnUsedEntries(0L)
442 : {
443 0 : NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin());
444 0 : aStart += nIndex;
445 0 : NormalsData3DVector::const_iterator aEnd(aStart);
446 0 : aEnd += nCount;
447 0 : maVector.reserve(nCount);
448 :
449 0 : for(; aStart != aEnd; ++aStart)
450 : {
451 0 : if(!aStart->equalZero())
452 0 : mnUsedEntries++;
453 :
454 0 : maVector.push_back(*aStart);
455 : }
456 0 : }
457 :
458 5913 : ~NormalsArray3D()
459 5913 : {
460 5913 : }
461 :
462 : sal_uInt32 count() const
463 : {
464 : return maVector.size();
465 : }
466 :
467 5118 : bool operator==(const NormalsArray3D& rCandidate) const
468 : {
469 5118 : return (maVector == rCandidate.maVector);
470 : }
471 :
472 17649 : bool isUsed() const
473 : {
474 17649 : return (0L != mnUsedEntries);
475 : }
476 :
477 17376 : const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
478 : {
479 17376 : return maVector[nIndex];
480 : }
481 :
482 16536 : void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
483 : {
484 16536 : bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
485 16536 : bool bIsUsed(!rValue.equalZero());
486 :
487 16536 : if(bWasUsed)
488 : {
489 192 : if(bIsUsed)
490 : {
491 192 : maVector[nIndex] = rValue;
492 : }
493 : else
494 : {
495 0 : maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector();
496 0 : mnUsedEntries--;
497 : }
498 : }
499 : else
500 : {
501 16344 : if(bIsUsed)
502 : {
503 16344 : maVector[nIndex] = rValue;
504 16344 : mnUsedEntries++;
505 : }
506 : }
507 16536 : }
508 :
509 0 : void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount)
510 : {
511 0 : if(nCount)
512 : {
513 : // add nCount copies of rValue
514 0 : NormalsData3DVector::iterator aIndex(maVector.begin());
515 0 : aIndex += nIndex;
516 0 : maVector.insert(aIndex, nCount, rValue);
517 :
518 0 : if(!rValue.equalZero())
519 0 : mnUsedEntries += nCount;
520 : }
521 0 : }
522 :
523 0 : void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource)
524 : {
525 0 : const sal_uInt32 nCount(rSource.maVector.size());
526 :
527 0 : if(nCount)
528 : {
529 : // insert data
530 0 : NormalsData3DVector::iterator aIndex(maVector.begin());
531 0 : aIndex += nIndex;
532 0 : NormalsData3DVector::const_iterator aStart(rSource.maVector.begin());
533 0 : NormalsData3DVector::const_iterator aEnd(rSource.maVector.end());
534 0 : maVector.insert(aIndex, aStart, aEnd);
535 :
536 0 : for(; aStart != aEnd; ++aStart)
537 : {
538 0 : if(!aStart->equalZero())
539 0 : mnUsedEntries++;
540 : }
541 : }
542 0 : }
543 :
544 0 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
545 : {
546 0 : if(nCount)
547 : {
548 0 : const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex);
549 0 : const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount);
550 0 : NormalsData3DVector::const_iterator aStart(aDeleteStart);
551 :
552 0 : for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
553 : {
554 0 : if(!aStart->equalZero())
555 0 : mnUsedEntries--;
556 : }
557 :
558 : // remove point data
559 0 : maVector.erase(aDeleteStart, aDeleteEnd);
560 : }
561 0 : }
562 :
563 5216 : void flip()
564 : {
565 5216 : if(maVector.size() > 1)
566 : {
567 5216 : const sal_uInt32 nHalfSize(maVector.size() >> 1L);
568 5216 : NormalsData3DVector::iterator aStart(maVector.begin());
569 5216 : NormalsData3DVector::iterator aEnd(maVector.end() - 1L);
570 :
571 15648 : for(sal_uInt32 a(0); a < nHalfSize; a++)
572 : {
573 10432 : ::std::swap(*aStart, *aEnd);
574 10432 : ++aStart;
575 10432 : --aEnd;
576 : }
577 : }
578 5216 : }
579 :
580 66 : void transform(const basegfx::B3DHomMatrix& rMatrix)
581 : {
582 66 : const NormalsData3DVector::const_iterator aEnd(maVector.end());
583 :
584 330 : for(NormalsData3DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
585 : {
586 264 : (*aStart) *= rMatrix;
587 : }
588 66 : }
589 : };
590 :
591 : //////////////////////////////////////////////////////////////////////////////
592 :
593 : class TextureCoordinate2D
594 : {
595 : typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector;
596 :
597 : TextureData2DVector maVector;
598 : sal_uInt32 mnUsedEntries;
599 :
600 : public:
601 5336 : explicit TextureCoordinate2D(sal_uInt32 nCount)
602 : : maVector(nCount),
603 5336 : mnUsedEntries(0L)
604 : {
605 5336 : }
606 :
607 454 : explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal)
608 : : maVector(rOriginal.maVector),
609 454 : mnUsedEntries(rOriginal.mnUsedEntries)
610 : {
611 454 : }
612 :
613 0 : TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
614 : : maVector(),
615 0 : mnUsedEntries(0L)
616 : {
617 0 : TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin());
618 0 : aStart += nIndex;
619 0 : TextureData2DVector::const_iterator aEnd(aStart);
620 0 : aEnd += nCount;
621 0 : maVector.reserve(nCount);
622 :
623 0 : for(; aStart != aEnd; ++aStart)
624 : {
625 0 : if(!aStart->equalZero())
626 0 : mnUsedEntries++;
627 :
628 0 : maVector.push_back(*aStart);
629 : }
630 0 : }
631 :
632 5790 : ~TextureCoordinate2D()
633 5790 : {
634 5790 : }
635 :
636 : sal_uInt32 count() const
637 : {
638 : return maVector.size();
639 : }
640 :
641 5070 : bool operator==(const TextureCoordinate2D& rCandidate) const
642 : {
643 5070 : return (maVector == rCandidate.maVector);
644 : }
645 :
646 12214 : bool isUsed() const
647 : {
648 12214 : return (0L != mnUsedEntries);
649 : }
650 :
651 16328 : const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
652 : {
653 16328 : return maVector[nIndex];
654 : }
655 :
656 16008 : void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
657 : {
658 16008 : bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
659 16008 : bool bIsUsed(!rValue.equalZero());
660 :
661 16008 : if(bWasUsed)
662 : {
663 0 : if(bIsUsed)
664 : {
665 0 : maVector[nIndex] = rValue;
666 : }
667 : else
668 : {
669 0 : maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint();
670 0 : mnUsedEntries--;
671 : }
672 : }
673 : else
674 : {
675 16008 : if(bIsUsed)
676 : {
677 16008 : maVector[nIndex] = rValue;
678 16008 : mnUsedEntries++;
679 : }
680 : }
681 16008 : }
682 :
683 0 : void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount)
684 : {
685 0 : if(nCount)
686 : {
687 : // add nCount copies of rValue
688 0 : TextureData2DVector::iterator aIndex(maVector.begin());
689 0 : aIndex += nIndex;
690 0 : maVector.insert(aIndex, nCount, rValue);
691 :
692 0 : if(!rValue.equalZero())
693 0 : mnUsedEntries += nCount;
694 : }
695 0 : }
696 :
697 0 : void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource)
698 : {
699 0 : const sal_uInt32 nCount(rSource.maVector.size());
700 :
701 0 : if(nCount)
702 : {
703 : // insert data
704 0 : TextureData2DVector::iterator aIndex(maVector.begin());
705 0 : aIndex += nIndex;
706 0 : TextureData2DVector::const_iterator aStart(rSource.maVector.begin());
707 0 : TextureData2DVector::const_iterator aEnd(rSource.maVector.end());
708 0 : maVector.insert(aIndex, aStart, aEnd);
709 :
710 0 : for(; aStart != aEnd; ++aStart)
711 : {
712 0 : if(!aStart->equalZero())
713 0 : mnUsedEntries++;
714 : }
715 : }
716 0 : }
717 :
718 0 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
719 : {
720 0 : if(nCount)
721 : {
722 0 : const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
723 0 : const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
724 0 : TextureData2DVector::const_iterator aStart(aDeleteStart);
725 :
726 0 : for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
727 : {
728 0 : if(!aStart->equalZero())
729 0 : mnUsedEntries--;
730 : }
731 :
732 : // remove point data
733 0 : maVector.erase(aDeleteStart, aDeleteEnd);
734 : }
735 0 : }
736 :
737 5192 : void flip()
738 : {
739 5192 : if(maVector.size() > 1)
740 : {
741 5192 : const sal_uInt32 nHalfSize(maVector.size() >> 1L);
742 5192 : TextureData2DVector::iterator aStart(maVector.begin());
743 5192 : TextureData2DVector::iterator aEnd(maVector.end() - 1L);
744 :
745 15576 : for(sal_uInt32 a(0); a < nHalfSize; a++)
746 : {
747 10384 : ::std::swap(*aStart, *aEnd);
748 10384 : ++aStart;
749 10384 : --aEnd;
750 : }
751 : }
752 5192 : }
753 :
754 261 : void transform(const ::basegfx::B2DHomMatrix& rMatrix)
755 : {
756 261 : const TextureData2DVector::const_iterator aEnd(maVector.end());
757 :
758 1305 : for(TextureData2DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
759 : {
760 1044 : (*aStart) *= rMatrix;
761 : }
762 261 : }
763 : };
764 :
765 : //////////////////////////////////////////////////////////////////////////////
766 :
767 : class ImplB3DPolygon
768 : {
769 : // The point vector. This vector exists always and defines the
770 : // count of members.
771 : CoordinateDataArray3D maPoints;
772 :
773 : // The BColor vector. This vectors are created on demand
774 : // and may be zero.
775 : BColorArray* mpBColors;
776 :
777 : // The Normals vector. This vectors are created on demand
778 : // and may be zero.
779 : NormalsArray3D* mpNormals;
780 :
781 : // The TextureCoordinates vector. This vectors are created on demand
782 : // and may be zero.
783 : TextureCoordinate2D* mpTextureCoordiantes;
784 :
785 : // The calculated plane normal. mbPlaneNormalValid says if it's valid.
786 : ::basegfx::B3DVector maPlaneNormal;
787 :
788 : // bitfield
789 : // flag which decides if this polygon is opened or closed
790 : unsigned mbIsClosed : 1;
791 :
792 : // flag which says if maPlaneNormal is up-to-date
793 : unsigned mbPlaneNormalValid : 1;
794 :
795 : protected:
796 39541 : void invalidatePlaneNormal()
797 : {
798 39541 : if(mbPlaneNormalValid)
799 : {
800 9418 : mbPlaneNormalValid = false;
801 : }
802 39541 : }
803 :
804 : public:
805 : // This constructor is only used from the static identity polygon, thus
806 : // the RefCount is set to 1 to never 'delete' this static incarnation.
807 1 : ImplB3DPolygon()
808 : : maPoints(0L),
809 : mpBColors(0L),
810 : mpNormals(0L),
811 : mpTextureCoordiantes(0L),
812 1 : maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
813 : mbIsClosed(false),
814 2 : mbPlaneNormalValid(true)
815 : {
816 : // complete initialization with defaults
817 1 : }
818 :
819 15314 : ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied)
820 : : maPoints(rToBeCopied.maPoints),
821 : mpBColors(0L),
822 : mpNormals(0L),
823 : mpTextureCoordiantes(0L),
824 : maPlaneNormal(rToBeCopied.maPlaneNormal),
825 : mbIsClosed(rToBeCopied.mbIsClosed),
826 15314 : mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid)
827 : {
828 : // complete initialization using copy
829 15314 : if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
830 : {
831 0 : mpBColors = new BColorArray(*rToBeCopied.mpBColors);
832 : }
833 :
834 15314 : if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
835 : {
836 529 : mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals);
837 : }
838 :
839 15314 : if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
840 : {
841 454 : mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes);
842 : }
843 15314 : }
844 :
845 0 : ImplB3DPolygon(const ImplB3DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
846 : : maPoints(rToBeCopied.maPoints, nIndex, nCount),
847 : mpBColors(0L),
848 : mpNormals(0L),
849 : mpTextureCoordiantes(0L),
850 0 : maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
851 : mbIsClosed(rToBeCopied.mbIsClosed),
852 0 : mbPlaneNormalValid(false)
853 : {
854 : // complete initialization using partly copy
855 0 : if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
856 : {
857 0 : mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount);
858 :
859 0 : if(!mpBColors->isUsed())
860 : {
861 0 : delete mpBColors;
862 0 : mpBColors = 0L;
863 : }
864 : }
865 :
866 0 : if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
867 : {
868 0 : mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount);
869 :
870 0 : if(!mpNormals->isUsed())
871 : {
872 0 : delete mpNormals;
873 0 : mpNormals = 0L;
874 : }
875 : }
876 :
877 0 : if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
878 : {
879 0 : mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount);
880 :
881 0 : if(!mpTextureCoordiantes->isUsed())
882 : {
883 0 : delete mpTextureCoordiantes;
884 0 : mpTextureCoordiantes = 0L;
885 : }
886 : }
887 0 : }
888 :
889 15315 : ~ImplB3DPolygon()
890 15315 : {
891 15315 : if(mpBColors)
892 : {
893 66 : delete mpBColors;
894 66 : mpBColors = 0L;
895 : }
896 :
897 15315 : if(mpNormals)
898 : {
899 5720 : delete mpNormals;
900 5720 : mpNormals = 0L;
901 : }
902 :
903 15315 : if(mpTextureCoordiantes)
904 : {
905 5663 : delete mpTextureCoordiantes;
906 5663 : mpTextureCoordiantes = 0L;
907 : }
908 15315 : }
909 :
910 116291 : sal_uInt32 count() const
911 : {
912 116291 : return maPoints.count();
913 : }
914 :
915 9550 : bool isClosed() const
916 : {
917 9550 : return mbIsClosed;
918 : }
919 :
920 7674 : void setClosed(bool bNew)
921 : {
922 7674 : if(bNew != (bool)mbIsClosed)
923 : {
924 7674 : mbIsClosed = bNew;
925 : }
926 7674 : }
927 :
928 10520 : inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const
929 : {
930 10520 : bool bBColorsAreEqual(true);
931 :
932 10520 : if(mpBColors)
933 : {
934 0 : if(rCandidate.mpBColors)
935 : {
936 0 : bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors);
937 : }
938 : else
939 : {
940 : // candidate has no BColors, so it's assumed all unused.
941 0 : bBColorsAreEqual = !mpBColors->isUsed();
942 : }
943 : }
944 : else
945 : {
946 10520 : if(rCandidate.mpBColors)
947 : {
948 : // we have no TextureCoordiantes, so it's assumed all unused.
949 66 : bBColorsAreEqual = !rCandidate.mpBColors->isUsed();
950 : }
951 : }
952 :
953 10520 : return bBColorsAreEqual;
954 : }
955 :
956 10454 : inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const
957 : {
958 10454 : bool bNormalsAreEqual(true);
959 :
960 10454 : if(mpNormals)
961 : {
962 5118 : if(rCandidate.mpNormals)
963 : {
964 5118 : bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals);
965 : }
966 : else
967 : {
968 : // candidate has no normals, so it's assumed all unused.
969 0 : bNormalsAreEqual = !mpNormals->isUsed();
970 : }
971 : }
972 : else
973 : {
974 5336 : if(rCandidate.mpNormals)
975 : {
976 : // we have no normals, so it's assumed all unused.
977 5288 : bNormalsAreEqual = !rCandidate.mpNormals->isUsed();
978 : }
979 : }
980 :
981 10454 : return bNormalsAreEqual;
982 : }
983 :
984 5118 : inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const
985 : {
986 5118 : bool bTextureCoordinatesAreEqual(true);
987 :
988 5118 : if(mpTextureCoordiantes)
989 : {
990 5070 : if(rCandidate.mpTextureCoordiantes)
991 : {
992 5070 : bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes);
993 : }
994 : else
995 : {
996 : // candidate has no TextureCoordinates, so it's assumed all unused.
997 0 : bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed();
998 : }
999 : }
1000 : else
1001 : {
1002 48 : if(rCandidate.mpTextureCoordiantes)
1003 : {
1004 : // we have no TextureCoordiantes, so it's assumed all unused.
1005 0 : bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed();
1006 : }
1007 : }
1008 :
1009 5118 : return bTextureCoordinatesAreEqual;
1010 : }
1011 :
1012 10520 : bool operator==(const ImplB3DPolygon& rCandidate) const
1013 : {
1014 10520 : if(mbIsClosed == rCandidate.mbIsClosed)
1015 : {
1016 10520 : if(maPoints == rCandidate.maPoints)
1017 : {
1018 10520 : if(impBColorsAreEqual(rCandidate))
1019 : {
1020 10454 : if(impNormalsAreEqual(rCandidate))
1021 : {
1022 5118 : if(impTextureCoordinatesAreEqual(rCandidate))
1023 : {
1024 5118 : return true;
1025 : }
1026 : }
1027 : }
1028 : }
1029 : }
1030 :
1031 5402 : return false;
1032 : }
1033 :
1034 102208 : const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const
1035 : {
1036 102208 : return maPoints.getCoordinate(nIndex);
1037 : }
1038 :
1039 0 : void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue)
1040 : {
1041 0 : maPoints.setCoordinate(nIndex, rValue);
1042 0 : invalidatePlaneNormal();
1043 0 : }
1044 :
1045 33482 : void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1046 : {
1047 33482 : if(nCount)
1048 : {
1049 33482 : CoordinateData3D aCoordinate(rPoint);
1050 33482 : maPoints.insert(nIndex, aCoordinate, nCount);
1051 33482 : invalidatePlaneNormal();
1052 :
1053 33482 : if(mpBColors)
1054 : {
1055 0 : mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1056 : }
1057 :
1058 33482 : if(mpNormals)
1059 : {
1060 0 : mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1061 : }
1062 :
1063 33482 : if(mpTextureCoordiantes)
1064 : {
1065 0 : mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1066 33482 : }
1067 : }
1068 33482 : }
1069 :
1070 792 : const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
1071 : {
1072 792 : if(mpBColors)
1073 : {
1074 726 : return mpBColors->getBColor(nIndex);
1075 : }
1076 : else
1077 : {
1078 66 : return ::basegfx::BColor::getEmptyBColor();
1079 : }
1080 : }
1081 :
1082 264 : void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
1083 : {
1084 264 : if(!mpBColors)
1085 : {
1086 66 : if(!rValue.equalZero())
1087 : {
1088 66 : mpBColors = new BColorArray(maPoints.count());
1089 66 : mpBColors->setBColor(nIndex, rValue);
1090 : }
1091 : }
1092 : else
1093 : {
1094 198 : mpBColors->setBColor(nIndex, rValue);
1095 :
1096 198 : if(!mpBColors->isUsed())
1097 : {
1098 0 : delete mpBColors;
1099 0 : mpBColors = 0L;
1100 : }
1101 : }
1102 264 : }
1103 :
1104 842 : bool areBColorsUsed() const
1105 : {
1106 842 : return (mpBColors && mpBColors->isUsed());
1107 : }
1108 :
1109 0 : void clearBColors()
1110 : {
1111 0 : if(mpBColors)
1112 : {
1113 0 : delete mpBColors;
1114 0 : mpBColors = 0L;
1115 : }
1116 0 : }
1117 :
1118 701 : const ::basegfx::B3DVector& getNormal() const
1119 : {
1120 701 : if(!mbPlaneNormalValid)
1121 : {
1122 628 : const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal();
1123 628 : const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true;
1124 : }
1125 :
1126 701 : return maPlaneNormal;
1127 : }
1128 :
1129 22760 : const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
1130 : {
1131 22760 : if(mpNormals)
1132 : {
1133 17376 : return mpNormals->getNormal(nIndex);
1134 : }
1135 : else
1136 : {
1137 5384 : return ::basegfx::B3DVector::getEmptyVector();
1138 : }
1139 : }
1140 :
1141 16536 : void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
1142 : {
1143 16536 : if(!mpNormals)
1144 : {
1145 5384 : if(!rValue.equalZero())
1146 : {
1147 5384 : mpNormals = new NormalsArray3D(maPoints.count());
1148 5384 : mpNormals->setNormal(nIndex, rValue);
1149 : }
1150 : }
1151 : else
1152 : {
1153 11152 : mpNormals->setNormal(nIndex, rValue);
1154 :
1155 11152 : if(!mpNormals->isUsed())
1156 : {
1157 0 : delete mpNormals;
1158 0 : mpNormals = 0L;
1159 : }
1160 : }
1161 16536 : }
1162 :
1163 66 : void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
1164 : {
1165 66 : if(mpNormals)
1166 : {
1167 66 : mpNormals->transform(rMatrix);
1168 : }
1169 66 : }
1170 :
1171 1756 : bool areNormalsUsed() const
1172 : {
1173 1756 : return (mpNormals && mpNormals->isUsed());
1174 : }
1175 :
1176 193 : void clearNormals()
1177 : {
1178 193 : if(mpNormals)
1179 : {
1180 193 : delete mpNormals;
1181 193 : mpNormals = 0L;
1182 : }
1183 193 : }
1184 :
1185 22640 : const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
1186 : {
1187 22640 : if(mpTextureCoordiantes)
1188 : {
1189 16328 : return mpTextureCoordiantes->getTextureCoordinate(nIndex);
1190 : }
1191 : else
1192 : {
1193 6312 : return ::basegfx::B2DPoint::getEmptyPoint();
1194 : }
1195 : }
1196 :
1197 16008 : void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
1198 : {
1199 16008 : if(!mpTextureCoordiantes)
1200 : {
1201 5336 : if(!rValue.equalZero())
1202 : {
1203 5336 : mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1204 5336 : mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1205 : }
1206 : }
1207 : else
1208 : {
1209 10672 : mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1210 :
1211 10672 : if(!mpTextureCoordiantes->isUsed())
1212 : {
1213 0 : delete mpTextureCoordiantes;
1214 0 : mpTextureCoordiantes = 0L;
1215 : }
1216 : }
1217 16008 : }
1218 :
1219 1549 : bool areTextureCoordinatesUsed() const
1220 : {
1221 1549 : return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed());
1222 : }
1223 :
1224 127 : void clearTextureCoordinates()
1225 : {
1226 127 : if(mpTextureCoordiantes)
1227 : {
1228 127 : delete mpTextureCoordiantes;
1229 127 : mpTextureCoordiantes = 0L;
1230 : }
1231 127 : }
1232 :
1233 261 : void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
1234 : {
1235 261 : if(mpTextureCoordiantes)
1236 : {
1237 261 : mpTextureCoordiantes->transform(rMatrix);
1238 : }
1239 261 : }
1240 :
1241 0 : void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource)
1242 : {
1243 0 : const sal_uInt32 nCount(rSource.maPoints.count());
1244 :
1245 0 : if(nCount)
1246 : {
1247 0 : maPoints.insert(nIndex, rSource.maPoints);
1248 0 : invalidatePlaneNormal();
1249 :
1250 0 : if(rSource.mpBColors && rSource.mpBColors->isUsed())
1251 : {
1252 0 : if(!mpBColors)
1253 : {
1254 0 : mpBColors = new BColorArray(maPoints.count());
1255 : }
1256 :
1257 0 : mpBColors->insert(nIndex, *rSource.mpBColors);
1258 : }
1259 : else
1260 : {
1261 0 : if(mpBColors)
1262 : {
1263 0 : mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1264 : }
1265 : }
1266 :
1267 0 : if(rSource.mpNormals && rSource.mpNormals->isUsed())
1268 : {
1269 0 : if(!mpNormals)
1270 : {
1271 0 : mpNormals = new NormalsArray3D(maPoints.count());
1272 : }
1273 :
1274 0 : mpNormals->insert(nIndex, *rSource.mpNormals);
1275 : }
1276 : else
1277 : {
1278 0 : if(mpNormals)
1279 : {
1280 0 : mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1281 : }
1282 : }
1283 :
1284 0 : if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed())
1285 : {
1286 0 : if(!mpTextureCoordiantes)
1287 : {
1288 0 : mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1289 : }
1290 :
1291 0 : mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes);
1292 : }
1293 : else
1294 : {
1295 0 : if(mpTextureCoordiantes)
1296 : {
1297 0 : mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1298 : }
1299 : }
1300 : }
1301 0 : }
1302 :
1303 842 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1304 : {
1305 842 : if(nCount)
1306 : {
1307 842 : maPoints.remove(nIndex, nCount);
1308 842 : invalidatePlaneNormal();
1309 :
1310 842 : if(mpBColors)
1311 : {
1312 0 : mpBColors->remove(nIndex, nCount);
1313 :
1314 0 : if(!mpBColors->isUsed())
1315 : {
1316 0 : delete mpBColors;
1317 0 : mpBColors = 0L;
1318 : }
1319 : }
1320 :
1321 842 : if(mpNormals)
1322 : {
1323 0 : mpNormals->remove(nIndex, nCount);
1324 :
1325 0 : if(!mpNormals->isUsed())
1326 : {
1327 0 : delete mpNormals;
1328 0 : mpNormals = 0L;
1329 : }
1330 : }
1331 :
1332 842 : if(mpTextureCoordiantes)
1333 : {
1334 0 : mpTextureCoordiantes->remove(nIndex, nCount);
1335 :
1336 0 : if(!mpTextureCoordiantes->isUsed())
1337 : {
1338 0 : delete mpTextureCoordiantes;
1339 0 : mpTextureCoordiantes = 0L;
1340 : }
1341 : }
1342 : }
1343 842 : }
1344 :
1345 5216 : void flip()
1346 : {
1347 5216 : if(maPoints.count() > 1)
1348 : {
1349 5216 : maPoints.flip();
1350 :
1351 5216 : if(mbPlaneNormalValid)
1352 : {
1353 : // mirror plane normal
1354 24 : maPlaneNormal = -maPlaneNormal;
1355 : }
1356 :
1357 5216 : if(mpBColors)
1358 : {
1359 0 : mpBColors->flip();
1360 : }
1361 :
1362 5216 : if(mpNormals)
1363 : {
1364 5216 : mpNormals->flip();
1365 : }
1366 :
1367 5216 : if(mpTextureCoordiantes)
1368 : {
1369 5192 : mpTextureCoordiantes->flip();
1370 : }
1371 : }
1372 5216 : }
1373 :
1374 0 : bool hasDoublePoints() const
1375 : {
1376 0 : if(mbIsClosed)
1377 : {
1378 : // check for same start and end point
1379 0 : const sal_uInt32 nIndex(maPoints.count() - 1L);
1380 :
1381 0 : if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex))
1382 : {
1383 0 : const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)));
1384 :
1385 0 : if(bBColorEqual)
1386 : {
1387 0 : const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)));
1388 :
1389 0 : if(bNormalsEqual)
1390 : {
1391 0 : const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)));
1392 :
1393 0 : if(bTextureCoordinatesEqual)
1394 : {
1395 0 : return true;
1396 : }
1397 : }
1398 : }
1399 : }
1400 : }
1401 :
1402 : // test for range
1403 0 : for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++)
1404 : {
1405 0 : if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L))
1406 : {
1407 0 : const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L)));
1408 :
1409 0 : if(bBColorEqual)
1410 : {
1411 0 : const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L)));
1412 :
1413 0 : if(bNormalsEqual)
1414 : {
1415 0 : const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L)));
1416 :
1417 0 : if(bTextureCoordinatesEqual)
1418 : {
1419 0 : return true;
1420 : }
1421 : }
1422 : }
1423 : }
1424 : }
1425 :
1426 0 : return false;
1427 : }
1428 :
1429 0 : void removeDoublePointsAtBeginEnd()
1430 : {
1431 : // Only remove DoublePoints at Begin and End when poly is closed
1432 0 : if(mbIsClosed)
1433 : {
1434 : bool bRemove;
1435 :
1436 0 : do
1437 : {
1438 0 : bRemove = false;
1439 :
1440 0 : if(maPoints.count() > 1L)
1441 : {
1442 0 : const sal_uInt32 nIndex(maPoints.count() - 1L);
1443 0 : bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex));
1444 :
1445 0 : if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)))
1446 : {
1447 0 : bRemove = false;
1448 : }
1449 :
1450 0 : if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)))
1451 : {
1452 0 : bRemove = false;
1453 : }
1454 :
1455 0 : if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)))
1456 : {
1457 0 : bRemove = false;
1458 : }
1459 : }
1460 :
1461 0 : if(bRemove)
1462 : {
1463 0 : const sal_uInt32 nIndex(maPoints.count() - 1L);
1464 0 : remove(nIndex, 1L);
1465 : }
1466 : } while(bRemove);
1467 : }
1468 0 : }
1469 :
1470 0 : void removeDoublePointsWholeTrack()
1471 : {
1472 0 : sal_uInt32 nIndex(0L);
1473 :
1474 : // test as long as there are at least two points and as long as the index
1475 : // is smaller or equal second last point
1476 0 : while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L))
1477 : {
1478 0 : const sal_uInt32 nNextIndex(nIndex + 1L);
1479 0 : bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex));
1480 :
1481 0 : if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex)))
1482 : {
1483 0 : bRemove = false;
1484 : }
1485 :
1486 0 : if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex)))
1487 : {
1488 0 : bRemove = false;
1489 : }
1490 :
1491 0 : if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex)))
1492 : {
1493 0 : bRemove = false;
1494 : }
1495 :
1496 0 : if(bRemove)
1497 : {
1498 : // if next is same as index and the control vectors are unused, delete index
1499 0 : remove(nIndex, 1L);
1500 : }
1501 : else
1502 : {
1503 : // if different, step forward
1504 0 : nIndex++;
1505 : }
1506 : }
1507 0 : }
1508 :
1509 5217 : void transform(const ::basegfx::B3DHomMatrix& rMatrix)
1510 : {
1511 5217 : maPoints.transform(rMatrix);
1512 :
1513 : // Here, it seems to be possible to transform a valid plane normal and to avoid
1514 : // invalidation, but it's not true. If the transformation contains shears or e.g.
1515 : // perspective projection, the orthogonality to the transformed plane will not
1516 : // be preserved. It may be possible to test that at the matrix to not invalidate in
1517 : // all cases or to extract a matrix which does not 'shear' the vector which is
1518 : // a normal in this case. As long as this is not sure, i will just invalidate.
1519 5217 : invalidatePlaneNormal();
1520 5217 : }
1521 : };
1522 :
1523 : //////////////////////////////////////////////////////////////////////////////
1524 :
1525 : namespace basegfx
1526 : {
1527 : namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType,
1528 : DefaultPolygon > {}; }
1529 :
1530 14562 : B3DPolygon::B3DPolygon() :
1531 14562 : mpPolygon(DefaultPolygon::get())
1532 : {
1533 14562 : }
1534 :
1535 63038 : B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) :
1536 63038 : mpPolygon(rPolygon.mpPolygon)
1537 : {
1538 63038 : }
1539 :
1540 77600 : B3DPolygon::~B3DPolygon()
1541 : {
1542 77600 : }
1543 :
1544 10594 : B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon)
1545 : {
1546 10594 : mpPolygon = rPolygon.mpPolygon;
1547 10594 : return *this;
1548 : }
1549 :
1550 10520 : bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const
1551 : {
1552 10520 : if(mpPolygon.same_object(rPolygon.mpPolygon))
1553 0 : return true;
1554 :
1555 10520 : return (*mpPolygon == *rPolygon.mpPolygon);
1556 : }
1557 :
1558 5402 : bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const
1559 : {
1560 5402 : return !(*this == rPolygon);
1561 : }
1562 :
1563 77592 : sal_uInt32 B3DPolygon::count() const
1564 : {
1565 77592 : return mpPolygon->count();
1566 : }
1567 :
1568 102208 : basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const
1569 : {
1570 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1571 :
1572 102208 : return mpPolygon->getPoint(nIndex);
1573 : }
1574 :
1575 0 : void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
1576 : {
1577 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1578 :
1579 0 : if(getB3DPoint(nIndex) != rValue)
1580 0 : mpPolygon->setPoint(nIndex, rValue);
1581 0 : }
1582 :
1583 528 : BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const
1584 : {
1585 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1586 :
1587 528 : return mpPolygon->getBColor(nIndex);
1588 : }
1589 :
1590 264 : void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue)
1591 : {
1592 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1593 :
1594 264 : if(mpPolygon->getBColor(nIndex) != rValue)
1595 264 : mpPolygon->setBColor(nIndex, rValue);
1596 264 : }
1597 :
1598 832 : bool B3DPolygon::areBColorsUsed() const
1599 : {
1600 832 : return mpPolygon->areBColorsUsed();
1601 : }
1602 :
1603 10 : void B3DPolygon::clearBColors()
1604 : {
1605 10 : if(mpPolygon->areBColorsUsed())
1606 0 : mpPolygon->clearBColors();
1607 10 : }
1608 :
1609 701 : B3DVector B3DPolygon::getNormal() const
1610 : {
1611 701 : return mpPolygon->getNormal();
1612 : }
1613 :
1614 1032 : B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const
1615 : {
1616 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1617 :
1618 1032 : return mpPolygon->getNormal(nIndex);
1619 : }
1620 :
1621 21728 : void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue)
1622 : {
1623 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1624 :
1625 21728 : if(mpPolygon->getNormal(nIndex) != rValue)
1626 16536 : mpPolygon->setNormal(nIndex, rValue);
1627 21728 : }
1628 :
1629 66 : void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix)
1630 : {
1631 66 : if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity())
1632 66 : mpPolygon->transformNormals(rMatrix);
1633 66 : }
1634 :
1635 1487 : bool B3DPolygon::areNormalsUsed() const
1636 : {
1637 1487 : return mpPolygon->areNormalsUsed();
1638 : }
1639 :
1640 203 : void B3DPolygon::clearNormals()
1641 : {
1642 203 : if(mpPolygon->areNormalsUsed())
1643 193 : mpPolygon->clearNormals();
1644 203 : }
1645 :
1646 1296 : B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const
1647 : {
1648 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1649 :
1650 1296 : return mpPolygon->getTextureCoordinate(nIndex);
1651 : }
1652 :
1653 21344 : void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue)
1654 : {
1655 : OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1656 :
1657 21344 : if(mpPolygon->getTextureCoordinate(nIndex) != rValue)
1658 16008 : mpPolygon->setTextureCoordinate(nIndex, rValue);
1659 21344 : }
1660 :
1661 261 : void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
1662 : {
1663 261 : if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity())
1664 261 : mpPolygon->transformTextureCoordinates(rMatrix);
1665 261 : }
1666 :
1667 1151 : bool B3DPolygon::areTextureCoordinatesUsed() const
1668 : {
1669 1151 : return mpPolygon->areTextureCoordinatesUsed();
1670 : }
1671 :
1672 137 : void B3DPolygon::clearTextureCoordinates()
1673 : {
1674 137 : if(mpPolygon->areTextureCoordinatesUsed())
1675 127 : mpPolygon->clearTextureCoordinates();
1676 137 : }
1677 :
1678 33482 : void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1679 : {
1680 33482 : if(nCount)
1681 33482 : mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1682 33482 : }
1683 :
1684 0 : void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
1685 : {
1686 0 : if(rPoly.count())
1687 : {
1688 0 : if(!nCount)
1689 : {
1690 0 : nCount = rPoly.count();
1691 : }
1692 :
1693 0 : if(0L == nIndex && nCount == rPoly.count())
1694 : {
1695 0 : mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
1696 : }
1697 : else
1698 : {
1699 : OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)");
1700 0 : ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
1701 0 : mpPolygon->insert(mpPolygon->count(), aTempPoly);
1702 : }
1703 : }
1704 0 : }
1705 :
1706 842 : void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1707 : {
1708 : OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)");
1709 :
1710 842 : if(nCount)
1711 842 : mpPolygon->remove(nIndex, nCount);
1712 842 : }
1713 :
1714 0 : void B3DPolygon::clear()
1715 : {
1716 0 : mpPolygon = DefaultPolygon::get();
1717 0 : }
1718 :
1719 9550 : bool B3DPolygon::isClosed() const
1720 : {
1721 9550 : return mpPolygon->isClosed();
1722 : }
1723 :
1724 8410 : void B3DPolygon::setClosed(bool bNew)
1725 : {
1726 8410 : if(isClosed() != bNew)
1727 7674 : mpPolygon->setClosed(bNew);
1728 8410 : }
1729 :
1730 5216 : void B3DPolygon::flip()
1731 : {
1732 5216 : if(count() > 1)
1733 5216 : mpPolygon->flip();
1734 5216 : }
1735 :
1736 0 : bool B3DPolygon::hasDoublePoints() const
1737 : {
1738 0 : return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints());
1739 : }
1740 :
1741 0 : void B3DPolygon::removeDoublePoints()
1742 : {
1743 0 : if(hasDoublePoints())
1744 : {
1745 0 : mpPolygon->removeDoublePointsAtBeginEnd();
1746 0 : mpPolygon->removeDoublePointsWholeTrack();
1747 : }
1748 0 : }
1749 :
1750 5217 : void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix)
1751 : {
1752 5217 : if(mpPolygon->count() && !rMatrix.isIdentity())
1753 : {
1754 5217 : mpPolygon->transform(rMatrix);
1755 : }
1756 5217 : }
1757 : } // end of namespace basegfx
1758 :
1759 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|