LCOV - code coverage report
Current view: top level - drawinglayer/source/primitive3d - sdrextrudelathetools3d.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 365 456 80.0 %
Date: 2015-06-13 12:38:46 Functions: 11 13 84.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 <drawinglayer/primitive3d/sdrextrudelathetools3d.hxx>
      21             : 
      22             : #include <osl/diagnose.h>
      23             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      24             : #include <basegfx/range/b2drange.hxx>
      25             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      26             : #include <basegfx/matrix/b2dhommatrix.hxx>
      27             : #include <basegfx/point/b3dpoint.hxx>
      28             : #include <basegfx/polygon/b3dpolygon.hxx>
      29             : #include <basegfx/polygon/b3dpolygontools.hxx>
      30             : #include <basegfx/polygon/b3dpolypolygontools.hxx>
      31             : #include <basegfx/range/b3drange.hxx>
      32             : #include <basegfx/matrix/b3dhommatrix.hxx>
      33             : #include <basegfx/polygon/b2dpolygontools.hxx>
      34             : #include <drawinglayer/geometry/viewinformation3d.hxx>
      35             : #include <numeric>
      36             : 
      37             : 
      38             : // decompositon helpers for extrude/lathe (rotation) objects
      39             : 
      40             : namespace
      41             : {
      42             : 
      43             :     // common helpers
      44             : 
      45           0 :     basegfx::B2DPolyPolygon impScalePolyPolygonOnCenter(
      46             :         const basegfx::B2DPolyPolygon& rSource,
      47             :         double fScale)
      48             :     {
      49           0 :         basegfx::B2DPolyPolygon aRetval(rSource);
      50             : 
      51           0 :         if(!basegfx::fTools::equalZero(fScale))
      52             :         {
      53           0 :             const basegfx::B2DRange aRange(basegfx::tools::getRange(rSource));
      54           0 :             const basegfx::B2DPoint aCenter(aRange.getCenter());
      55           0 :             basegfx::B2DHomMatrix aTrans;
      56             : 
      57           0 :             aTrans.translate(-aCenter.getX(), -aCenter.getY());
      58           0 :             aTrans.scale(fScale, fScale);
      59           0 :             aTrans.translate(aCenter.getX(), aCenter.getY());
      60           0 :             aRetval.transform(aTrans);
      61             :         }
      62             : 
      63           0 :         return aRetval;
      64             :     }
      65             : 
      66        8290 :     void impGetOuterPolyPolygon(
      67             :         basegfx::B2DPolyPolygon& rPolygon,
      68             :         basegfx::B2DPolyPolygon& rOuterPolyPolygon,
      69             :         double fOffset,
      70             :         bool bCharacterMode)
      71             :     {
      72        8290 :         rOuterPolyPolygon = rPolygon;
      73             : 
      74        8290 :         if(basegfx::fTools::more(fOffset, 0.0))
      75             :         {
      76         234 :             if(bCharacterMode)
      77             :             {
      78             :                 // grow the outside polygon and scale all polygons to original size. This is done
      79             :                 // to avoid a shrink which potentially would lead to self-intersections, but changes
      80             :                 // the original polygon -> not a precision step, so e.g. not usable for charts
      81         234 :                 const basegfx::B2DRange aRange(basegfx::tools::getRange(rPolygon));
      82         234 :                 rPolygon = basegfx::tools::growInNormalDirection(rPolygon, fOffset);
      83         234 :                 const basegfx::B2DRange aGrownRange(basegfx::tools::getRange(rPolygon));
      84         234 :                 const double fScaleX(basegfx::fTools::equalZero(aGrownRange.getWidth()) ? 1.0 : aRange.getWidth() / aGrownRange.getWidth());
      85         234 :                 const double fScaleY(basegfx::fTools::equalZero(aGrownRange.getHeight())? 1.0 : aRange.getHeight() / aGrownRange.getHeight());
      86         234 :                 basegfx::B2DHomMatrix aScaleTrans;
      87             : 
      88         234 :                 aScaleTrans.translate(-aGrownRange.getMinX(), -aGrownRange.getMinY());
      89         234 :                 aScaleTrans.scale(fScaleX, fScaleY);
      90         234 :                 aScaleTrans.translate(aRange.getMinX(), aRange.getMinY());
      91         234 :                 rPolygon.transform(aScaleTrans);
      92         234 :                 rOuterPolyPolygon.transform(aScaleTrans);
      93             :             }
      94             :             else
      95             :             {
      96             :                 // use more precision, shrink the outer polygons. Since this may lead to self-intersections,
      97             :                 // some kind of correction should be applied here after that step
      98           0 :                 rOuterPolyPolygon = basegfx::tools::growInNormalDirection(rPolygon, -fOffset);
      99           0 :                 basegfx::tools::correctGrowShrinkPolygonPair(rPolygon, rOuterPolyPolygon);
     100             :             }
     101             :         }
     102        8290 :     }
     103             : 
     104        3149 :     void impAddInBetweenFill(
     105             :         basegfx::B3DPolyPolygon& rTarget,
     106             :         const basegfx::B3DPolyPolygon& rPolA,
     107             :         const basegfx::B3DPolyPolygon& rPolB,
     108             :         double fTexVerStart,
     109             :         double fTexVerStop,
     110             :         bool bCreateNormals,
     111             :         bool bCreateTextureCoordinates)
     112             :     {
     113             :         OSL_ENSURE(rPolA.count() == rPolB.count(), "impAddInBetweenFill: unequally sized polygons (!)");
     114        3149 :         const sal_uInt32 nPolygonCount(::std::min(rPolA.count(), rPolB.count()));
     115             : 
     116       10906 :         for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     117             :         {
     118        7757 :             const basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
     119       15514 :             const basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
     120             :             OSL_ENSURE(aSubA.count() == aSubB.count(), "impAddInBetweenFill: unequally sized polygons (!)");
     121        7757 :             const sal_uInt32 nPointCount(::std::min(aSubA.count(), aSubB.count()));
     122             : 
     123        7757 :             if(nPointCount)
     124             :             {
     125        7757 :                 const sal_uInt32 nEdgeCount(aSubA.isClosed() ? nPointCount : nPointCount - 1L);
     126        7757 :                 double fTexHorMultiplicatorA(0.0), fTexHorMultiplicatorB(0.0);
     127        7757 :                 double fPolygonPosA(0.0), fPolygonPosB(0.0);
     128             : 
     129        7757 :                 if(bCreateTextureCoordinates)
     130             :                 {
     131        7680 :                     const double fPolygonLengthA(basegfx::tools::getLength(aSubA));
     132        7680 :                     fTexHorMultiplicatorA = basegfx::fTools::equalZero(fPolygonLengthA) ? 1.0 : 1.0 / fPolygonLengthA;
     133             : 
     134        7680 :                     const double fPolygonLengthB(basegfx::tools::getLength(aSubB));
     135        7680 :                     fTexHorMultiplicatorB = basegfx::fTools::equalZero(fPolygonLengthB) ? 1.0 : 1.0 / fPolygonLengthB;
     136             :                 }
     137             : 
     138       15745 :                 for(sal_uInt32 b(0L); b < nEdgeCount; b++)
     139             :                 {
     140        7988 :                     const sal_uInt32 nIndexA(b);
     141        7988 :                     const sal_uInt32 nIndexB((b + 1L) % nPointCount);
     142             : 
     143        7988 :                     const basegfx::B3DPoint aStartA(aSubA.getB3DPoint(nIndexA));
     144       15976 :                     const basegfx::B3DPoint aEndA(aSubA.getB3DPoint(nIndexB));
     145       15976 :                     const basegfx::B3DPoint aStartB(aSubB.getB3DPoint(nIndexA));
     146       15976 :                     const basegfx::B3DPoint aEndB(aSubB.getB3DPoint(nIndexB));
     147             : 
     148       15976 :                     basegfx::B3DPolygon aNew;
     149        7988 :                     aNew.setClosed(true);
     150             : 
     151        7988 :                     aNew.append(aStartA);
     152        7988 :                     aNew.append(aStartB);
     153        7988 :                     aNew.append(aEndB);
     154        7988 :                     aNew.append(aEndA);
     155             : 
     156        7988 :                     if(bCreateNormals)
     157             :                     {
     158        7988 :                         aNew.setNormal(0L, aSubA.getNormal(nIndexA));
     159        7988 :                         aNew.setNormal(1L, aSubB.getNormal(nIndexA));
     160        7988 :                         aNew.setNormal(2L, aSubB.getNormal(nIndexB));
     161        7988 :                         aNew.setNormal(3L, aSubA.getNormal(nIndexB));
     162             :                     }
     163             : 
     164        7988 :                     if(bCreateTextureCoordinates)
     165             :                     {
     166        7680 :                         const double fRelTexAL(fPolygonPosA * fTexHorMultiplicatorA);
     167        7680 :                         const double fEdgeLengthA(basegfx::B3DVector(aEndA - aStartA).getLength());
     168        7680 :                         fPolygonPosA += fEdgeLengthA;
     169        7680 :                         const double fRelTexAR(fPolygonPosA * fTexHorMultiplicatorA);
     170             : 
     171        7680 :                         const double fRelTexBL(fPolygonPosB * fTexHorMultiplicatorB);
     172        7680 :                         const double fEdgeLengthB(basegfx::B3DVector(aEndB - aStartB).getLength());
     173        7680 :                         fPolygonPosB += fEdgeLengthB;
     174        7680 :                         const double fRelTexBR(fPolygonPosB * fTexHorMultiplicatorB);
     175             : 
     176        7680 :                         aNew.setTextureCoordinate(0L, basegfx::B2DPoint(fRelTexAL, fTexVerStart));
     177        7680 :                         aNew.setTextureCoordinate(1L, basegfx::B2DPoint(fRelTexBL, fTexVerStop));
     178        7680 :                         aNew.setTextureCoordinate(2L, basegfx::B2DPoint(fRelTexBR, fTexVerStop));
     179        7680 :                         aNew.setTextureCoordinate(3L, basegfx::B2DPoint(fRelTexAR, fTexVerStart));
     180             :                     }
     181             : 
     182        7988 :                     rTarget.append(aNew);
     183        7988 :                 }
     184             :             }
     185        7757 :         }
     186        3149 :     }
     187             : 
     188         154 :     void impSetNormal(
     189             :         basegfx::B3DPolyPolygon& rCandidate,
     190             :         const basegfx::B3DVector& rNormal)
     191             :     {
     192         308 :         for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
     193             :         {
     194         154 :             basegfx::B3DPolygon aSub(rCandidate.getB3DPolygon(a));
     195             : 
     196         770 :             for(sal_uInt32 b(0L); b < aSub.count(); b++)
     197             :             {
     198         616 :                 aSub.setNormal(b, rNormal);
     199             :             }
     200             : 
     201         154 :             rCandidate.setB3DPolygon(a, aSub);
     202         154 :         }
     203         154 :     }
     204             : 
     205        9293 :     void impCreateInBetweenNormals(
     206             :         basegfx::B3DPolyPolygon& rPolA,
     207             :         basegfx::B3DPolyPolygon& rPolB,
     208             :         bool bSmoothHorizontalNormals)
     209             :     {
     210             :         OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
     211        9293 :         const sal_uInt32 nPolygonCount(::std::min(rPolA.count(), rPolB.count()));
     212             : 
     213       32410 :         for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     214             :         {
     215       23117 :             basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
     216       46234 :             basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
     217             :             OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
     218       23117 :             const sal_uInt32 nPointCount(::std::min(aSubA.count(), aSubB.count()));
     219             : 
     220       23117 :             if(nPointCount)
     221             :             {
     222       23117 :                 basegfx::B3DPoint aPrevA(aSubA.getB3DPoint(nPointCount - 1L));
     223       46234 :                 basegfx::B3DPoint aCurrA(aSubA.getB3DPoint(0L));
     224       23117 :                 const bool bClosed(aSubA.isClosed());
     225             : 
     226       69505 :                 for(sal_uInt32 b(0L); b < nPointCount; b++)
     227             :                 {
     228       46388 :                     const sal_uInt32 nIndNext((b + 1L) % nPointCount);
     229       46388 :                     const basegfx::B3DPoint aNextA(aSubA.getB3DPoint(nIndNext));
     230       92776 :                     const basegfx::B3DPoint aCurrB(aSubB.getB3DPoint(b));
     231             : 
     232             :                     // vector to back
     233       92776 :                     basegfx::B3DVector aDepth(aCurrB - aCurrA);
     234       46388 :                     aDepth.normalize();
     235             : 
     236       46388 :                     if(aDepth.equalZero())
     237             :                     {
     238             :                         // no difference, try to get depth from next point
     239       16896 :                         const basegfx::B3DPoint aNextB(aSubB.getB3DPoint(nIndNext));
     240       16896 :                         aDepth = aNextB - aNextA;
     241       16896 :                         aDepth.normalize();
     242             :                     }
     243             : 
     244             :                     // vector to left (correct for non-closed lines)
     245       46388 :                     const bool bFirstAndNotClosed(!bClosed && 0L == b);
     246       92776 :                     basegfx::B3DVector aLeft(bFirstAndNotClosed ? aCurrA - aNextA : aPrevA - aCurrA);
     247       46388 :                     aLeft.normalize();
     248             : 
     249             :                     // create left normal
     250       92776 :                     const basegfx::B3DVector aNormalLeft(aDepth.getPerpendicular(aLeft));
     251             : 
     252       46388 :                     if(bSmoothHorizontalNormals)
     253             :                     {
     254             :                         // vector to right (correct for non-closed lines)
     255       46388 :                         const bool bLastAndNotClosed(!bClosed && b + 1L == nPointCount);
     256       46388 :                         basegfx::B3DVector aRight(bLastAndNotClosed ? aCurrA - aPrevA : aNextA - aCurrA);
     257       46388 :                         aRight.normalize();
     258             : 
     259             :                         // create right normal
     260       92776 :                         const basegfx::B3DVector aNormalRight(aRight.getPerpendicular(aDepth));
     261             : 
     262             :                         // create smoothed in-between normal
     263       92776 :                         basegfx::B3DVector aNewNormal(aNormalLeft + aNormalRight);
     264       46388 :                         aNewNormal.normalize();
     265             : 
     266             :                         // set as new normal at polygons
     267       46388 :                         aSubA.setNormal(b, aNewNormal);
     268       92776 :                         aSubB.setNormal(b, aNewNormal);
     269             :                     }
     270             :                     else
     271             :                     {
     272             :                         // set aNormalLeft as new normal at polygons
     273           0 :                         aSubA.setNormal(b, aNormalLeft);
     274           0 :                         aSubB.setNormal(b, aNormalLeft);
     275             :                     }
     276             : 
     277             :                     // prepare next step
     278       46388 :                     aPrevA = aCurrA;
     279       46388 :                     aCurrA = aNextA;
     280       46388 :                 }
     281             : 
     282       23117 :                 rPolA.setB3DPolygon(a, aSubA);
     283       46234 :                 rPolB.setB3DPolygon(a, aSubB);
     284             :             }
     285       23117 :         }
     286        9293 :     }
     287             : 
     288        6298 :     void impMixNormals(
     289             :         basegfx::B3DPolyPolygon& rPolA,
     290             :         const basegfx::B3DPolyPolygon& rPolB,
     291             :         double fWeightA)
     292             :     {
     293        6298 :         const double fWeightB(1.0 - fWeightA);
     294             :         OSL_ENSURE(rPolA.count() == rPolB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
     295        6298 :         const sal_uInt32 nPolygonCount(::std::min(rPolA.count(), rPolB.count()));
     296             : 
     297       21812 :         for(sal_uInt32 a(0L); a < nPolygonCount; a++)
     298             :         {
     299       15514 :             basegfx::B3DPolygon aSubA(rPolA.getB3DPolygon(a));
     300       31028 :             const basegfx::B3DPolygon aSubB(rPolB.getB3DPolygon(a));
     301             :             OSL_ENSURE(aSubA.count() == aSubB.count(), "sdrExtrudePrimitive3D: unequally sized polygons (!)");
     302       15514 :             const sal_uInt32 nPointCount(::std::min(aSubA.count(), aSubB.count()));
     303             : 
     304       46850 :             for(sal_uInt32 b(0L); b < nPointCount; b++)
     305             :             {
     306       31336 :                 const basegfx::B3DVector aVA(aSubA.getNormal(b) * fWeightA);
     307       62672 :                 const basegfx::B3DVector aVB(aSubB.getNormal(b) * fWeightB);
     308       62672 :                 basegfx::B3DVector aVNew(aVA + aVB);
     309       31336 :                 aVNew.normalize();
     310       31336 :                 aSubA.setNormal(b, aVNew);
     311       31336 :             }
     312             : 
     313       15514 :             rPolA.setB3DPolygon(a, aSubA);
     314       15514 :         }
     315        6298 :     }
     316             : 
     317        2120 :     bool impHasCutWith(const basegfx::B2DPolygon& rPoly, const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd)
     318             :     {
     319             :         // polygon is closed, one of the points is a member
     320        2120 :         const sal_uInt32 nPointCount(rPoly.count());
     321             : 
     322        2120 :         if(nPointCount)
     323             :         {
     324        2120 :             basegfx::B2DPoint aCurrent(rPoly.getB2DPoint(0));
     325        3288 :             const basegfx::B2DVector aVector(rEnd - rStart);
     326             : 
     327       52506 :             for(sal_uInt32 a(0); a < nPointCount; a++)
     328             :             {
     329       51338 :                 const sal_uInt32 nNextIndex((a + 1) % nPointCount);
     330       51338 :                 const basegfx::B2DPoint aNext(rPoly.getB2DPoint(nNextIndex));
     331      101724 :                 const basegfx::B2DVector aEdgeVector(aNext - aCurrent);
     332             : 
     333       51338 :                 if(basegfx::tools::findCut(
     334             :                     rStart, aVector,
     335       51338 :                     aCurrent, aEdgeVector) != CutFlagValue::NONE)
     336             :                 {
     337         952 :                     return true;
     338             :                 }
     339             : 
     340       50386 :                 aCurrent = aNext;
     341       51554 :             }
     342             :         }
     343             : 
     344        1168 :         return false;
     345             :     }
     346             : } // end of anonymous namespace
     347             : 
     348             : 
     349             : 
     350             : namespace drawinglayer
     351             : {
     352             :     namespace primitive3d
     353             :     {
     354         183 :         void createLatheSlices(
     355             :             Slice3DVector& rSliceVector,
     356             :             const basegfx::B2DPolyPolygon& rSource,
     357             :             double fBackScale,
     358             :             double fDiagonal,
     359             :             double fRotation,
     360             :             sal_uInt32 nSteps,
     361             :             bool bCharacterMode,
     362             :             bool bCloseFront,
     363             :             bool bCloseBack)
     364             :         {
     365         183 :             if(basegfx::fTools::equalZero(fRotation) || 0L == nSteps)
     366             :             {
     367             :                 // no rotation or no steps, just one plane
     368           0 :                 rSliceVector.push_back(Slice3D(rSource, basegfx::B3DHomMatrix()));
     369             :             }
     370             :             else
     371             :             {
     372         183 :                 const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
     373         183 :                 const bool bClosedRotation(!bBackScale && basegfx::fTools::equal(fRotation, F_2PI));
     374         183 :                 basegfx::B2DPolyPolygon aFront(rSource);
     375         366 :                 basegfx::B2DPolyPolygon aBack(rSource);
     376         366 :                 basegfx::B3DHomMatrix aTransformBack;
     377         366 :                 basegfx::B2DPolyPolygon aOuterBack;
     378             : 
     379         183 :                 if(bClosedRotation)
     380             :                 {
     381         183 :                     bCloseFront = bCloseBack = false;
     382             :                 }
     383             : 
     384         183 :                 if(bBackScale)
     385             :                 {
     386             :                     // avoid null zoom
     387           0 :                     if(basegfx::fTools::equalZero(fBackScale))
     388             :                     {
     389           0 :                         fBackScale = 0.000001;
     390             :                     }
     391             : 
     392             :                     // back is scaled compared to front, create scaled version
     393           0 :                     aBack = impScalePolyPolygonOnCenter(aBack, fBackScale);
     394             :                 }
     395             : 
     396         183 :                 if(bCloseFront || bCloseBack)
     397             :                 {
     398           0 :                     const basegfx::B2DRange aBaseRange(basegfx::tools::getRange(aFront));
     399           0 :                     const double fOuterLength(aBaseRange.getMaxX() * fRotation);
     400           0 :                     const double fInnerLength(aBaseRange.getMinX() * fRotation);
     401           0 :                     const double fAverageLength((fOuterLength + fInnerLength) * 0.5);
     402             : 
     403           0 :                     if(bCloseFront)
     404             :                     {
     405           0 :                         const double fOffsetLen((fAverageLength / 12.0) * fDiagonal);
     406           0 :                         basegfx::B2DPolyPolygon aOuterFront;
     407           0 :                         impGetOuterPolyPolygon(aFront, aOuterFront, fOffsetLen, bCharacterMode);
     408           0 :                         basegfx::B3DHomMatrix aTransform;
     409           0 :                         aTransform.translate(0.0, 0.0, fOffsetLen);
     410           0 :                         rSliceVector.push_back(Slice3D(aOuterFront, aTransform, SLICETYPE3D_FRONTCAP));
     411             :                     }
     412             : 
     413           0 :                     if(bCloseBack)
     414             :                     {
     415           0 :                         const double fOffsetLen((fAverageLength / 12.0) * fDiagonal);
     416           0 :                         impGetOuterPolyPolygon(aBack, aOuterBack, fOffsetLen, bCharacterMode);
     417           0 :                         aTransformBack.translate(0.0, 0.0, -fOffsetLen);
     418           0 :                         aTransformBack.rotate(0.0, fRotation, 0.0);
     419             :                     }
     420             :                 }
     421             : 
     422             :                 // add start polygon (a = 0L)
     423         183 :                 if(!bClosedRotation)
     424             :                 {
     425           0 :                     rSliceVector.push_back(Slice3D(aFront, basegfx::B3DHomMatrix()));
     426             :                 }
     427             : 
     428             :                 // create segments (a + 1 .. nSteps)
     429         183 :                 const double fStepSize(1.0 / (double)nSteps);
     430             : 
     431        5535 :                 for(sal_uInt32 a(0L); a < nSteps; a++)
     432             :                 {
     433        5352 :                     const double fStep((double)(a + 1L) * fStepSize);
     434        5352 :                     basegfx::B2DPolyPolygon aNewPoly(bBackScale ? basegfx::tools::interpolate(aFront, aBack, fStep) : aFront);
     435       10704 :                     basegfx::B3DHomMatrix aNewMat;
     436        5352 :                     aNewMat.rotate(0.0, fRotation * fStep, 0.0);
     437        5352 :                     rSliceVector.push_back(Slice3D(aNewPoly, aNewMat));
     438        5352 :                 }
     439             : 
     440         183 :                 if(bCloseBack)
     441             :                 {
     442           0 :                     rSliceVector.push_back(Slice3D(aOuterBack, aTransformBack, SLICETYPE3D_BACKCAP));
     443         183 :                 }
     444             :             }
     445         183 :         }
     446             : 
     447        4145 :         void createExtrudeSlices(
     448             :             Slice3DVector& rSliceVector,
     449             :             const basegfx::B2DPolyPolygon& rSource,
     450             :             double fBackScale,
     451             :             double fDiagonal,
     452             :             double fDepth,
     453             :             bool bCharacterMode,
     454             :             bool bCloseFront,
     455             :             bool bCloseBack)
     456             :         {
     457        4145 :             if(basegfx::fTools::equalZero(fDepth))
     458             :             {
     459             :                 // no depth, just one plane
     460           0 :                 rSliceVector.push_back(Slice3D(rSource, basegfx::B3DHomMatrix()));
     461             :             }
     462             :             else
     463             :             {
     464             :                 // there is depth, create Polygons for front,back and their default depth positions
     465        4145 :                 basegfx::B2DPolyPolygon aFront(rSource);
     466        8290 :                 basegfx::B2DPolyPolygon aBack(rSource);
     467        4145 :                 const bool bBackScale(!basegfx::fTools::equal(fBackScale, 1.0));
     468        4145 :                 double fZFront(fDepth); // default depth for aFront
     469        4145 :                 double fZBack(0.0); // default depth for aBack
     470        8290 :                 basegfx::B2DPolyPolygon aOuterBack;
     471             : 
     472        4145 :                 if(bBackScale)
     473             :                 {
     474             :                     // avoid null zoom
     475           0 :                     if(basegfx::fTools::equalZero(fBackScale))
     476             :                     {
     477           0 :                         fBackScale = 0.000001;
     478             :                     }
     479             : 
     480             :                     // aFront is scaled compared to aBack, create scaled version
     481           0 :                     aFront = impScalePolyPolygonOnCenter(aFront, fBackScale);
     482             :                 }
     483             : 
     484        4145 :                 if(bCloseFront)
     485             :                 {
     486        4145 :                     const double fOffset(fDepth * fDiagonal * 0.5);
     487        4145 :                     fZFront = fDepth - fOffset;
     488        4145 :                     basegfx::B2DPolyPolygon aOuterFront;
     489        4145 :                     impGetOuterPolyPolygon(aFront, aOuterFront, fOffset, bCharacterMode);
     490        8290 :                     basegfx::B3DHomMatrix aTransformFront;
     491        4145 :                     aTransformFront.translate(0.0, 0.0, fDepth);
     492        8290 :                     rSliceVector.push_back(Slice3D(aOuterFront, aTransformFront, SLICETYPE3D_FRONTCAP));
     493             :                 }
     494             : 
     495        4145 :                 if(bCloseBack)
     496             :                 {
     497        4145 :                     const double fOffset(fDepth * fDiagonal * 0.5);
     498        4145 :                     fZBack = fOffset;
     499        4145 :                     impGetOuterPolyPolygon(aBack, aOuterBack, fOffset, bCharacterMode);
     500             :                 }
     501             : 
     502             :                 // add front and back polygons at evtl. changed depths
     503             :                 {
     504        8290 :                     basegfx::B3DHomMatrix aTransformA, aTransformB;
     505             : 
     506        4145 :                     aTransformA.translate(0.0, 0.0, fZFront);
     507        4145 :                     rSliceVector.push_back(Slice3D(aFront, aTransformA));
     508             : 
     509        4145 :                     aTransformB.translate(0.0, 0.0, fZBack);
     510        8290 :                     rSliceVector.push_back(Slice3D(aBack, aTransformB));
     511             :                 }
     512             : 
     513        4145 :                 if(bCloseBack)
     514             :                 {
     515        4145 :                     rSliceVector.push_back(Slice3D(aOuterBack, basegfx::B3DHomMatrix(), SLICETYPE3D_BACKCAP));
     516        4145 :                 }
     517             :             }
     518        4145 :         }
     519             : 
     520          48 :         basegfx::B3DPolyPolygon extractHorizontalLinesFromSlice(const Slice3DVector& rSliceVector, bool bCloseHorLines)
     521             :         {
     522          48 :             basegfx::B3DPolyPolygon aRetval;
     523          48 :             const sal_uInt32 nNumSlices(rSliceVector.size());
     524             : 
     525          48 :             if(nNumSlices)
     526             :             {
     527          48 :                 const sal_uInt32 nSlideSubPolygonCount(rSliceVector[0].getB3DPolyPolygon().count());
     528             : 
     529         168 :                 for(sal_uInt32 b(0); b < nSlideSubPolygonCount; b++)
     530             :                 {
     531         120 :                     const sal_uInt32 nSubPolygonPointCount(rSliceVector[0].getB3DPolyPolygon().getB3DPolygon(b).count());
     532             : 
     533         360 :                     for(sal_uInt32 c(0); c < nSubPolygonPointCount; c++)
     534             :                     {
     535         240 :                         basegfx::B3DPolygon aNew;
     536             : 
     537        7920 :                         for(sal_uInt32 d(0); d < nNumSlices; d++)
     538             :                         {
     539        7680 :                             const bool bSamePolygonCount(nSlideSubPolygonCount == rSliceVector[d].getB3DPolyPolygon().count());
     540        7680 :                             const bool bSamePointCount(nSubPolygonPointCount == rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).count());
     541             : 
     542        7680 :                             if(bSamePolygonCount && bSamePointCount)
     543             :                             {
     544        7680 :                                 aNew.append(rSliceVector[d].getB3DPolyPolygon().getB3DPolygon(b).getB3DPoint(c));
     545             :                             }
     546             :                             else
     547             :                             {
     548             :                                 OSL_ENSURE(bSamePolygonCount, "Slice tools::PolyPolygon with different Polygon count (!)");
     549             :                                 OSL_ENSURE(bSamePointCount, "Slice Polygon with different point count (!)");
     550             :                             }
     551             :                         }
     552             : 
     553         240 :                         aNew.setClosed(bCloseHorLines);
     554         240 :                         aRetval.append(aNew);
     555         240 :                     }
     556             :                 }
     557             :             }
     558             : 
     559          48 :             return aRetval;
     560             :         }
     561             : 
     562           0 :         basegfx::B3DPolyPolygon  extractVerticalLinesFromSlice(const Slice3DVector& rSliceVector)
     563             :         {
     564           0 :             basegfx::B3DPolyPolygon aRetval;
     565           0 :             const sal_uInt32 nNumSlices(rSliceVector.size());
     566             : 
     567           0 :             for(sal_uInt32 a(0L); a < nNumSlices; a++)
     568             :             {
     569           0 :                 aRetval.append(rSliceVector[a].getB3DPolyPolygon());
     570             :             }
     571             : 
     572           0 :             return aRetval;
     573             :         }
     574             : 
     575         173 :         void extractPlanesFromSlice(
     576             :             ::std::vector< basegfx::B3DPolyPolygon >& rFill,
     577             :             const Slice3DVector& rSliceVector,
     578             :             bool bCreateNormals,
     579             :             bool bSmoothHorizontalNormals,
     580             :             bool bSmoothNormals,
     581             :             bool bSmoothLids,
     582             :             bool bClosed,
     583             :             double fSmoothNormalsMix,
     584             :             double fSmoothLidsMix,
     585             :             bool bCreateTextureCoordinates,
     586             :             const basegfx::B2DHomMatrix& rTexTransform)
     587             :         {
     588         173 :             const sal_uInt32 nNumSlices(rSliceVector.size());
     589             : 
     590         173 :             if(nNumSlices)
     591             :             {
     592             :                 // common parameters
     593         173 :                 const sal_uInt32 nLoopCount(bClosed ? nNumSlices : nNumSlices - 1L);
     594         173 :                 basegfx::B3DPolyPolygon aEdgeRounding;
     595             :                 sal_uInt32 a;
     596             : 
     597             :                 // tetxture parameters
     598         173 :                 double fInvTexHeight(1.0);
     599         173 :                 double fTexHeightPos(0.0);
     600         173 :                 double fTexStart(0.0);
     601         173 :                 double fTexStop(1.0);
     602         346 :                 ::std::vector<double> aTexHeightArray;
     603         173 :                 basegfx::B3DRange aTexRangeFront;
     604         173 :                 basegfx::B3DRange aTexRangeBack;
     605             : 
     606         173 :                 if(bCreateTextureCoordinates)
     607             :                 {
     608          96 :                     aTexRangeFront = basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon());
     609          96 :                     aTexRangeBack = basegfx::tools::getRange(rSliceVector[nNumSlices - 1L].getB3DPolyPolygon());
     610             : 
     611          96 :                     if(aTexRangeBack.getDepth() > aTexRangeBack.getWidth())
     612             :                     {
     613             :                         // last polygon is rotated so that depth is bigger than width, exchange X and Z
     614             :                         // for making applyDefaultTextureCoordinatesParallel use Z instead of X for
     615             :                         // horizontal texture coordinate
     616             :                         aTexRangeBack = basegfx::B3DRange(
     617             :                             aTexRangeBack.getMinZ(), aTexRangeBack.getMinY(), aTexRangeBack.getMinX(),
     618           0 :                             aTexRangeBack.getMaxZ(), aTexRangeBack.getMaxY(), aTexRangeBack.getMaxX());
     619             :                     }
     620             : 
     621          96 :                     basegfx::B3DPoint aCenter(basegfx::tools::getRange(rSliceVector[0L].getB3DPolyPolygon()).getCenter());
     622             : 
     623        3168 :                     for(a = 0L; a < nLoopCount; a++)
     624             :                     {
     625        3072 :                         const basegfx::B3DPoint aNextCenter(basegfx::tools::getRange(rSliceVector[(a + 1L) % nNumSlices].getB3DPolyPolygon()).getCenter());
     626        3072 :                         const double fLength(basegfx::B3DVector(aNextCenter - aCenter).getLength());
     627        3072 :                         aTexHeightArray.push_back(fLength);
     628        3072 :                         aCenter = aNextCenter;
     629        3072 :                     }
     630             : 
     631          96 :                     const double fTexHeight(::std::accumulate(aTexHeightArray.begin(), aTexHeightArray.end(), 0.0));
     632             : 
     633          96 :                     if(!basegfx::fTools::equalZero(fTexHeight))
     634             :                     {
     635          96 :                         fInvTexHeight = 1.0 / fTexHeight;
     636          96 :                     }
     637             :                 }
     638             : 
     639         173 :                 if(nLoopCount)
     640             :                 {
     641        3476 :                     for(a = 0L; a < nLoopCount; a++)
     642             :                     {
     643        3303 :                         const Slice3D& rSliceA(rSliceVector[a]);
     644        3303 :                         const Slice3D& rSliceB(rSliceVector[(a + 1L) % nNumSlices]);
     645        3303 :                         const bool bAcceptPair(SLICETYPE3D_REGULAR == rSliceA.getSliceType() && SLICETYPE3D_REGULAR == rSliceB.getSliceType());
     646        3303 :                         basegfx::B3DPolyPolygon aPolA(rSliceA.getB3DPolyPolygon());
     647        6606 :                         basegfx::B3DPolyPolygon aPolB(rSliceB.getB3DPolyPolygon());
     648             : 
     649        3303 :                         if(bAcceptPair)
     650             :                         {
     651        3149 :                             if(bCreateNormals)
     652             :                             {
     653        3149 :                                 impCreateInBetweenNormals(aPolB, aPolA, bSmoothHorizontalNormals);
     654             :                             }
     655             : 
     656             :                             {
     657        3149 :                                 const sal_uInt32 nIndPrev((a + nNumSlices - 1L) % nNumSlices);
     658        3149 :                                 const Slice3D& rSlicePrev(rSliceVector[nIndPrev]);
     659        3149 :                                 basegfx::B3DPolyPolygon aPrev(rSlicePrev.getB3DPolyPolygon());
     660        6298 :                                 basegfx::B3DPolyPolygon aPolAA(rSliceA.getB3DPolyPolygon());
     661             : 
     662        3149 :                                 if(SLICETYPE3D_FRONTCAP == rSlicePrev.getSliceType())
     663             :                                 {
     664          77 :                                     basegfx::B3DPolyPolygon aFront(rSlicePrev.getB3DPolyPolygon());
     665          77 :                                     const bool bHasSlant(aPolAA != aPrev);
     666             : 
     667          77 :                                     if(bCreateTextureCoordinates)
     668             :                                     {
     669           0 :                                         aFront = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront);
     670             :                                     }
     671             : 
     672          77 :                                     if(bCreateNormals)
     673             :                                     {
     674          77 :                                         basegfx::B3DVector aNormal(0.0, 0.0, -1.0);
     675             : 
     676          77 :                                         if(aFront.count())
     677             :                                         {
     678          77 :                                             aNormal = -aFront.getB3DPolygon(0L).getNormal();
     679             :                                         }
     680             : 
     681          77 :                                         impSetNormal(aFront, aNormal);
     682             : 
     683          77 :                                         if(bHasSlant)
     684             :                                         {
     685           0 :                                             impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals);
     686             : 
     687           0 :                                             if(bSmoothNormals)
     688             :                                             {
     689             :                                                 // smooth and copy
     690           0 :                                                 impMixNormals(aPolA, aPolAA, fSmoothNormalsMix);
     691           0 :                                                 aPolAA = aPolA;
     692             :                                             }
     693             :                                             else
     694             :                                             {
     695             :                                                 // take over from surface
     696           0 :                                                 aPolAA = aPolA;
     697             :                                             }
     698             : 
     699           0 :                                             if(bSmoothLids)
     700             :                                             {
     701             :                                                 // smooth and copy
     702           0 :                                                 impMixNormals(aFront, aPrev, fSmoothLidsMix);
     703           0 :                                                 aPrev = aFront;
     704             :                                             }
     705             :                                             else
     706             :                                             {
     707             :                                                 // take over from front
     708           0 :                                                 aPrev = aFront;
     709             :                                             }
     710             :                                         }
     711             :                                         else
     712             :                                         {
     713          77 :                                             if(bSmoothNormals)
     714             :                                             {
     715             :                                                 // smooth
     716          77 :                                                 impMixNormals(aPolA, aFront, fSmoothNormalsMix);
     717             :                                             }
     718             : 
     719          77 :                                             if(bSmoothLids)
     720             :                                             {
     721             :                                                 // smooth and copy
     722           0 :                                                 impMixNormals(aFront, aPolA, fSmoothLidsMix);
     723           0 :                                                 aPolA = aFront;
     724             :                                             }
     725          77 :                                         }
     726             :                                     }
     727             : 
     728          77 :                                     if(bHasSlant)
     729             :                                     {
     730           0 :                                         if(bCreateTextureCoordinates)
     731             :                                         {
     732           0 :                                             fTexStart = fTexHeightPos * fInvTexHeight;
     733           0 :                                             fTexStop = (fTexHeightPos - aTexHeightArray[(a + nLoopCount - 1L) % nLoopCount]) * fInvTexHeight;
     734             :                                         }
     735             : 
     736           0 :                                         impAddInBetweenFill(aEdgeRounding, aPolAA, aPrev, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
     737             :                                     }
     738             : 
     739          77 :                                     aFront.flip();
     740          77 :                                     rFill.push_back(aFront);
     741             :                                 }
     742             :                                 else
     743             :                                 {
     744        3072 :                                     if(bCreateNormals && bSmoothNormals && (nIndPrev != a + 1L))
     745             :                                     {
     746        3072 :                                         impCreateInBetweenNormals(aPolAA, aPrev, bSmoothHorizontalNormals);
     747        3072 :                                         impMixNormals(aPolA, aPolAA, 0.5);
     748             :                                     }
     749        3149 :                                 }
     750             :                             }
     751             : 
     752             :                             {
     753        3149 :                                 const sal_uInt32 nIndNext((a + 2L) % nNumSlices);
     754        3149 :                                 const Slice3D& rSliceNext(rSliceVector[nIndNext]);
     755        3149 :                                 basegfx::B3DPolyPolygon aNext(rSliceNext.getB3DPolyPolygon());
     756        6298 :                                 basegfx::B3DPolyPolygon aPolBB(rSliceB.getB3DPolyPolygon());
     757             : 
     758        3149 :                                 if(SLICETYPE3D_BACKCAP == rSliceNext.getSliceType())
     759             :                                 {
     760          77 :                                     basegfx::B3DPolyPolygon aBack(rSliceNext.getB3DPolyPolygon());
     761          77 :                                     const bool bHasSlant(aPolBB != aNext);
     762             : 
     763          77 :                                     if(bCreateTextureCoordinates)
     764             :                                     {
     765           0 :                                         aBack = basegfx::tools::applyDefaultTextureCoordinatesParallel(aBack, aTexRangeBack);
     766             :                                     }
     767             : 
     768          77 :                                     if(bCreateNormals)
     769             :                                     {
     770          77 :                                         const basegfx::B3DVector aNormal(aBack.count() ? aBack.getB3DPolygon(0L).getNormal() : basegfx::B3DVector(0.0, 0.0, 1.0));
     771          77 :                                         impSetNormal(aBack, aNormal);
     772             : 
     773          77 :                                         if(bHasSlant)
     774             :                                         {
     775           0 :                                             impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals);
     776             : 
     777           0 :                                             if(bSmoothNormals)
     778             :                                             {
     779             :                                                 // smooth and copy
     780           0 :                                                 impMixNormals(aPolB, aPolBB, fSmoothNormalsMix);
     781           0 :                                                 aPolBB = aPolB;
     782             :                                             }
     783             :                                             else
     784             :                                             {
     785             :                                                 // take over from surface
     786           0 :                                                 aPolBB = aPolB;
     787             :                                             }
     788             : 
     789           0 :                                             if(bSmoothLids)
     790             :                                             {
     791             :                                                 // smooth and copy
     792           0 :                                                 impMixNormals(aBack, aNext, fSmoothLidsMix);
     793           0 :                                                 aNext = aBack;
     794             :                                             }
     795             :                                             else
     796             :                                             {
     797             :                                                 // take over from back
     798           0 :                                                 aNext = aBack;
     799             :                                             }
     800             :                                         }
     801             :                                         else
     802             :                                         {
     803          77 :                                             if(bSmoothNormals)
     804             :                                             {
     805             :                                                 // smooth
     806          77 :                                                 impMixNormals(aPolB, aBack, fSmoothNormalsMix);
     807             :                                             }
     808             : 
     809          77 :                                             if(bSmoothLids)
     810             :                                             {
     811             :                                                 // smooth and copy
     812           0 :                                                 impMixNormals(aBack, aPolB, fSmoothLidsMix);
     813           0 :                                                 aPolB = aBack;
     814             :                                             }
     815          77 :                                         }
     816             :                                     }
     817             : 
     818          77 :                                     if(bHasSlant)
     819             :                                     {
     820           0 :                                         if(bCreateTextureCoordinates)
     821             :                                         {
     822           0 :                                             fTexStart = (fTexHeightPos + aTexHeightArray[a] + aTexHeightArray[(a + 1L) % nLoopCount]) * fInvTexHeight;
     823           0 :                                             fTexStop = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight;
     824             :                                         }
     825             : 
     826           0 :                                         impAddInBetweenFill(aEdgeRounding, aNext, aPolBB, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
     827             :                                     }
     828             : 
     829          77 :                                     rFill.push_back(aBack);
     830             :                                 }
     831             :                                 else
     832             :                                 {
     833        3072 :                                     if(bCreateNormals && bSmoothNormals && (nIndNext != a))
     834             :                                     {
     835        3072 :                                         impCreateInBetweenNormals(aNext, aPolBB, bSmoothHorizontalNormals);
     836        3072 :                                         impMixNormals(aPolB, aPolBB, 0.5);
     837             :                                     }
     838        3149 :                                 }
     839             :                             }
     840             : 
     841        3149 :                             if(bCreateTextureCoordinates)
     842             :                             {
     843        3072 :                                 fTexStart = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight;
     844        3072 :                                 fTexStop = fTexHeightPos * fInvTexHeight;
     845             :                             }
     846             : 
     847        3149 :                             impAddInBetweenFill(aEdgeRounding, aPolB, aPolA, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates);
     848             :                         }
     849             : 
     850        3303 :                         if(bCreateTextureCoordinates)
     851             :                         {
     852        3072 :                             fTexHeightPos += aTexHeightArray[a];
     853             :                         }
     854        3303 :                     }
     855             :                 }
     856             :                 else
     857             :                 {
     858             :                     // no loop, but a single slice (1 == nNumSlices), create a filling from the single
     859             :                     // front plane
     860           0 :                     const Slice3D& rSlice(rSliceVector[0]);
     861           0 :                     basegfx::B3DPolyPolygon aFront(rSlice.getB3DPolyPolygon());
     862             : 
     863           0 :                     if(bCreateTextureCoordinates)
     864             :                     {
     865           0 :                         aFront = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront);
     866             :                     }
     867             : 
     868           0 :                     if(bCreateNormals)
     869             :                     {
     870           0 :                         basegfx::B3DVector aNormal(0.0, 0.0, -1.0);
     871             : 
     872           0 :                         if(aFront.count())
     873             :                         {
     874           0 :                             aNormal = -aFront.getB3DPolygon(0L).getNormal();
     875             :                         }
     876             : 
     877           0 :                         impSetNormal(aFront, aNormal);
     878             :                     }
     879             : 
     880           0 :                     aFront.flip();
     881           0 :                     rFill.push_back(aFront);
     882             :                 }
     883             : 
     884         173 :                 if(bCreateTextureCoordinates)
     885             :                 {
     886          96 :                     aEdgeRounding.transformTextureCoordiantes(rTexTransform);
     887             :                 }
     888             : 
     889        8161 :                 for(a = 0L; a < aEdgeRounding.count(); a++)
     890             :                 {
     891        7988 :                     rFill.push_back(basegfx::B3DPolyPolygon(aEdgeRounding.getB3DPolygon(a)));
     892         173 :                 }
     893             :             }
     894         173 :         }
     895             : 
     896         192 :         void createReducedOutlines(
     897             :             const geometry::ViewInformation3D& rViewInformation,
     898             :             const basegfx::B3DHomMatrix& rObjectTransform,
     899             :             const basegfx::B3DPolygon& rLoopA,
     900             :             const basegfx::B3DPolygon& rLoopB,
     901             :             basegfx::B3DPolyPolygon& rTarget)
     902             :         {
     903         192 :             const sal_uInt32 nPointCount(rLoopA.count());
     904             : 
     905             :             // with idetic polygons there are no outlines
     906         192 :             if(rLoopA != rLoopB)
     907             :             {
     908         120 :                 if(nPointCount && nPointCount == rLoopB.count())
     909             :                 {
     910         120 :                     const basegfx::B3DHomMatrix aObjectTransform(rViewInformation.getObjectToView() * rObjectTransform);
     911         240 :                     const basegfx::B2DPolygon a2DLoopA(basegfx::tools::createB2DPolygonFromB3DPolygon(rLoopA, aObjectTransform));
     912         240 :                     const basegfx::B2DPolygon a2DLoopB(basegfx::tools::createB2DPolygonFromB3DPolygon(rLoopB, aObjectTransform));
     913         240 :                     const basegfx::B2DPoint a2DCenterA(a2DLoopA.getB2DRange().getCenter());
     914         240 :                     const basegfx::B2DPoint a2DCenterB(a2DLoopB.getB2DRange().getCenter());
     915             : 
     916             :                     // without detectable Y-Axis there are no outlines
     917         120 :                     if(!a2DCenterA.equal(a2DCenterB))
     918             :                     {
     919             :                         // search for outmost left and right inter-loop-edges which do not cut the loops
     920          48 :                         const basegfx::B2DPoint aCommonCenter(basegfx::average(a2DCenterA, a2DCenterB));
     921          96 :                         const basegfx::B2DVector aAxisVector(a2DCenterA - a2DCenterB);
     922          48 :                         double fMaxLeft(0.0);
     923          48 :                         double fMaxRight(0.0);
     924          48 :                         sal_uInt32 nIndexLeft(0);
     925          48 :                         sal_uInt32 nIndexRight(0);
     926             : 
     927        1584 :                         for(sal_uInt32 a(0); a < nPointCount; a++)
     928             :                         {
     929        1536 :                             const basegfx::B2DPoint aStart(a2DLoopA.getB2DPoint(a));
     930        3072 :                             const basegfx::B2DPoint aEnd(a2DLoopB.getB2DPoint(a));
     931        3072 :                             const basegfx::B2DPoint aMiddle(basegfx::average(aStart, aEnd));
     932             : 
     933        1536 :                             if(!basegfx::tools::isInside(a2DLoopA, aMiddle))
     934             :                             {
     935        1464 :                                 if(!basegfx::tools::isInside(a2DLoopB, aMiddle))
     936             :                                 {
     937        1392 :                                     if(!impHasCutWith(a2DLoopA, aStart, aEnd))
     938             :                                     {
     939         728 :                                         if(!impHasCutWith(a2DLoopB, aStart, aEnd))
     940             :                                         {
     941         440 :                                             const basegfx::B2DVector aCandidateVector(aMiddle - aCommonCenter);
     942         440 :                                             const double fCross(aCandidateVector.cross(aAxisVector));
     943         440 :                                             const double fDistance(aCandidateVector.getLength());
     944             : 
     945         440 :                                             if(fCross > 0.0)
     946             :                                             {
     947         216 :                                                 if(fDistance > fMaxLeft)
     948             :                                                 {
     949          72 :                                                     fMaxLeft = fDistance;
     950          72 :                                                     nIndexLeft = a;
     951             :                                                 }
     952             :                                             }
     953         224 :                                             else if(fCross < 0.0)
     954             :                                             {
     955         224 :                                                 if(fDistance > fMaxRight)
     956             :                                                 {
     957         216 :                                                     fMaxRight = fDistance;
     958         216 :                                                     nIndexRight = a;
     959             :                                                 }
     960         440 :                                             }
     961             :                                         }
     962             :                                     }
     963             :                                 }
     964             :                             }
     965        1536 :                         }
     966             : 
     967          48 :                         if(fMaxLeft != 0.0)
     968             :                         {
     969          48 :                             basegfx::B3DPolygon aToBeAdded;
     970          48 :                             aToBeAdded.append(rLoopA.getB3DPoint(nIndexLeft));
     971          48 :                             aToBeAdded.append(rLoopB.getB3DPoint(nIndexLeft));
     972          48 :                             rTarget.append(aToBeAdded);
     973             :                         }
     974             : 
     975          48 :                         if(fMaxRight != 0.0)
     976             :                         {
     977          48 :                             basegfx::B3DPolygon aToBeAdded;
     978          48 :                             aToBeAdded.append(rLoopA.getB3DPoint(nIndexRight));
     979          48 :                             aToBeAdded.append(rLoopB.getB3DPoint(nIndexRight));
     980          48 :                             rTarget.append(aToBeAdded);
     981          48 :                         }
     982         120 :                     }
     983             :                 }
     984             :             }
     985         192 :         }
     986             : 
     987             :     } // end of namespace primitive3d
     988             : } // end of namespace drawinglayer
     989             : 
     990             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11