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