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

Generated by: LCOV version 1.11