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