LCOV - code coverage report
Current view: top level - basegfx/source/polygon - b3dpolygon.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 767 0.0 %
Date: 2014-04-14 Functions: 0 134 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10