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

Generated by: LCOV version 1.11