fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / basegfx / source / polygon / b3dpolygon.cxx
blob5a07ab2b6d0c3440809309d8e51d52b06e7e129b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
31 //////////////////////////////////////////////////////////////////////////////
33 class CoordinateData3D
35 basegfx::B3DPoint maPoint;
37 public:
38 CoordinateData3D()
39 : maPoint()
43 explicit CoordinateData3D(const basegfx::B3DPoint& rData)
44 : maPoint(rData)
48 const basegfx::B3DPoint& getCoordinate() const
50 return maPoint;
53 void setCoordinate(const basegfx::B3DPoint& rValue)
55 if(rValue != maPoint)
56 maPoint = rValue;
59 bool operator==(const CoordinateData3D& rData) const
61 return (maPoint == rData.getCoordinate());
64 void transform(const basegfx::B3DHomMatrix& rMatrix)
66 maPoint *= rMatrix;
70 //////////////////////////////////////////////////////////////////////////////
72 class CoordinateDataArray3D
74 typedef ::std::vector< CoordinateData3D > CoordinateData3DVector;
76 CoordinateData3DVector maVector;
78 public:
79 explicit CoordinateDataArray3D(sal_uInt32 nCount)
80 : maVector(nCount)
84 explicit CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal)
85 : maVector(rOriginal.maVector)
89 CoordinateDataArray3D(const CoordinateDataArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
90 : maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
94 ~CoordinateDataArray3D()
98 ::basegfx::B3DVector getNormal() const
100 ::basegfx::B3DVector aRetval;
101 const sal_uInt32 nPointCount(maVector.size());
103 if(nPointCount > 2)
105 sal_uInt32 nISmallest(0);
106 sal_uInt32 a(0);
107 const basegfx::B3DPoint* pSmallest(&maVector[0].getCoordinate());
108 const basegfx::B3DPoint* pNext(0);
109 const basegfx::B3DPoint* pPrev(0);
111 // To guarantee a correctly oriented point, choose an outmost one
112 // which then cannot be concave
113 for(a = 1; a < nPointCount; a++)
115 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
117 if((rCandidate.getX() < pSmallest->getX())
118 || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() < pSmallest->getY())
119 || (rCandidate.getX() == pSmallest->getX() && rCandidate.getY() == pSmallest->getY() && rCandidate.getZ() < pSmallest->getZ()))
121 nISmallest = a;
122 pSmallest = &rCandidate;
126 // look for a next point different from minimal one
127 for(a = (nISmallest + 1) % nPointCount; a != nISmallest; a = (a + 1) % nPointCount)
129 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
131 if(!rCandidate.equal(*pSmallest))
133 pNext = &rCandidate;
134 break;
138 // look for a previous point different from minimal one
139 for(a = (nISmallest + nPointCount - 1) % nPointCount; a != nISmallest; a = (a + nPointCount - 1) % nPointCount)
141 const basegfx::B3DPoint& rCandidate = maVector[a].getCoordinate();
143 if(!rCandidate.equal(*pSmallest))
145 pPrev = &rCandidate;
146 break;
150 // we always have a minimal point. If we also have a different next and previous,
151 // we can calculate the normal
152 if(pNext && pPrev)
154 const basegfx::B3DVector aPrev(*pPrev - *pSmallest);
155 const basegfx::B3DVector aNext(*pNext - *pSmallest);
157 aRetval = cross(aPrev, aNext);
158 aRetval.normalize();
162 return aRetval;
165 sal_uInt32 count() const
167 return maVector.size();
170 bool operator==(const CoordinateDataArray3D& rCandidate) const
172 return (maVector == rCandidate.maVector);
175 const basegfx::B3DPoint& getCoordinate(sal_uInt32 nIndex) const
177 return maVector[nIndex].getCoordinate();
180 void setCoordinate(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
182 maVector[nIndex].setCoordinate(rValue);
185 void insert(sal_uInt32 nIndex, const CoordinateData3D& rValue, sal_uInt32 nCount)
187 if(nCount)
189 // add nCount copies of rValue
190 CoordinateData3DVector::iterator aIndex(maVector.begin());
191 aIndex += nIndex;
192 maVector.insert(aIndex, nCount, rValue);
196 void insert(sal_uInt32 nIndex, const CoordinateDataArray3D& rSource)
198 const sal_uInt32 nCount(rSource.maVector.size());
200 if(nCount)
202 // insert data
203 CoordinateData3DVector::iterator aIndex(maVector.begin());
204 aIndex += nIndex;
205 CoordinateData3DVector::const_iterator aStart(rSource.maVector.begin());
206 CoordinateData3DVector::const_iterator aEnd(rSource.maVector.end());
207 maVector.insert(aIndex, aStart, aEnd);
211 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
213 if(nCount)
215 // remove point data
216 CoordinateData3DVector::iterator aStart(maVector.begin());
217 aStart += nIndex;
218 const CoordinateData3DVector::iterator aEnd(aStart + nCount);
219 maVector.erase(aStart, aEnd);
223 void flip()
225 if(maVector.size() > 1)
227 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
228 CoordinateData3DVector::iterator aStart(maVector.begin());
229 CoordinateData3DVector::iterator aEnd(maVector.end() - 1L);
231 for(sal_uInt32 a(0); a < nHalfSize; a++)
233 ::std::swap(*aStart, *aEnd);
234 ++aStart;
235 --aEnd;
240 void transform(const ::basegfx::B3DHomMatrix& rMatrix)
242 CoordinateData3DVector::iterator aStart(maVector.begin());
243 CoordinateData3DVector::iterator aEnd(maVector.end());
245 for(; aStart != aEnd; ++aStart)
247 aStart->transform(rMatrix);
252 //////////////////////////////////////////////////////////////////////////////
254 class BColorArray
256 typedef ::std::vector< ::basegfx::BColor > BColorDataVector;
258 BColorDataVector maVector;
259 sal_uInt32 mnUsedEntries;
261 public:
262 explicit BColorArray(sal_uInt32 nCount)
263 : maVector(nCount),
264 mnUsedEntries(0L)
268 explicit BColorArray(const BColorArray& rOriginal)
269 : maVector(rOriginal.maVector),
270 mnUsedEntries(rOriginal.mnUsedEntries)
274 BColorArray(const BColorArray& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
275 : maVector(),
276 mnUsedEntries(0L)
278 BColorDataVector::const_iterator aStart(rOriginal.maVector.begin());
279 aStart += nIndex;
280 BColorDataVector::const_iterator aEnd(aStart);
281 assert(nCount <= rOriginal.maVector.size());
282 aEnd += nCount;
283 maVector.reserve(nCount);
285 for(; aStart != aEnd; ++aStart)
287 if(!aStart->equalZero())
288 mnUsedEntries++;
290 maVector.push_back(*aStart);
294 ~BColorArray()
298 sal_uInt32 count() const
300 return maVector.size();
303 bool operator==(const BColorArray& rCandidate) const
305 return (maVector == rCandidate.maVector);
308 bool isUsed() const
310 return (0L != mnUsedEntries);
313 const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
315 return maVector[nIndex];
318 void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
320 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
321 bool bIsUsed(!rValue.equalZero());
323 if(bWasUsed)
325 if(bIsUsed)
327 maVector[nIndex] = rValue;
329 else
331 maVector[nIndex] = ::basegfx::BColor::getEmptyBColor();
332 mnUsedEntries--;
335 else
337 if(bIsUsed)
339 maVector[nIndex] = rValue;
340 mnUsedEntries++;
345 void insert(sal_uInt32 nIndex, const ::basegfx::BColor& rValue, sal_uInt32 nCount)
347 if(nCount)
349 // add nCount copies of rValue
350 BColorDataVector::iterator aIndex(maVector.begin());
351 aIndex += nIndex;
352 maVector.insert(aIndex, nCount, rValue);
354 if(!rValue.equalZero())
355 mnUsedEntries += nCount;
359 void insert(sal_uInt32 nIndex, const BColorArray& rSource)
361 const sal_uInt32 nCount(rSource.maVector.size());
363 if(nCount)
365 // insert data
366 BColorDataVector::iterator aIndex(maVector.begin());
367 aIndex += nIndex;
368 BColorDataVector::const_iterator aStart(rSource.maVector.begin());
369 BColorDataVector::const_iterator aEnd(rSource.maVector.end());
370 maVector.insert(aIndex, aStart, aEnd);
372 for(; aStart != aEnd; ++aStart)
374 if(!aStart->equalZero())
375 mnUsedEntries++;
380 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
382 if(nCount)
384 const BColorDataVector::iterator aDeleteStart(maVector.begin() + nIndex);
385 const BColorDataVector::iterator aDeleteEnd(aDeleteStart + nCount);
386 BColorDataVector::const_iterator aStart(aDeleteStart);
388 for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
390 if(!aStart->equalZero())
391 mnUsedEntries--;
394 // remove point data
395 maVector.erase(aDeleteStart, aDeleteEnd);
399 void flip()
401 if(maVector.size() > 1)
403 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
404 BColorDataVector::iterator aStart(maVector.begin());
405 BColorDataVector::iterator aEnd(maVector.end() - 1L);
407 for(sal_uInt32 a(0); a < nHalfSize; a++)
409 ::std::swap(*aStart, *aEnd);
410 ++aStart;
411 --aEnd;
417 //////////////////////////////////////////////////////////////////////////////
419 class NormalsArray3D
421 typedef ::std::vector< ::basegfx::B3DVector > NormalsData3DVector;
423 NormalsData3DVector maVector;
424 sal_uInt32 mnUsedEntries;
426 public:
427 explicit NormalsArray3D(sal_uInt32 nCount)
428 : maVector(nCount),
429 mnUsedEntries(0L)
433 explicit NormalsArray3D(const NormalsArray3D& rOriginal)
434 : maVector(rOriginal.maVector),
435 mnUsedEntries(rOriginal.mnUsedEntries)
439 NormalsArray3D(const NormalsArray3D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
440 : maVector(),
441 mnUsedEntries(0L)
443 NormalsData3DVector::const_iterator aStart(rOriginal.maVector.begin());
444 aStart += nIndex;
445 NormalsData3DVector::const_iterator aEnd(aStart);
446 aEnd += nCount;
447 maVector.reserve(nCount);
449 for(; aStart != aEnd; ++aStart)
451 if(!aStart->equalZero())
452 mnUsedEntries++;
454 maVector.push_back(*aStart);
458 ~NormalsArray3D()
462 sal_uInt32 count() const
464 return maVector.size();
467 bool operator==(const NormalsArray3D& rCandidate) const
469 return (maVector == rCandidate.maVector);
472 bool isUsed() const
474 return (0L != mnUsedEntries);
477 const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
479 return maVector[nIndex];
482 void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
484 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
485 bool bIsUsed(!rValue.equalZero());
487 if(bWasUsed)
489 if(bIsUsed)
491 maVector[nIndex] = rValue;
493 else
495 maVector[nIndex] = ::basegfx::B3DVector::getEmptyVector();
496 mnUsedEntries--;
499 else
501 if(bIsUsed)
503 maVector[nIndex] = rValue;
504 mnUsedEntries++;
509 void insert(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue, sal_uInt32 nCount)
511 if(nCount)
513 // add nCount copies of rValue
514 NormalsData3DVector::iterator aIndex(maVector.begin());
515 aIndex += nIndex;
516 maVector.insert(aIndex, nCount, rValue);
518 if(!rValue.equalZero())
519 mnUsedEntries += nCount;
523 void insert(sal_uInt32 nIndex, const NormalsArray3D& rSource)
525 const sal_uInt32 nCount(rSource.maVector.size());
527 if(nCount)
529 // insert data
530 NormalsData3DVector::iterator aIndex(maVector.begin());
531 aIndex += nIndex;
532 NormalsData3DVector::const_iterator aStart(rSource.maVector.begin());
533 NormalsData3DVector::const_iterator aEnd(rSource.maVector.end());
534 maVector.insert(aIndex, aStart, aEnd);
536 for(; aStart != aEnd; ++aStart)
538 if(!aStart->equalZero())
539 mnUsedEntries++;
544 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
546 if(nCount)
548 const NormalsData3DVector::iterator aDeleteStart(maVector.begin() + nIndex);
549 const NormalsData3DVector::iterator aDeleteEnd(aDeleteStart + nCount);
550 NormalsData3DVector::const_iterator aStart(aDeleteStart);
552 for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
554 if(!aStart->equalZero())
555 mnUsedEntries--;
558 // remove point data
559 maVector.erase(aDeleteStart, aDeleteEnd);
563 void flip()
565 if(maVector.size() > 1)
567 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
568 NormalsData3DVector::iterator aStart(maVector.begin());
569 NormalsData3DVector::iterator aEnd(maVector.end() - 1L);
571 for(sal_uInt32 a(0); a < nHalfSize; a++)
573 ::std::swap(*aStart, *aEnd);
574 ++aStart;
575 --aEnd;
580 void transform(const basegfx::B3DHomMatrix& rMatrix)
582 const NormalsData3DVector::const_iterator aEnd(maVector.end());
584 for(NormalsData3DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
586 (*aStart) *= rMatrix;
591 //////////////////////////////////////////////////////////////////////////////
593 class TextureCoordinate2D
595 typedef ::std::vector< ::basegfx::B2DPoint > TextureData2DVector;
597 TextureData2DVector maVector;
598 sal_uInt32 mnUsedEntries;
600 public:
601 explicit TextureCoordinate2D(sal_uInt32 nCount)
602 : maVector(nCount),
603 mnUsedEntries(0L)
607 explicit TextureCoordinate2D(const TextureCoordinate2D& rOriginal)
608 : maVector(rOriginal.maVector),
609 mnUsedEntries(rOriginal.mnUsedEntries)
613 TextureCoordinate2D(const TextureCoordinate2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
614 : maVector(),
615 mnUsedEntries(0L)
617 TextureData2DVector::const_iterator aStart(rOriginal.maVector.begin());
618 aStart += nIndex;
619 TextureData2DVector::const_iterator aEnd(aStart);
620 aEnd += nCount;
621 maVector.reserve(nCount);
623 for(; aStart != aEnd; ++aStart)
625 if(!aStart->equalZero())
626 mnUsedEntries++;
628 maVector.push_back(*aStart);
632 ~TextureCoordinate2D()
636 sal_uInt32 count() const
638 return maVector.size();
641 bool operator==(const TextureCoordinate2D& rCandidate) const
643 return (maVector == rCandidate.maVector);
646 bool isUsed() const
648 return (0L != mnUsedEntries);
651 const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
653 return maVector[nIndex];
656 void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
658 bool bWasUsed(mnUsedEntries && !maVector[nIndex].equalZero());
659 bool bIsUsed(!rValue.equalZero());
661 if(bWasUsed)
663 if(bIsUsed)
665 maVector[nIndex] = rValue;
667 else
669 maVector[nIndex] = ::basegfx::B2DPoint::getEmptyPoint();
670 mnUsedEntries--;
673 else
675 if(bIsUsed)
677 maVector[nIndex] = rValue;
678 mnUsedEntries++;
683 void insert(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue, sal_uInt32 nCount)
685 if(nCount)
687 // add nCount copies of rValue
688 TextureData2DVector::iterator aIndex(maVector.begin());
689 aIndex += nIndex;
690 maVector.insert(aIndex, nCount, rValue);
692 if(!rValue.equalZero())
693 mnUsedEntries += nCount;
697 void insert(sal_uInt32 nIndex, const TextureCoordinate2D& rSource)
699 const sal_uInt32 nCount(rSource.maVector.size());
701 if(nCount)
703 // insert data
704 TextureData2DVector::iterator aIndex(maVector.begin());
705 aIndex += nIndex;
706 TextureData2DVector::const_iterator aStart(rSource.maVector.begin());
707 TextureData2DVector::const_iterator aEnd(rSource.maVector.end());
708 maVector.insert(aIndex, aStart, aEnd);
710 for(; aStart != aEnd; ++aStart)
712 if(!aStart->equalZero())
713 mnUsedEntries++;
718 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
720 if(nCount)
722 const TextureData2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
723 const TextureData2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
724 TextureData2DVector::const_iterator aStart(aDeleteStart);
726 for(; mnUsedEntries && aStart != aDeleteEnd; ++aStart)
728 if(!aStart->equalZero())
729 mnUsedEntries--;
732 // remove point data
733 maVector.erase(aDeleteStart, aDeleteEnd);
737 void flip()
739 if(maVector.size() > 1)
741 const sal_uInt32 nHalfSize(maVector.size() >> 1L);
742 TextureData2DVector::iterator aStart(maVector.begin());
743 TextureData2DVector::iterator aEnd(maVector.end() - 1L);
745 for(sal_uInt32 a(0); a < nHalfSize; a++)
747 ::std::swap(*aStart, *aEnd);
748 ++aStart;
749 --aEnd;
754 void transform(const ::basegfx::B2DHomMatrix& rMatrix)
756 const TextureData2DVector::const_iterator aEnd(maVector.end());
758 for(TextureData2DVector::iterator aStart(maVector.begin()); aStart != aEnd; ++aStart)
760 (*aStart) *= rMatrix;
765 //////////////////////////////////////////////////////////////////////////////
767 class ImplB3DPolygon
769 // The point vector. This vector exists always and defines the
770 // count of members.
771 CoordinateDataArray3D maPoints;
773 // The BColor vector. This vectors are created on demand
774 // and may be zero.
775 BColorArray* mpBColors;
777 // The Normals vector. This vectors are created on demand
778 // and may be zero.
779 NormalsArray3D* mpNormals;
781 // The TextureCoordinates vector. This vectors are created on demand
782 // and may be zero.
783 TextureCoordinate2D* mpTextureCoordiantes;
785 // The calculated plane normal. mbPlaneNormalValid says if it's valid.
786 ::basegfx::B3DVector maPlaneNormal;
788 // bitfield
789 // flag which decides if this polygon is opened or closed
790 unsigned mbIsClosed : 1;
792 // flag which says if maPlaneNormal is up-to-date
793 unsigned mbPlaneNormalValid : 1;
795 protected:
796 void invalidatePlaneNormal()
798 if(mbPlaneNormalValid)
800 mbPlaneNormalValid = false;
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 ImplB3DPolygon()
808 : maPoints(0L),
809 mpBColors(0L),
810 mpNormals(0L),
811 mpTextureCoordiantes(0L),
812 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
813 mbIsClosed(false),
814 mbPlaneNormalValid(true)
816 // complete initialization with defaults
819 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 mbPlaneNormalValid(rToBeCopied.mbPlaneNormalValid)
828 // complete initialization using copy
829 if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
831 mpBColors = new BColorArray(*rToBeCopied.mpBColors);
834 if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
836 mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals);
839 if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
841 mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes);
845 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 maPlaneNormal(::basegfx::B3DVector::getEmptyVector()),
851 mbIsClosed(rToBeCopied.mbIsClosed),
852 mbPlaneNormalValid(false)
854 // complete initialization using partly copy
855 if(rToBeCopied.mpBColors && rToBeCopied.mpBColors->isUsed())
857 mpBColors = new BColorArray(*rToBeCopied.mpBColors, nIndex, nCount);
859 if(!mpBColors->isUsed())
861 delete mpBColors;
862 mpBColors = 0L;
866 if(rToBeCopied.mpNormals && rToBeCopied.mpNormals->isUsed())
868 mpNormals = new NormalsArray3D(*rToBeCopied.mpNormals, nIndex, nCount);
870 if(!mpNormals->isUsed())
872 delete mpNormals;
873 mpNormals = 0L;
877 if(rToBeCopied.mpTextureCoordiantes && rToBeCopied.mpTextureCoordiantes->isUsed())
879 mpTextureCoordiantes = new TextureCoordinate2D(*rToBeCopied.mpTextureCoordiantes, nIndex, nCount);
881 if(!mpTextureCoordiantes->isUsed())
883 delete mpTextureCoordiantes;
884 mpTextureCoordiantes = 0L;
889 ~ImplB3DPolygon()
891 if(mpBColors)
893 delete mpBColors;
894 mpBColors = 0L;
897 if(mpNormals)
899 delete mpNormals;
900 mpNormals = 0L;
903 if(mpTextureCoordiantes)
905 delete mpTextureCoordiantes;
906 mpTextureCoordiantes = 0L;
910 sal_uInt32 count() const
912 return maPoints.count();
915 bool isClosed() const
917 return mbIsClosed;
920 void setClosed(bool bNew)
922 if(bNew != (bool)mbIsClosed)
924 mbIsClosed = bNew;
928 inline bool impBColorsAreEqual(const ImplB3DPolygon& rCandidate) const
930 bool bBColorsAreEqual(true);
932 if(mpBColors)
934 if(rCandidate.mpBColors)
936 bBColorsAreEqual = (*mpBColors == *rCandidate.mpBColors);
938 else
940 // candidate has no BColors, so it's assumed all unused.
941 bBColorsAreEqual = !mpBColors->isUsed();
944 else
946 if(rCandidate.mpBColors)
948 // we have no TextureCoordiantes, so it's assumed all unused.
949 bBColorsAreEqual = !rCandidate.mpBColors->isUsed();
953 return bBColorsAreEqual;
956 inline bool impNormalsAreEqual(const ImplB3DPolygon& rCandidate) const
958 bool bNormalsAreEqual(true);
960 if(mpNormals)
962 if(rCandidate.mpNormals)
964 bNormalsAreEqual = (*mpNormals == *rCandidate.mpNormals);
966 else
968 // candidate has no normals, so it's assumed all unused.
969 bNormalsAreEqual = !mpNormals->isUsed();
972 else
974 if(rCandidate.mpNormals)
976 // we have no normals, so it's assumed all unused.
977 bNormalsAreEqual = !rCandidate.mpNormals->isUsed();
981 return bNormalsAreEqual;
984 inline bool impTextureCoordinatesAreEqual(const ImplB3DPolygon& rCandidate) const
986 bool bTextureCoordinatesAreEqual(true);
988 if(mpTextureCoordiantes)
990 if(rCandidate.mpTextureCoordiantes)
992 bTextureCoordinatesAreEqual = (*mpTextureCoordiantes == *rCandidate.mpTextureCoordiantes);
994 else
996 // candidate has no TextureCoordinates, so it's assumed all unused.
997 bTextureCoordinatesAreEqual = !mpTextureCoordiantes->isUsed();
1000 else
1002 if(rCandidate.mpTextureCoordiantes)
1004 // we have no TextureCoordiantes, so it's assumed all unused.
1005 bTextureCoordinatesAreEqual = !rCandidate.mpTextureCoordiantes->isUsed();
1009 return bTextureCoordinatesAreEqual;
1012 bool operator==(const ImplB3DPolygon& rCandidate) const
1014 if(mbIsClosed == rCandidate.mbIsClosed)
1016 if(maPoints == rCandidate.maPoints)
1018 if(impBColorsAreEqual(rCandidate))
1020 if(impNormalsAreEqual(rCandidate))
1022 if(impTextureCoordinatesAreEqual(rCandidate))
1024 return true;
1031 return false;
1034 const ::basegfx::B3DPoint& getPoint(sal_uInt32 nIndex) const
1036 return maPoints.getCoordinate(nIndex);
1039 void setPoint(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rValue)
1041 maPoints.setCoordinate(nIndex, rValue);
1042 invalidatePlaneNormal();
1045 void insert(sal_uInt32 nIndex, const ::basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1047 if(nCount)
1049 CoordinateData3D aCoordinate(rPoint);
1050 maPoints.insert(nIndex, aCoordinate, nCount);
1051 invalidatePlaneNormal();
1053 if(mpBColors)
1055 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1058 if(mpNormals)
1060 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1063 if(mpTextureCoordiantes)
1065 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1070 const ::basegfx::BColor& getBColor(sal_uInt32 nIndex) const
1072 if(mpBColors)
1074 return mpBColors->getBColor(nIndex);
1076 else
1078 return ::basegfx::BColor::getEmptyBColor();
1082 void setBColor(sal_uInt32 nIndex, const ::basegfx::BColor& rValue)
1084 if(!mpBColors)
1086 if(!rValue.equalZero())
1088 mpBColors = new BColorArray(maPoints.count());
1089 mpBColors->setBColor(nIndex, rValue);
1092 else
1094 mpBColors->setBColor(nIndex, rValue);
1096 if(!mpBColors->isUsed())
1098 delete mpBColors;
1099 mpBColors = 0L;
1104 bool areBColorsUsed() const
1106 return (mpBColors && mpBColors->isUsed());
1109 void clearBColors()
1111 if(mpBColors)
1113 delete mpBColors;
1114 mpBColors = 0L;
1118 const ::basegfx::B3DVector& getNormal() const
1120 if(!mbPlaneNormalValid)
1122 const_cast< ImplB3DPolygon* >(this)->maPlaneNormal = maPoints.getNormal();
1123 const_cast< ImplB3DPolygon* >(this)->mbPlaneNormalValid = true;
1126 return maPlaneNormal;
1129 const ::basegfx::B3DVector& getNormal(sal_uInt32 nIndex) const
1131 if(mpNormals)
1133 return mpNormals->getNormal(nIndex);
1135 else
1137 return ::basegfx::B3DVector::getEmptyVector();
1141 void setNormal(sal_uInt32 nIndex, const ::basegfx::B3DVector& rValue)
1143 if(!mpNormals)
1145 if(!rValue.equalZero())
1147 mpNormals = new NormalsArray3D(maPoints.count());
1148 mpNormals->setNormal(nIndex, rValue);
1151 else
1153 mpNormals->setNormal(nIndex, rValue);
1155 if(!mpNormals->isUsed())
1157 delete mpNormals;
1158 mpNormals = 0L;
1163 void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
1165 if(mpNormals)
1167 mpNormals->transform(rMatrix);
1171 bool areNormalsUsed() const
1173 return (mpNormals && mpNormals->isUsed());
1176 void clearNormals()
1178 if(mpNormals)
1180 delete mpNormals;
1181 mpNormals = 0L;
1185 const ::basegfx::B2DPoint& getTextureCoordinate(sal_uInt32 nIndex) const
1187 if(mpTextureCoordiantes)
1189 return mpTextureCoordiantes->getTextureCoordinate(nIndex);
1191 else
1193 return ::basegfx::B2DPoint::getEmptyPoint();
1197 void setTextureCoordinate(sal_uInt32 nIndex, const ::basegfx::B2DPoint& rValue)
1199 if(!mpTextureCoordiantes)
1201 if(!rValue.equalZero())
1203 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1204 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1207 else
1209 mpTextureCoordiantes->setTextureCoordinate(nIndex, rValue);
1211 if(!mpTextureCoordiantes->isUsed())
1213 delete mpTextureCoordiantes;
1214 mpTextureCoordiantes = 0L;
1219 bool areTextureCoordinatesUsed() const
1221 return (mpTextureCoordiantes && mpTextureCoordiantes->isUsed());
1224 void clearTextureCoordinates()
1226 if(mpTextureCoordiantes)
1228 delete mpTextureCoordiantes;
1229 mpTextureCoordiantes = 0L;
1233 void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
1235 if(mpTextureCoordiantes)
1237 mpTextureCoordiantes->transform(rMatrix);
1241 void insert(sal_uInt32 nIndex, const ImplB3DPolygon& rSource)
1243 const sal_uInt32 nCount(rSource.maPoints.count());
1245 if(nCount)
1247 maPoints.insert(nIndex, rSource.maPoints);
1248 invalidatePlaneNormal();
1250 if(rSource.mpBColors && rSource.mpBColors->isUsed())
1252 if(!mpBColors)
1254 mpBColors = new BColorArray(maPoints.count());
1257 mpBColors->insert(nIndex, *rSource.mpBColors);
1259 else
1261 if(mpBColors)
1263 mpBColors->insert(nIndex, ::basegfx::BColor::getEmptyBColor(), nCount);
1267 if(rSource.mpNormals && rSource.mpNormals->isUsed())
1269 if(!mpNormals)
1271 mpNormals = new NormalsArray3D(maPoints.count());
1274 mpNormals->insert(nIndex, *rSource.mpNormals);
1276 else
1278 if(mpNormals)
1280 mpNormals->insert(nIndex, ::basegfx::B3DVector::getEmptyVector(), nCount);
1284 if(rSource.mpTextureCoordiantes && rSource.mpTextureCoordiantes->isUsed())
1286 if(!mpTextureCoordiantes)
1288 mpTextureCoordiantes = new TextureCoordinate2D(maPoints.count());
1291 mpTextureCoordiantes->insert(nIndex, *rSource.mpTextureCoordiantes);
1293 else
1295 if(mpTextureCoordiantes)
1297 mpTextureCoordiantes->insert(nIndex, ::basegfx::B2DPoint::getEmptyPoint(), nCount);
1303 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1305 if(nCount)
1307 maPoints.remove(nIndex, nCount);
1308 invalidatePlaneNormal();
1310 if(mpBColors)
1312 mpBColors->remove(nIndex, nCount);
1314 if(!mpBColors->isUsed())
1316 delete mpBColors;
1317 mpBColors = 0L;
1321 if(mpNormals)
1323 mpNormals->remove(nIndex, nCount);
1325 if(!mpNormals->isUsed())
1327 delete mpNormals;
1328 mpNormals = 0L;
1332 if(mpTextureCoordiantes)
1334 mpTextureCoordiantes->remove(nIndex, nCount);
1336 if(!mpTextureCoordiantes->isUsed())
1338 delete mpTextureCoordiantes;
1339 mpTextureCoordiantes = 0L;
1345 void flip()
1347 if(maPoints.count() > 1)
1349 maPoints.flip();
1351 if(mbPlaneNormalValid)
1353 // mirror plane normal
1354 maPlaneNormal = -maPlaneNormal;
1357 if(mpBColors)
1359 mpBColors->flip();
1362 if(mpNormals)
1364 mpNormals->flip();
1367 if(mpTextureCoordiantes)
1369 mpTextureCoordiantes->flip();
1374 bool hasDoublePoints() const
1376 if(mbIsClosed)
1378 // check for same start and end point
1379 const sal_uInt32 nIndex(maPoints.count() - 1L);
1381 if(maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex))
1383 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)));
1385 if(bBColorEqual)
1387 const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)));
1389 if(bNormalsEqual)
1391 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)));
1393 if(bTextureCoordinatesEqual)
1395 return true;
1402 // test for range
1403 for(sal_uInt32 a(0L); a < maPoints.count() - 1L; a++)
1405 if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1L))
1407 const bool bBColorEqual(!mpBColors || (mpBColors->getBColor(a) == mpBColors->getBColor(a + 1L)));
1409 if(bBColorEqual)
1411 const bool bNormalsEqual(!mpNormals || (mpNormals->getNormal(a) == mpNormals->getNormal(a + 1L)));
1413 if(bNormalsEqual)
1415 const bool bTextureCoordinatesEqual(!mpTextureCoordiantes || (mpTextureCoordiantes->getTextureCoordinate(a) == mpTextureCoordiantes->getTextureCoordinate(a + 1L)));
1417 if(bTextureCoordinatesEqual)
1419 return true;
1426 return false;
1429 void removeDoublePointsAtBeginEnd()
1431 // Only remove DoublePoints at Begin and End when poly is closed
1432 if(mbIsClosed)
1434 bool bRemove;
1438 bRemove = false;
1440 if(maPoints.count() > 1L)
1442 const sal_uInt32 nIndex(maPoints.count() - 1L);
1443 bRemove = (maPoints.getCoordinate(0L) == maPoints.getCoordinate(nIndex));
1445 if(bRemove && mpBColors && !(mpBColors->getBColor(0L) == mpBColors->getBColor(nIndex)))
1447 bRemove = false;
1450 if(bRemove && mpNormals && !(mpNormals->getNormal(0L) == mpNormals->getNormal(nIndex)))
1452 bRemove = false;
1455 if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(0L) == mpTextureCoordiantes->getTextureCoordinate(nIndex)))
1457 bRemove = false;
1461 if(bRemove)
1463 const sal_uInt32 nIndex(maPoints.count() - 1L);
1464 remove(nIndex, 1L);
1466 } while(bRemove);
1470 void removeDoublePointsWholeTrack()
1472 sal_uInt32 nIndex(0L);
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 while((maPoints.count() > 1L) && (nIndex <= maPoints.count() - 2L))
1478 const sal_uInt32 nNextIndex(nIndex + 1L);
1479 bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nNextIndex));
1481 if(bRemove && mpBColors && !(mpBColors->getBColor(nIndex) == mpBColors->getBColor(nNextIndex)))
1483 bRemove = false;
1486 if(bRemove && mpNormals && !(mpNormals->getNormal(nIndex) == mpNormals->getNormal(nNextIndex)))
1488 bRemove = false;
1491 if(bRemove && mpTextureCoordiantes && !(mpTextureCoordiantes->getTextureCoordinate(nIndex) == mpTextureCoordiantes->getTextureCoordinate(nNextIndex)))
1493 bRemove = false;
1496 if(bRemove)
1498 // if next is same as index and the control vectors are unused, delete index
1499 remove(nIndex, 1L);
1501 else
1503 // if different, step forward
1504 nIndex++;
1509 void transform(const ::basegfx::B3DHomMatrix& rMatrix)
1511 maPoints.transform(rMatrix);
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 invalidatePlaneNormal();
1523 //////////////////////////////////////////////////////////////////////////////
1525 namespace basegfx
1527 namespace { struct DefaultPolygon : public rtl::Static< B3DPolygon::ImplType,
1528 DefaultPolygon > {}; }
1530 B3DPolygon::B3DPolygon() :
1531 mpPolygon(DefaultPolygon::get())
1535 B3DPolygon::B3DPolygon(const B3DPolygon& rPolygon) :
1536 mpPolygon(rPolygon.mpPolygon)
1540 B3DPolygon::~B3DPolygon()
1544 B3DPolygon& B3DPolygon::operator=(const B3DPolygon& rPolygon)
1546 mpPolygon = rPolygon.mpPolygon;
1547 return *this;
1550 bool B3DPolygon::operator==(const B3DPolygon& rPolygon) const
1552 if(mpPolygon.same_object(rPolygon.mpPolygon))
1553 return true;
1555 return (*mpPolygon == *rPolygon.mpPolygon);
1558 bool B3DPolygon::operator!=(const B3DPolygon& rPolygon) const
1560 return !(*this == rPolygon);
1563 sal_uInt32 B3DPolygon::count() const
1565 return mpPolygon->count();
1568 basegfx::B3DPoint B3DPolygon::getB3DPoint(sal_uInt32 nIndex) const
1570 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1572 return mpPolygon->getPoint(nIndex);
1575 void B3DPolygon::setB3DPoint(sal_uInt32 nIndex, const basegfx::B3DPoint& rValue)
1577 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1579 if(getB3DPoint(nIndex) != rValue)
1580 mpPolygon->setPoint(nIndex, rValue);
1583 BColor B3DPolygon::getBColor(sal_uInt32 nIndex) const
1585 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1587 return mpPolygon->getBColor(nIndex);
1590 void B3DPolygon::setBColor(sal_uInt32 nIndex, const BColor& rValue)
1592 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1594 if(mpPolygon->getBColor(nIndex) != rValue)
1595 mpPolygon->setBColor(nIndex, rValue);
1598 bool B3DPolygon::areBColorsUsed() const
1600 return mpPolygon->areBColorsUsed();
1603 void B3DPolygon::clearBColors()
1605 if(mpPolygon->areBColorsUsed())
1606 mpPolygon->clearBColors();
1609 B3DVector B3DPolygon::getNormal() const
1611 return mpPolygon->getNormal();
1614 B3DVector B3DPolygon::getNormal(sal_uInt32 nIndex) const
1616 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1618 return mpPolygon->getNormal(nIndex);
1621 void B3DPolygon::setNormal(sal_uInt32 nIndex, const B3DVector& rValue)
1623 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1625 if(mpPolygon->getNormal(nIndex) != rValue)
1626 mpPolygon->setNormal(nIndex, rValue);
1629 void B3DPolygon::transformNormals(const B3DHomMatrix& rMatrix)
1631 if(mpPolygon->areNormalsUsed() && !rMatrix.isIdentity())
1632 mpPolygon->transformNormals(rMatrix);
1635 bool B3DPolygon::areNormalsUsed() const
1637 return mpPolygon->areNormalsUsed();
1640 void B3DPolygon::clearNormals()
1642 if(mpPolygon->areNormalsUsed())
1643 mpPolygon->clearNormals();
1646 B2DPoint B3DPolygon::getTextureCoordinate(sal_uInt32 nIndex) const
1648 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1650 return mpPolygon->getTextureCoordinate(nIndex);
1653 void B3DPolygon::setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue)
1655 OSL_ENSURE(nIndex < mpPolygon->count(), "B3DPolygon access outside range (!)");
1657 if(mpPolygon->getTextureCoordinate(nIndex) != rValue)
1658 mpPolygon->setTextureCoordinate(nIndex, rValue);
1661 void B3DPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
1663 if(mpPolygon->areTextureCoordinatesUsed() && !rMatrix.isIdentity())
1664 mpPolygon->transformTextureCoordinates(rMatrix);
1667 bool B3DPolygon::areTextureCoordinatesUsed() const
1669 return mpPolygon->areTextureCoordinatesUsed();
1672 void B3DPolygon::clearTextureCoordinates()
1674 if(mpPolygon->areTextureCoordinatesUsed())
1675 mpPolygon->clearTextureCoordinates();
1678 void B3DPolygon::append(const basegfx::B3DPoint& rPoint, sal_uInt32 nCount)
1680 if(nCount)
1681 mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1684 void B3DPolygon::append(const B3DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
1686 if(rPoly.count())
1688 if(!nCount)
1690 nCount = rPoly.count();
1693 if(0L == nIndex && nCount == rPoly.count())
1695 mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
1697 else
1699 OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B3DPolygon Append outside range (!)");
1700 ImplB3DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
1701 mpPolygon->insert(mpPolygon->count(), aTempPoly);
1706 void B3DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1708 OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B3DPolygon Remove outside range (!)");
1710 if(nCount)
1711 mpPolygon->remove(nIndex, nCount);
1714 void B3DPolygon::clear()
1716 mpPolygon = DefaultPolygon::get();
1719 bool B3DPolygon::isClosed() const
1721 return mpPolygon->isClosed();
1724 void B3DPolygon::setClosed(bool bNew)
1726 if(isClosed() != bNew)
1727 mpPolygon->setClosed(bNew);
1730 void B3DPolygon::flip()
1732 if(count() > 1)
1733 mpPolygon->flip();
1736 bool B3DPolygon::hasDoublePoints() const
1738 return (mpPolygon->count() > 1L && mpPolygon->hasDoublePoints());
1741 void B3DPolygon::removeDoublePoints()
1743 if(hasDoublePoints())
1745 mpPolygon->removeDoublePointsAtBeginEnd();
1746 mpPolygon->removeDoublePointsWholeTrack();
1750 void B3DPolygon::transform(const basegfx::B3DHomMatrix& rMatrix)
1752 if(mpPolygon->count() && !rMatrix.isIdentity())
1754 mpPolygon->transform(rMatrix);
1757 } // end of namespace basegfx
1759 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */