LCOV - code coverage report
Current view: top level - basegfx/source/polygon - b3dpolygontools.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 53 341 15.5 %
Date: 2014-11-03 Functions: 6 15 40.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <osl/diagnose.h>
      21             : #include <basegfx/polygon/b3dpolygontools.hxx>
      22             : #include <basegfx/polygon/b3dpolygon.hxx>
      23             : #include <basegfx/numeric/ftools.hxx>
      24             : #include <basegfx/range/b3drange.hxx>
      25             : #include <basegfx/point/b2dpoint.hxx>
      26             : #include <basegfx/matrix/b3dhommatrix.hxx>
      27             : #include <basegfx/polygon/b2dpolygon.hxx>
      28             : #include <basegfx/polygon/b2dpolygontools.hxx>
      29             : #include <basegfx/tuple/b3ituple.hxx>
      30             : #include <numeric>
      31             : 
      32             : namespace basegfx
      33             : {
      34             :     namespace tools
      35             :     {
      36             :         // B3DPolygon tools
      37        3497 :         void checkClosed(B3DPolygon& rCandidate)
      38             :         {
      39       23807 :             while(rCandidate.count() > 1L
      40       27080 :                 && rCandidate.getB3DPoint(0L).equal(rCandidate.getB3DPoint(rCandidate.count() - 1L)))
      41             :             {
      42        3273 :                 rCandidate.setClosed(true);
      43        3273 :                 rCandidate.remove(rCandidate.count() - 1L);
      44             :             }
      45        3497 :         }
      46             : 
      47       31328 :         sal_uInt32 getIndexOfSuccessor(sal_uInt32 nIndex, const B3DPolygon& rCandidate)
      48             :         {
      49             :             OSL_ENSURE(nIndex < rCandidate.count(), "getIndexOfPredecessor: Access to polygon out of range (!)");
      50             : 
      51       31328 :             if(nIndex + 1L < rCandidate.count())
      52             :             {
      53       31296 :                 return nIndex + 1L;
      54             :             }
      55             :             else
      56             :             {
      57          32 :                 return 0L;
      58             :             }
      59             :         }
      60             : 
      61      169698 :         B3DRange getRange(const B3DPolygon& rCandidate)
      62             :         {
      63      169698 :             B3DRange aRetval;
      64      169698 :             const sal_uInt32 nPointCount(rCandidate.count());
      65             : 
      66      722958 :             for(sal_uInt32 a(0L); a < nPointCount; a++)
      67             :             {
      68      553260 :                 const B3DPoint aTestPoint(rCandidate.getB3DPoint(a));
      69      553260 :                 aRetval.expand(aTestPoint);
      70      553260 :             }
      71             : 
      72      169698 :             return aRetval;
      73             :         }
      74             : 
      75         723 :         B3DVector getNormal(const B3DPolygon& rCandidate)
      76             :         {
      77         723 :             return rCandidate.getNormal();
      78             :         }
      79             : 
      80       30752 :         double getLength(const B3DPolygon& rCandidate)
      81             :         {
      82       30752 :             double fRetval(0.0);
      83       30752 :             const sal_uInt32 nPointCount(rCandidate.count());
      84             : 
      85       30752 :             if(nPointCount > 1L)
      86             :             {
      87       30752 :                 const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1L);
      88             : 
      89       62080 :                 for(sal_uInt32 a(0L); a < nLoopCount; a++)
      90             :                 {
      91       31328 :                     const sal_uInt32 nNextIndex(getIndexOfSuccessor(a, rCandidate));
      92       31328 :                     const B3DPoint aCurrentPoint(rCandidate.getB3DPoint(a));
      93       62656 :                     const B3DPoint aNextPoint(rCandidate.getB3DPoint(nNextIndex));
      94       62656 :                     const B3DVector aVector(aNextPoint - aCurrentPoint);
      95       31328 :                     fRetval += aVector.getLength();
      96       31328 :                 }
      97             :             }
      98             : 
      99       30752 :             return fRetval;
     100             :         }
     101             : 
     102           0 :         void applyLineDashing(const B3DPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B3DPolyPolygon* pLineTarget, B3DPolyPolygon* pGapTarget, double fDotDashLength)
     103             :         {
     104           0 :             const sal_uInt32 nPointCount(rCandidate.count());
     105           0 :             const sal_uInt32 nDotDashCount(rDotDashArray.size());
     106             : 
     107           0 :             if(fTools::lessOrEqual(fDotDashLength, 0.0))
     108             :             {
     109           0 :                 fDotDashLength = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
     110             :             }
     111             : 
     112           0 :             if(fTools::more(fDotDashLength, 0.0) && (pLineTarget || pGapTarget) && nPointCount)
     113             :             {
     114             :                 // clear targets
     115           0 :                 if(pLineTarget)
     116             :                 {
     117           0 :                     pLineTarget->clear();
     118             :                 }
     119             : 
     120           0 :                 if(pGapTarget)
     121             :                 {
     122           0 :                     pGapTarget->clear();
     123             :                 }
     124             : 
     125             :                 // prepare current edge's start
     126           0 :                 B3DPoint aCurrentPoint(rCandidate.getB3DPoint(0));
     127           0 :                 const sal_uInt32 nEdgeCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
     128             : 
     129             :                 // prepare DotDashArray iteration and the line/gap switching bool
     130           0 :                 sal_uInt32 nDotDashIndex(0);
     131           0 :                 bool bIsLine(true);
     132           0 :                 double fDotDashMovingLength(rDotDashArray[0]);
     133           0 :                 B3DPolygon aSnippet;
     134             : 
     135             :                 // iterate over all edges
     136           0 :                 for(sal_uInt32 a(0); a < nEdgeCount; a++)
     137             :                 {
     138             :                     // update current edge
     139           0 :                     double fLastDotDashMovingLength(0.0);
     140           0 :                     const sal_uInt32 nNextIndex((a + 1) % nPointCount);
     141           0 :                     const B3DPoint aNextPoint(rCandidate.getB3DPoint(nNextIndex));
     142           0 :                     const double fEdgeLength(B3DVector(aNextPoint - aCurrentPoint).getLength());
     143             : 
     144           0 :                     if(!fTools::equalZero(fEdgeLength))
     145             :                     {
     146           0 :                         while(fTools::less(fDotDashMovingLength, fEdgeLength))
     147             :                         {
     148             :                             // new split is inside edge, create and append snippet [fLastDotDashMovingLength, fDotDashMovingLength]
     149           0 :                             const bool bHandleLine(bIsLine && pLineTarget);
     150           0 :                             const bool bHandleGap(!bIsLine && pGapTarget);
     151             : 
     152           0 :                             if(bHandleLine || bHandleGap)
     153             :                             {
     154           0 :                                 if(!aSnippet.count())
     155             :                                 {
     156           0 :                                     aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fLastDotDashMovingLength / fEdgeLength));
     157             :                                 }
     158             : 
     159           0 :                                 aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fDotDashMovingLength / fEdgeLength));
     160             : 
     161           0 :                                 if(bHandleLine)
     162             :                                 {
     163           0 :                                     pLineTarget->append(aSnippet);
     164             :                                 }
     165             :                                 else
     166             :                                 {
     167           0 :                                     pGapTarget->append(aSnippet);
     168             :                                 }
     169             : 
     170           0 :                                 aSnippet.clear();
     171             :                             }
     172             : 
     173             :                             // prepare next DotDashArray step and flip line/gap flag
     174           0 :                             fLastDotDashMovingLength = fDotDashMovingLength;
     175           0 :                             fDotDashMovingLength += rDotDashArray[(++nDotDashIndex) % nDotDashCount];
     176           0 :                             bIsLine = !bIsLine;
     177             :                         }
     178             : 
     179             :                         // append snippet [fLastDotDashMovingLength, fEdgeLength]
     180           0 :                         const bool bHandleLine(bIsLine && pLineTarget);
     181           0 :                         const bool bHandleGap(!bIsLine && pGapTarget);
     182             : 
     183           0 :                         if(bHandleLine || bHandleGap)
     184             :                         {
     185           0 :                             if(!aSnippet.count())
     186             :                             {
     187           0 :                                 aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fLastDotDashMovingLength / fEdgeLength));
     188             :                             }
     189             : 
     190           0 :                             aSnippet.append(aNextPoint);
     191             :                         }
     192             : 
     193             :                         // prepare move to next edge
     194           0 :                         fDotDashMovingLength -= fEdgeLength;
     195             :                     }
     196             : 
     197             :                     // prepare next edge step (end point gets new start point)
     198           0 :                     aCurrentPoint = aNextPoint;
     199           0 :                 }
     200             : 
     201             :                 // append last intermediate results (if exists)
     202           0 :                 if(aSnippet.count())
     203             :                 {
     204           0 :                     if(bIsLine && pLineTarget)
     205             :                     {
     206           0 :                         pLineTarget->append(aSnippet);
     207             :                     }
     208           0 :                     else if(!bIsLine && pGapTarget)
     209             :                     {
     210           0 :                         pGapTarget->append(aSnippet);
     211             :                     }
     212             :                 }
     213             : 
     214             :                 // check if start and end polygon may be merged
     215           0 :                 if(pLineTarget)
     216             :                 {
     217           0 :                     const sal_uInt32 nCount(pLineTarget->count());
     218             : 
     219           0 :                     if(nCount > 1)
     220             :                     {
     221             :                         // these polygons were created above, there exists none with less than two points,
     222             :                         // thus dircet point access below is allowed
     223           0 :                         const B3DPolygon aFirst(pLineTarget->getB3DPolygon(0));
     224           0 :                         B3DPolygon aLast(pLineTarget->getB3DPolygon(nCount - 1));
     225             : 
     226           0 :                         if(aFirst.getB3DPoint(0).equal(aLast.getB3DPoint(aLast.count() - 1)))
     227             :                         {
     228             :                             // start of first and end of last are the same -> merge them
     229           0 :                             aLast.append(aFirst);
     230           0 :                             aLast.removeDoublePoints();
     231           0 :                             pLineTarget->setB3DPolygon(0, aLast);
     232           0 :                             pLineTarget->remove(nCount - 1);
     233           0 :                         }
     234             :                     }
     235             :                 }
     236             : 
     237           0 :                 if(pGapTarget)
     238             :                 {
     239           0 :                     const sal_uInt32 nCount(pGapTarget->count());
     240             : 
     241           0 :                     if(nCount > 1)
     242             :                     {
     243             :                         // these polygons were created above, there exists none with less than two points,
     244             :                         // thus dircet point access below is allowed
     245           0 :                         const B3DPolygon aFirst(pGapTarget->getB3DPolygon(0));
     246           0 :                         B3DPolygon aLast(pGapTarget->getB3DPolygon(nCount - 1));
     247             : 
     248           0 :                         if(aFirst.getB3DPoint(0).equal(aLast.getB3DPoint(aLast.count() - 1)))
     249             :                         {
     250             :                             // start of first and end of last are the same -> merge them
     251           0 :                             aLast.append(aFirst);
     252           0 :                             aLast.removeDoublePoints();
     253           0 :                             pGapTarget->setB3DPolygon(0, aLast);
     254           0 :                             pGapTarget->remove(nCount - 1);
     255           0 :                         }
     256             :                     }
     257           0 :                 }
     258             :             }
     259             :             else
     260             :             {
     261             :                 // parameters make no sense, just add source to targets
     262           0 :                 if(pLineTarget)
     263             :                 {
     264           0 :                     pLineTarget->append(rCandidate);
     265             :                 }
     266             : 
     267           0 :                 if(pGapTarget)
     268             :                 {
     269           0 :                     pGapTarget->append(rCandidate);
     270             :                 }
     271             :             }
     272           0 :         }
     273             : 
     274           0 :         B3DPolygon applyDefaultNormalsSphere( const B3DPolygon& rCandidate, const B3DPoint& rCenter)
     275             :         {
     276           0 :             B3DPolygon aRetval(rCandidate);
     277             : 
     278           0 :             for(sal_uInt32 a(0L); a < aRetval.count(); a++)
     279             :             {
     280           0 :                 B3DVector aVector(aRetval.getB3DPoint(a) - rCenter);
     281           0 :                 aVector.normalize();
     282           0 :                 aRetval.setNormal(a, aVector);
     283           0 :             }
     284             : 
     285           0 :             return aRetval;
     286             :         }
     287             : 
     288           0 :         B3DPolygon invertNormals( const B3DPolygon& rCandidate)
     289             :         {
     290           0 :             B3DPolygon aRetval(rCandidate);
     291             : 
     292           0 :             if(aRetval.areNormalsUsed())
     293             :             {
     294           0 :                 for(sal_uInt32 a(0L); a < aRetval.count(); a++)
     295             :                 {
     296           0 :                     aRetval.setNormal(a, -aRetval.getNormal(a));
     297             :                 }
     298             :             }
     299             : 
     300           0 :             return aRetval;
     301             :         }
     302             : 
     303         692 :         B3DPolygon applyDefaultTextureCoordinatesParallel( const B3DPolygon& rCandidate, const B3DRange& rRange, bool bChangeX, bool bChangeY)
     304             :         {
     305         692 :             B3DPolygon aRetval(rCandidate);
     306             : 
     307         692 :             if(bChangeX || bChangeY)
     308             :             {
     309             :                 // create projection of standard texture coordinates in (X, Y) onto
     310             :                 // the 3d coordinates straight
     311         692 :                 const double fWidth(rRange.getWidth());
     312         692 :                 const double fHeight(rRange.getHeight());
     313         692 :                 const bool bWidthSet(!fTools::equalZero(fWidth));
     314         692 :                 const bool bHeightSet(!fTools::equalZero(fHeight));
     315         692 :                 const double fOne(1.0);
     316             : 
     317        4420 :                 for(sal_uInt32 a(0L); a < aRetval.count(); a++)
     318             :                 {
     319        3728 :                     const B3DPoint aPoint(aRetval.getB3DPoint(a));
     320        7456 :                     B2DPoint aTextureCoordinate(aRetval.getTextureCoordinate(a));
     321             : 
     322        3728 :                     if(bChangeX)
     323             :                     {
     324        3728 :                         if(bWidthSet)
     325             :                         {
     326        3728 :                             aTextureCoordinate.setX((aPoint.getX() - rRange.getMinX()) / fWidth);
     327             :                         }
     328             :                         else
     329             :                         {
     330           0 :                             aTextureCoordinate.setX(0.0);
     331             :                         }
     332             :                     }
     333             : 
     334        3728 :                     if(bChangeY)
     335             :                     {
     336        1904 :                         if(bHeightSet)
     337             :                         {
     338        1904 :                             aTextureCoordinate.setY(fOne - ((aPoint.getY() - rRange.getMinY()) / fHeight));
     339             :                         }
     340             :                         else
     341             :                         {
     342           0 :                             aTextureCoordinate.setY(fOne);
     343             :                         }
     344             :                     }
     345             : 
     346        3728 :                     aRetval.setTextureCoordinate(a, aTextureCoordinate);
     347        3728 :                 }
     348             :             }
     349             : 
     350         692 :             return aRetval;
     351             :         }
     352             : 
     353           0 :         B3DPolygon applyDefaultTextureCoordinatesSphere( const B3DPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX, bool bChangeY)
     354             :         {
     355           0 :             B3DPolygon aRetval(rCandidate);
     356             : 
     357           0 :             if(bChangeX || bChangeY)
     358             :             {
     359             :                 // create texture coordinates using sphere projection to cartesian coordinates,
     360             :                 // use object's center as base
     361           0 :                 const double fOne(1.0);
     362           0 :                 const sal_uInt32 nPointCount(aRetval.count());
     363           0 :                 bool bPolarPoints(false);
     364             :                 sal_uInt32 a;
     365             : 
     366             :                 // create center cartesian coordinates to have a possibility to decide if on boundary
     367             :                 // transitions which value to choose
     368           0 :                 const B3DRange aPlaneRange(getRange(rCandidate));
     369           0 :                 const B3DPoint aPlaneCenter(aPlaneRange.getCenter() - rCenter);
     370           0 :                 const double fXCenter(fOne - ((atan2(aPlaneCenter.getZ(), aPlaneCenter.getX()) + F_PI) / F_2PI));
     371             : 
     372           0 :                 for(a = 0L; a < nPointCount; a++)
     373             :                 {
     374           0 :                     const B3DVector aVector(aRetval.getB3DPoint(a) - rCenter);
     375           0 :                     const double fY(fOne - ((atan2(aVector.getY(), aVector.getXZLength()) + F_PI2) / F_PI));
     376           0 :                     B2DPoint aTexCoor(aRetval.getTextureCoordinate(a));
     377             : 
     378           0 :                     if(fTools::equalZero(fY))
     379             :                     {
     380             :                         // point is a north polar point, no useful X-coordinate can be created.
     381           0 :                         if(bChangeY)
     382             :                         {
     383           0 :                             aTexCoor.setY(0.0);
     384             : 
     385           0 :                             if(bChangeX)
     386             :                             {
     387           0 :                                 bPolarPoints = true;
     388             :                             }
     389             :                         }
     390             :                     }
     391           0 :                     else if(fTools::equal(fY, fOne))
     392             :                     {
     393             :                         // point is a south polar point, no useful X-coordinate can be created. Set
     394             :                         // Y-coordinte, though
     395           0 :                         if(bChangeY)
     396             :                         {
     397           0 :                             aTexCoor.setY(fOne);
     398             : 
     399           0 :                             if(bChangeX)
     400             :                             {
     401           0 :                                 bPolarPoints = true;
     402             :                             }
     403             :                         }
     404             :                     }
     405             :                     else
     406             :                     {
     407           0 :                         double fX(fOne - ((atan2(aVector.getZ(), aVector.getX()) + F_PI) / F_2PI));
     408             : 
     409             :                         // correct cartesinan point coordiante dependent from center value
     410           0 :                         if(fX > fXCenter + 0.5)
     411             :                         {
     412           0 :                             fX -= fOne;
     413             :                         }
     414           0 :                         else if(fX < fXCenter - 0.5)
     415             :                         {
     416           0 :                             fX += fOne;
     417             :                         }
     418             : 
     419           0 :                         if(bChangeX)
     420             :                         {
     421           0 :                             aTexCoor.setX(fX);
     422             :                         }
     423             : 
     424           0 :                         if(bChangeY)
     425             :                         {
     426           0 :                             aTexCoor.setY(fY);
     427             :                         }
     428             :                     }
     429             : 
     430           0 :                     aRetval.setTextureCoordinate(a, aTexCoor);
     431           0 :                 }
     432             : 
     433           0 :                 if(bPolarPoints)
     434             :                 {
     435             :                     // correct X-texture coordinates if polar points are contained. Those
     436             :                     // coordinates cannot be correct, so use prev or next X-coordinate
     437           0 :                     for(a = 0L; a < nPointCount; a++)
     438             :                     {
     439           0 :                         B2DPoint aTexCoor(aRetval.getTextureCoordinate(a));
     440             : 
     441           0 :                         if(fTools::equalZero(aTexCoor.getY()) || fTools::equal(aTexCoor.getY(), fOne))
     442             :                         {
     443             :                             // get prev, next TexCoor and test for pole
     444           0 :                             const B2DPoint aPrevTexCoor(aRetval.getTextureCoordinate(a ? a - 1L : nPointCount - 1L));
     445           0 :                             const B2DPoint aNextTexCoor(aRetval.getTextureCoordinate((a + 1L) % nPointCount));
     446           0 :                             const bool bPrevPole(fTools::equalZero(aPrevTexCoor.getY()) || fTools::equal(aPrevTexCoor.getY(), fOne));
     447           0 :                             const bool bNextPole(fTools::equalZero(aNextTexCoor.getY()) || fTools::equal(aNextTexCoor.getY(), fOne));
     448             : 
     449           0 :                             if(!bPrevPole && !bNextPole)
     450             :                             {
     451             :                                 // both no poles, mix them
     452           0 :                                 aTexCoor.setX((aPrevTexCoor.getX() + aNextTexCoor.getX()) / 2.0);
     453             :                             }
     454           0 :                             else if(!bNextPole)
     455             :                             {
     456             :                                 // copy next
     457           0 :                                 aTexCoor.setX(aNextTexCoor.getX());
     458             :                             }
     459             :                             else
     460             :                             {
     461             :                                 // copy prev, even if it's a pole, hopefully it is already corrected
     462           0 :                                 aTexCoor.setX(aPrevTexCoor.getX());
     463             :                             }
     464             : 
     465           0 :                             aRetval.setTextureCoordinate(a, aTexCoor);
     466             :                         }
     467           0 :                     }
     468           0 :                 }
     469             :             }
     470             : 
     471           0 :             return aRetval;
     472             :         }
     473             : 
     474           0 :         bool isInside(const B3DPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder)
     475             :         {
     476           0 :             if(bWithBorder && isPointOnPolygon(rCandidate, rPoint, true))
     477             :             {
     478           0 :                 return true;
     479             :             }
     480             :             else
     481             :             {
     482           0 :                 bool bRetval(false);
     483           0 :                 const B3DVector aPlaneNormal(rCandidate.getNormal());
     484             : 
     485           0 :                 if(!aPlaneNormal.equalZero())
     486             :                 {
     487           0 :                     const sal_uInt32 nPointCount(rCandidate.count());
     488             : 
     489           0 :                     if(nPointCount)
     490             :                     {
     491           0 :                         B3DPoint aCurrentPoint(rCandidate.getB3DPoint(nPointCount - 1));
     492           0 :                         const double fAbsX(fabs(aPlaneNormal.getX()));
     493           0 :                         const double fAbsY(fabs(aPlaneNormal.getY()));
     494           0 :                         const double fAbsZ(fabs(aPlaneNormal.getZ()));
     495             : 
     496           0 :                         if(fAbsX > fAbsY && fAbsX > fAbsZ)
     497             :                         {
     498             :                             // normal points mostly in X-Direction, use YZ-Polygon projection for check
     499             :                             // x -> y, y -> z
     500           0 :                             for(sal_uInt32 a(0); a < nPointCount; a++)
     501             :                             {
     502           0 :                                 const B3DPoint aPreviousPoint(aCurrentPoint);
     503           0 :                                 aCurrentPoint = rCandidate.getB3DPoint(a);
     504             : 
     505             :                                 // cross-over in Z?
     506           0 :                                 const bool bCompZA(fTools::more(aPreviousPoint.getZ(), rPoint.getZ()));
     507           0 :                                 const bool bCompZB(fTools::more(aCurrentPoint.getZ(), rPoint.getZ()));
     508             : 
     509           0 :                                 if(bCompZA != bCompZB)
     510             :                                 {
     511             :                                     // cross-over in Y?
     512           0 :                                     const bool bCompYA(fTools::more(aPreviousPoint.getY(), rPoint.getY()));
     513           0 :                                     const bool bCompYB(fTools::more(aCurrentPoint.getY(), rPoint.getY()));
     514             : 
     515           0 :                                     if(bCompYA == bCompYB)
     516             :                                     {
     517           0 :                                         if(bCompYA)
     518             :                                         {
     519           0 :                                             bRetval = !bRetval;
     520             :                                         }
     521             :                                     }
     522             :                                     else
     523             :                                     {
     524             :                                         const double fCompare(
     525           0 :                                             aCurrentPoint.getY() - (aCurrentPoint.getZ() - rPoint.getZ()) *
     526           0 :                                             (aPreviousPoint.getY() - aCurrentPoint.getY()) /
     527           0 :                                             (aPreviousPoint.getZ() - aCurrentPoint.getZ()));
     528             : 
     529           0 :                                         if(fTools::more(fCompare, rPoint.getY()))
     530             :                                         {
     531           0 :                                             bRetval = !bRetval;
     532             :                                         }
     533             :                                     }
     534             :                                 }
     535           0 :                             }
     536             :                         }
     537           0 :                         else if(fAbsY > fAbsX && fAbsY > fAbsZ)
     538             :                         {
     539             :                             // normal points mostly in Y-Direction, use XZ-Polygon projection for check
     540             :                             // x -> x, y -> z
     541           0 :                             for(sal_uInt32 a(0); a < nPointCount; a++)
     542             :                             {
     543           0 :                                 const B3DPoint aPreviousPoint(aCurrentPoint);
     544           0 :                                 aCurrentPoint = rCandidate.getB3DPoint(a);
     545             : 
     546             :                                 // cross-over in Z?
     547           0 :                                 const bool bCompZA(fTools::more(aPreviousPoint.getZ(), rPoint.getZ()));
     548           0 :                                 const bool bCompZB(fTools::more(aCurrentPoint.getZ(), rPoint.getZ()));
     549             : 
     550           0 :                                 if(bCompZA != bCompZB)
     551             :                                 {
     552             :                                     // cross-over in X?
     553           0 :                                     const bool bCompXA(fTools::more(aPreviousPoint.getX(), rPoint.getX()));
     554           0 :                                     const bool bCompXB(fTools::more(aCurrentPoint.getX(), rPoint.getX()));
     555             : 
     556           0 :                                     if(bCompXA == bCompXB)
     557             :                                     {
     558           0 :                                         if(bCompXA)
     559             :                                         {
     560           0 :                                             bRetval = !bRetval;
     561             :                                         }
     562             :                                     }
     563             :                                     else
     564             :                                     {
     565             :                                         const double fCompare(
     566           0 :                                             aCurrentPoint.getX() - (aCurrentPoint.getZ() - rPoint.getZ()) *
     567           0 :                                             (aPreviousPoint.getX() - aCurrentPoint.getX()) /
     568           0 :                                             (aPreviousPoint.getZ() - aCurrentPoint.getZ()));
     569             : 
     570           0 :                                         if(fTools::more(fCompare, rPoint.getX()))
     571             :                                         {
     572           0 :                                             bRetval = !bRetval;
     573             :                                         }
     574             :                                     }
     575             :                                 }
     576           0 :                             }
     577             :                         }
     578             :                         else
     579             :                         {
     580             :                             // normal points mostly in Z-Direction, use XY-Polygon projection for check
     581             :                             // x -> x, y -> y
     582           0 :                             for(sal_uInt32 a(0); a < nPointCount; a++)
     583             :                             {
     584           0 :                                 const B3DPoint aPreviousPoint(aCurrentPoint);
     585           0 :                                 aCurrentPoint = rCandidate.getB3DPoint(a);
     586             : 
     587             :                                 // cross-over in Y?
     588           0 :                                 const bool bCompYA(fTools::more(aPreviousPoint.getY(), rPoint.getY()));
     589           0 :                                 const bool bCompYB(fTools::more(aCurrentPoint.getY(), rPoint.getY()));
     590             : 
     591           0 :                                 if(bCompYA != bCompYB)
     592             :                                 {
     593             :                                     // cross-over in X?
     594           0 :                                     const bool bCompXA(fTools::more(aPreviousPoint.getX(), rPoint.getX()));
     595           0 :                                     const bool bCompXB(fTools::more(aCurrentPoint.getX(), rPoint.getX()));
     596             : 
     597           0 :                                     if(bCompXA == bCompXB)
     598             :                                     {
     599           0 :                                         if(bCompXA)
     600             :                                         {
     601           0 :                                             bRetval = !bRetval;
     602             :                                         }
     603             :                                     }
     604             :                                     else
     605             :                                     {
     606             :                                         const double fCompare(
     607           0 :                                             aCurrentPoint.getX() - (aCurrentPoint.getY() - rPoint.getY()) *
     608           0 :                                             (aPreviousPoint.getX() - aCurrentPoint.getX()) /
     609           0 :                                             (aPreviousPoint.getY() - aCurrentPoint.getY()));
     610             : 
     611           0 :                                         if(fTools::more(fCompare, rPoint.getX()))
     612             :                                         {
     613           0 :                                             bRetval = !bRetval;
     614             :                                         }
     615             :                                     }
     616             :                                 }
     617           0 :                             }
     618           0 :                         }
     619             :                     }
     620             :                 }
     621             : 
     622           0 :                 return bRetval;
     623             :             }
     624             :         }
     625             : 
     626           0 :         bool isPointOnLine(const B3DPoint& rStart, const B3DPoint& rEnd, const B3DPoint& rCandidate, bool bWithPoints)
     627             :         {
     628           0 :             if(rCandidate.equal(rStart) || rCandidate.equal(rEnd))
     629             :             {
     630             :                 // candidate is in epsilon around start or end -> inside
     631           0 :                 return bWithPoints;
     632             :             }
     633           0 :             else if(rStart.equal(rEnd))
     634             :             {
     635             :                 // start and end are equal, but candidate is outside their epsilon -> outside
     636           0 :                 return false;
     637             :             }
     638             :             else
     639             :             {
     640           0 :                 const B3DVector aEdgeVector(rEnd - rStart);
     641           0 :                 const B3DVector aTestVector(rCandidate - rStart);
     642             : 
     643           0 :                 if(areParallel(aEdgeVector, aTestVector))
     644             :                 {
     645           0 :                     const double fZero(0.0);
     646           0 :                     const double fOne(1.0);
     647           0 :                     double fParamTestOnCurr(0.0);
     648             : 
     649           0 :                     if(aEdgeVector.getX() > aEdgeVector.getY())
     650             :                     {
     651           0 :                         if(aEdgeVector.getX() > aEdgeVector.getZ())
     652             :                         {
     653             :                             // X is biggest
     654           0 :                             fParamTestOnCurr = aTestVector.getX() / aEdgeVector.getX();
     655             :                         }
     656             :                         else
     657             :                         {
     658             :                             // Z is biggest
     659           0 :                             fParamTestOnCurr = aTestVector.getZ() / aEdgeVector.getZ();
     660             :                         }
     661             :                     }
     662             :                     else
     663             :                     {
     664           0 :                         if(aEdgeVector.getY() > aEdgeVector.getZ())
     665             :                         {
     666             :                             // Y is biggest
     667           0 :                             fParamTestOnCurr = aTestVector.getY() / aEdgeVector.getY();
     668             :                         }
     669             :                         else
     670             :                         {
     671             :                             // Z is biggest
     672           0 :                             fParamTestOnCurr = aTestVector.getZ() / aEdgeVector.getZ();
     673             :                         }
     674             :                     }
     675             : 
     676           0 :                     if(fTools::more(fParamTestOnCurr, fZero) && fTools::less(fParamTestOnCurr, fOne))
     677             :                     {
     678           0 :                         return true;
     679             :                     }
     680             :                 }
     681             : 
     682           0 :                 return false;
     683             :             }
     684             :         }
     685             : 
     686           0 :         bool isPointOnPolygon(const B3DPolygon& rCandidate, const B3DPoint& rPoint, bool bWithPoints)
     687             :         {
     688           0 :             const sal_uInt32 nPointCount(rCandidate.count());
     689             : 
     690           0 :             if(nPointCount > 1L)
     691             :             {
     692           0 :                 const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1L);
     693           0 :                 B3DPoint aCurrentPoint(rCandidate.getB3DPoint(0));
     694             : 
     695           0 :                 for(sal_uInt32 a(0); a < nLoopCount; a++)
     696             :                 {
     697           0 :                     const B3DPoint aNextPoint(rCandidate.getB3DPoint((a + 1) % nPointCount));
     698             : 
     699           0 :                     if(isPointOnLine(aCurrentPoint, aNextPoint, rPoint, bWithPoints))
     700             :                     {
     701           0 :                         return true;
     702             :                     }
     703             : 
     704           0 :                     aCurrentPoint = aNextPoint;
     705           0 :                 }
     706             :             }
     707           0 :             else if(nPointCount && bWithPoints)
     708             :             {
     709           0 :                 return rPoint.equal(rCandidate.getB3DPoint(0));
     710             :             }
     711             : 
     712           0 :             return false;
     713             :         }
     714             : 
     715           0 :         bool getCutBetweenLineAndPlane(const B3DVector& rPlaneNormal, const B3DPoint& rPlanePoint, const B3DPoint& rEdgeStart, const B3DPoint& rEdgeEnd, double& fCut)
     716             :         {
     717           0 :             if(!rPlaneNormal.equalZero() && !rEdgeStart.equal(rEdgeEnd))
     718             :             {
     719           0 :                 const B3DVector aTestEdge(rEdgeEnd - rEdgeStart);
     720           0 :                 const double fScalarEdge(rPlaneNormal.scalar(aTestEdge));
     721             : 
     722           0 :                 if(!fTools::equalZero(fScalarEdge))
     723             :                 {
     724           0 :                     const B3DVector aCompareEdge(rPlanePoint - rEdgeStart);
     725           0 :                     const double fScalarCompare(rPlaneNormal.scalar(aCompareEdge));
     726             : 
     727           0 :                     fCut = fScalarCompare / fScalarEdge;
     728           0 :                     return true;
     729           0 :                 }
     730             :             }
     731             : 
     732           0 :             return false;
     733             :         }
     734             : 
     735             :         // snap points of horizontal or vertical edges to discrete values
     736           0 :         B3DPolygon snapPointsOfHorizontalOrVerticalEdges(const B3DPolygon& rCandidate)
     737             :         {
     738           0 :             const sal_uInt32 nPointCount(rCandidate.count());
     739             : 
     740           0 :             if(nPointCount > 1)
     741             :             {
     742             :                 // Start by copying the source polygon to get a writeable copy. The closed state is
     743             :                 // copied by aRetval's initialisation, too, so no need to copy it in this method
     744           0 :                 B3DPolygon aRetval(rCandidate);
     745             : 
     746             :                 // prepare geometry data. Get rounded from original
     747           0 :                 B3ITuple aPrevTuple(basegfx::fround(rCandidate.getB3DPoint(nPointCount - 1)));
     748           0 :                 B3DPoint aCurrPoint(rCandidate.getB3DPoint(0));
     749           0 :                 B3ITuple aCurrTuple(basegfx::fround(aCurrPoint));
     750             : 
     751             :                 // loop over all points. This will also snap the implicit closing edge
     752             :                 // even when not closed, but that's no problem here
     753           0 :                 for(sal_uInt32 a(0); a < nPointCount; a++)
     754             :                 {
     755             :                     // get next point. Get rounded from original
     756           0 :                     const bool bLastRun(a + 1 == nPointCount);
     757           0 :                     const sal_uInt32 nNextIndex(bLastRun ? 0 : a + 1);
     758           0 :                     const B3DPoint aNextPoint(rCandidate.getB3DPoint(nNextIndex));
     759           0 :                     const B3ITuple aNextTuple(basegfx::fround(aNextPoint));
     760             : 
     761             :                     // get the states
     762           0 :                     const bool bPrevVertical(aPrevTuple.getX() == aCurrTuple.getX());
     763           0 :                     const bool bNextVertical(aNextTuple.getX() == aCurrTuple.getX());
     764           0 :                     const bool bPrevHorizontal(aPrevTuple.getY() == aCurrTuple.getY());
     765           0 :                     const bool bNextHorizontal(aNextTuple.getY() == aCurrTuple.getY());
     766           0 :                     const bool bSnapX(bPrevVertical || bNextVertical);
     767           0 :                     const bool bSnapY(bPrevHorizontal || bNextHorizontal);
     768             : 
     769           0 :                     if(bSnapX || bSnapY)
     770             :                     {
     771             :                         const B3DPoint aSnappedPoint(
     772           0 :                             bSnapX ? aCurrTuple.getX() : aCurrPoint.getX(),
     773           0 :                             bSnapY ? aCurrTuple.getY() : aCurrPoint.getY(),
     774           0 :                             aCurrPoint.getZ());
     775             : 
     776           0 :                         aRetval.setB3DPoint(a, aSnappedPoint);
     777             :                     }
     778             : 
     779             :                     // prepare next point
     780           0 :                     if(!bLastRun)
     781             :                     {
     782           0 :                         aPrevTuple = aCurrTuple;
     783           0 :                         aCurrPoint = aNextPoint;
     784           0 :                         aCurrTuple = aNextTuple;
     785             :                     }
     786           0 :                 }
     787             : 
     788           0 :                 return aRetval;
     789             :             }
     790             :             else
     791             :             {
     792           0 :                 return rCandidate;
     793             :             }
     794             :         }
     795             : 
     796             :     } // end of namespace tools
     797             : } // end of namespace basegfx
     798             : 
     799             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10