1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_basegfx.hxx" 30*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 31*cdf0e10cSrcweir #include <osl/diagnose.h> 32*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx> 33*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx> 34*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 35*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx> 36*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygoncutter.hxx> 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir #include <numeric> 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir namespace basegfx 43*cdf0e10cSrcweir { 44*cdf0e10cSrcweir namespace tools 45*cdf0e10cSrcweir { 46*cdf0e10cSrcweir B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate) 47*cdf0e10cSrcweir { 48*cdf0e10cSrcweir B2DPolyPolygon aRetval(rCandidate); 49*cdf0e10cSrcweir const sal_uInt32 nCount(aRetval.count()); 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nCount; a++) 52*cdf0e10cSrcweir { 53*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 54*cdf0e10cSrcweir const B2VectorOrientation aOrientation(tools::getOrientation(aCandidate)); 55*cdf0e10cSrcweir sal_uInt32 nDepth(0L); 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir for(sal_uInt32 b(0L); b < nCount; b++) 58*cdf0e10cSrcweir { 59*cdf0e10cSrcweir if(b != a) 60*cdf0e10cSrcweir { 61*cdf0e10cSrcweir const B2DPolygon aCompare(rCandidate.getB2DPolygon(b)); 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir if(tools::isInside(aCompare, aCandidate, true)) 64*cdf0e10cSrcweir { 65*cdf0e10cSrcweir nDepth++; 66*cdf0e10cSrcweir } 67*cdf0e10cSrcweir } 68*cdf0e10cSrcweir } 69*cdf0e10cSrcweir 70*cdf0e10cSrcweir const bool bShallBeHole(1L == (nDepth & 0x00000001)); 71*cdf0e10cSrcweir const bool bIsHole(ORIENTATION_NEGATIVE == aOrientation); 72*cdf0e10cSrcweir 73*cdf0e10cSrcweir if(bShallBeHole != bIsHole && ORIENTATION_NEUTRAL != aOrientation) 74*cdf0e10cSrcweir { 75*cdf0e10cSrcweir B2DPolygon aFlipped(aCandidate); 76*cdf0e10cSrcweir aFlipped.flip(); 77*cdf0e10cSrcweir aRetval.setB2DPolygon(a, aFlipped); 78*cdf0e10cSrcweir } 79*cdf0e10cSrcweir } 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir return aRetval; 82*cdf0e10cSrcweir } 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate) 85*cdf0e10cSrcweir { 86*cdf0e10cSrcweir const sal_uInt32 nCount(rCandidate.count()); 87*cdf0e10cSrcweir 88*cdf0e10cSrcweir if(nCount > 1L) 89*cdf0e10cSrcweir { 90*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nCount; a++) 91*cdf0e10cSrcweir { 92*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 93*cdf0e10cSrcweir sal_uInt32 nDepth(0L); 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir for(sal_uInt32 b(0L); b < nCount; b++) 96*cdf0e10cSrcweir { 97*cdf0e10cSrcweir if(b != a) 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir const B2DPolygon aCompare(rCandidate.getB2DPolygon(b)); 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir if(tools::isInside(aCompare, aCandidate, true)) 102*cdf0e10cSrcweir { 103*cdf0e10cSrcweir nDepth++; 104*cdf0e10cSrcweir } 105*cdf0e10cSrcweir } 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir if(!nDepth) 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir B2DPolyPolygon aRetval(rCandidate); 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir if(a != 0L) 113*cdf0e10cSrcweir { 114*cdf0e10cSrcweir // exchange polygon a and polygon 0L 115*cdf0e10cSrcweir aRetval.setB2DPolygon(0L, aCandidate); 116*cdf0e10cSrcweir aRetval.setB2DPolygon(a, rCandidate.getB2DPolygon(0L)); 117*cdf0e10cSrcweir } 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir // exit 120*cdf0e10cSrcweir return aRetval; 121*cdf0e10cSrcweir } 122*cdf0e10cSrcweir } 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir return rCandidate; 126*cdf0e10cSrcweir } 127*cdf0e10cSrcweir 128*cdf0e10cSrcweir B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound) 129*cdf0e10cSrcweir { 130*cdf0e10cSrcweir if(rCandidate.areControlPointsUsed()) 131*cdf0e10cSrcweir { 132*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 133*cdf0e10cSrcweir B2DPolyPolygon aRetval; 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 136*cdf0e10cSrcweir { 137*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 138*cdf0e10cSrcweir 139*cdf0e10cSrcweir if(aCandidate.areControlPointsUsed()) 140*cdf0e10cSrcweir { 141*cdf0e10cSrcweir aRetval.append(tools::adaptiveSubdivideByDistance(aCandidate, fDistanceBound)); 142*cdf0e10cSrcweir } 143*cdf0e10cSrcweir else 144*cdf0e10cSrcweir { 145*cdf0e10cSrcweir aRetval.append(aCandidate); 146*cdf0e10cSrcweir } 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir 149*cdf0e10cSrcweir return aRetval; 150*cdf0e10cSrcweir } 151*cdf0e10cSrcweir else 152*cdf0e10cSrcweir { 153*cdf0e10cSrcweir return rCandidate; 154*cdf0e10cSrcweir } 155*cdf0e10cSrcweir } 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound) 158*cdf0e10cSrcweir { 159*cdf0e10cSrcweir if(rCandidate.areControlPointsUsed()) 160*cdf0e10cSrcweir { 161*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 162*cdf0e10cSrcweir B2DPolyPolygon aRetval; 163*cdf0e10cSrcweir 164*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 165*cdf0e10cSrcweir { 166*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir if(aCandidate.areControlPointsUsed()) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir aRetval.append(tools::adaptiveSubdivideByAngle(aCandidate, fAngleBound)); 171*cdf0e10cSrcweir } 172*cdf0e10cSrcweir else 173*cdf0e10cSrcweir { 174*cdf0e10cSrcweir aRetval.append(aCandidate); 175*cdf0e10cSrcweir } 176*cdf0e10cSrcweir } 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir return aRetval; 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir else 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir return rCandidate; 183*cdf0e10cSrcweir } 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir B2DPolyPolygon adaptiveSubdivideByCount(const B2DPolyPolygon& rCandidate, sal_uInt32 nCount) 187*cdf0e10cSrcweir { 188*cdf0e10cSrcweir if(rCandidate.areControlPointsUsed()) 189*cdf0e10cSrcweir { 190*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 191*cdf0e10cSrcweir B2DPolyPolygon aRetval; 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 194*cdf0e10cSrcweir { 195*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir if(aCandidate.areControlPointsUsed()) 198*cdf0e10cSrcweir { 199*cdf0e10cSrcweir aRetval.append(tools::adaptiveSubdivideByCount(aCandidate, nCount)); 200*cdf0e10cSrcweir } 201*cdf0e10cSrcweir else 202*cdf0e10cSrcweir { 203*cdf0e10cSrcweir aRetval.append(aCandidate); 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir } 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir return aRetval; 208*cdf0e10cSrcweir } 209*cdf0e10cSrcweir else 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir return rCandidate; 212*cdf0e10cSrcweir } 213*cdf0e10cSrcweir } 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder) 216*cdf0e10cSrcweir { 217*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir if(1L == nPolygonCount) 220*cdf0e10cSrcweir { 221*cdf0e10cSrcweir return isInside(rCandidate.getB2DPolygon(0L), rPoint, bWithBorder); 222*cdf0e10cSrcweir } 223*cdf0e10cSrcweir else 224*cdf0e10cSrcweir { 225*cdf0e10cSrcweir sal_Int32 nInsideCount(0L); 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 228*cdf0e10cSrcweir { 229*cdf0e10cSrcweir const B2DPolygon aPolygon(rCandidate.getB2DPolygon(a)); 230*cdf0e10cSrcweir const bool bInside(isInside(aPolygon, rPoint, bWithBorder)); 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir if(bInside) 233*cdf0e10cSrcweir { 234*cdf0e10cSrcweir nInsideCount++; 235*cdf0e10cSrcweir } 236*cdf0e10cSrcweir } 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir return (nInsideCount % 2L); 239*cdf0e10cSrcweir } 240*cdf0e10cSrcweir } 241*cdf0e10cSrcweir 242*cdf0e10cSrcweir B2DRange getRangeWithControlPoints(const B2DPolyPolygon& rCandidate) 243*cdf0e10cSrcweir { 244*cdf0e10cSrcweir B2DRange aRetval; 245*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 246*cdf0e10cSrcweir 247*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 248*cdf0e10cSrcweir { 249*cdf0e10cSrcweir B2DPolygon aCandidate = rCandidate.getB2DPolygon(a); 250*cdf0e10cSrcweir aRetval.expand(tools::getRangeWithControlPoints(aCandidate)); 251*cdf0e10cSrcweir } 252*cdf0e10cSrcweir 253*cdf0e10cSrcweir return aRetval; 254*cdf0e10cSrcweir } 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir B2DRange getRange(const B2DPolyPolygon& rCandidate) 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir B2DRange aRetval; 259*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 260*cdf0e10cSrcweir 261*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir B2DPolygon aCandidate = rCandidate.getB2DPolygon(a); 264*cdf0e10cSrcweir aRetval.expand(tools::getRange(aCandidate)); 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir 267*cdf0e10cSrcweir return aRetval; 268*cdf0e10cSrcweir } 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir void applyLineDashing(const B2DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B2DPolyPolygon* pLineTarget, B2DPolyPolygon* pGapTarget, double fFullDashDotLen) 271*cdf0e10cSrcweir { 272*cdf0e10cSrcweir if(0.0 == fFullDashDotLen && rDotDashArray.size()) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir // calculate fFullDashDotLen from rDotDashArray 275*cdf0e10cSrcweir fFullDashDotLen = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0); 276*cdf0e10cSrcweir } 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir if(rCandidate.count() && fFullDashDotLen > 0.0) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir B2DPolyPolygon aLineTarget, aGapTarget; 281*cdf0e10cSrcweir 282*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 283*cdf0e10cSrcweir { 284*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir applyLineDashing( 287*cdf0e10cSrcweir aCandidate, 288*cdf0e10cSrcweir rDotDashArray, 289*cdf0e10cSrcweir pLineTarget ? &aLineTarget : 0, 290*cdf0e10cSrcweir pGapTarget ? &aGapTarget : 0, 291*cdf0e10cSrcweir fFullDashDotLen); 292*cdf0e10cSrcweir 293*cdf0e10cSrcweir if(pLineTarget) 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir pLineTarget->append(aLineTarget); 296*cdf0e10cSrcweir } 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir if(pGapTarget) 299*cdf0e10cSrcweir { 300*cdf0e10cSrcweir pGapTarget->append(aGapTarget); 301*cdf0e10cSrcweir } 302*cdf0e10cSrcweir } 303*cdf0e10cSrcweir } 304*cdf0e10cSrcweir } 305*cdf0e10cSrcweir 306*cdf0e10cSrcweir bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance) 307*cdf0e10cSrcweir { 308*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 311*cdf0e10cSrcweir { 312*cdf0e10cSrcweir B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 313*cdf0e10cSrcweir 314*cdf0e10cSrcweir if(isInEpsilonRange(aCandidate, rTestPosition, fDistance)) 315*cdf0e10cSrcweir { 316*cdf0e10cSrcweir return true; 317*cdf0e10cSrcweir } 318*cdf0e10cSrcweir } 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir return false; 321*cdf0e10cSrcweir } 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate) 324*cdf0e10cSrcweir { 325*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 326*cdf0e10cSrcweir B3DPolyPolygon aRetval; 327*cdf0e10cSrcweir 328*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 329*cdf0e10cSrcweir { 330*cdf0e10cSrcweir B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir aRetval.append(createB3DPolygonFromB2DPolygon(aCandidate, fZCoordinate)); 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir return aRetval; 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat) 339*cdf0e10cSrcweir { 340*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 341*cdf0e10cSrcweir B2DPolyPolygon aRetval; 342*cdf0e10cSrcweir 343*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 344*cdf0e10cSrcweir { 345*cdf0e10cSrcweir B3DPolygon aCandidate(rCandidate.getB3DPolygon(a)); 346*cdf0e10cSrcweir 347*cdf0e10cSrcweir aRetval.append(createB2DPolygonFromB3DPolygon(aCandidate, rMat)); 348*cdf0e10cSrcweir } 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir return aRetval; 351*cdf0e10cSrcweir } 352*cdf0e10cSrcweir 353*cdf0e10cSrcweir double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut) 354*cdf0e10cSrcweir { 355*cdf0e10cSrcweir double fRetval(DBL_MAX); 356*cdf0e10cSrcweir const double fZero(0.0); 357*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 360*cdf0e10cSrcweir { 361*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 362*cdf0e10cSrcweir sal_uInt32 nNewEdgeIndex; 363*cdf0e10cSrcweir double fNewCut; 364*cdf0e10cSrcweir const double fNewDistance(getSmallestDistancePointToPolygon(aCandidate, rTestPoint, nNewEdgeIndex, fNewCut)); 365*cdf0e10cSrcweir 366*cdf0e10cSrcweir if(DBL_MAX == fRetval || fNewDistance < fRetval) 367*cdf0e10cSrcweir { 368*cdf0e10cSrcweir fRetval = fNewDistance; 369*cdf0e10cSrcweir rPolygonIndex = a; 370*cdf0e10cSrcweir rEdgeIndex = nNewEdgeIndex; 371*cdf0e10cSrcweir rCut = fNewCut; 372*cdf0e10cSrcweir 373*cdf0e10cSrcweir if(fTools::equal(fRetval, fZero)) 374*cdf0e10cSrcweir { 375*cdf0e10cSrcweir // already found zero distance, cannot get better. Ensure numerical zero value and end loop. 376*cdf0e10cSrcweir fRetval = 0.0; 377*cdf0e10cSrcweir break; 378*cdf0e10cSrcweir } 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir } 381*cdf0e10cSrcweir 382*cdf0e10cSrcweir return fRetval; 383*cdf0e10cSrcweir } 384*cdf0e10cSrcweir 385*cdf0e10cSrcweir B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight) 386*cdf0e10cSrcweir { 387*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 388*cdf0e10cSrcweir B2DPolyPolygon aRetval; 389*cdf0e10cSrcweir 390*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 391*cdf0e10cSrcweir { 392*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir aRetval.append(distort(aCandidate, rOriginal, rTopLeft, rTopRight, rBottomLeft, rBottomRight)); 395*cdf0e10cSrcweir } 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir return aRetval; 398*cdf0e10cSrcweir } 399*cdf0e10cSrcweir 400*cdf0e10cSrcweir B2DPolyPolygon rotateAroundPoint(const B2DPolyPolygon& rCandidate, const B2DPoint& rCenter, double fAngle) 401*cdf0e10cSrcweir { 402*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 403*cdf0e10cSrcweir B2DPolyPolygon aRetval; 404*cdf0e10cSrcweir 405*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 408*cdf0e10cSrcweir 409*cdf0e10cSrcweir aRetval.append(rotateAroundPoint(aCandidate, rCenter, fAngle)); 410*cdf0e10cSrcweir } 411*cdf0e10cSrcweir 412*cdf0e10cSrcweir return aRetval; 413*cdf0e10cSrcweir } 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate) 416*cdf0e10cSrcweir { 417*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 418*cdf0e10cSrcweir B2DPolyPolygon aRetval; 419*cdf0e10cSrcweir 420*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 421*cdf0e10cSrcweir { 422*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 423*cdf0e10cSrcweir 424*cdf0e10cSrcweir aRetval.append(expandToCurve(aCandidate)); 425*cdf0e10cSrcweir } 426*cdf0e10cSrcweir 427*cdf0e10cSrcweir return aRetval; 428*cdf0e10cSrcweir } 429*cdf0e10cSrcweir 430*cdf0e10cSrcweir B2DPolyPolygon setContinuity(const B2DPolyPolygon& rCandidate, B2VectorContinuity eContinuity) 431*cdf0e10cSrcweir { 432*cdf0e10cSrcweir if(rCandidate.areControlPointsUsed()) 433*cdf0e10cSrcweir { 434*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidate.count()); 435*cdf0e10cSrcweir B2DPolyPolygon aRetval; 436*cdf0e10cSrcweir 437*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nPolygonCount; a++) 438*cdf0e10cSrcweir { 439*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a)); 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir aRetval.append(setContinuity(aCandidate, eContinuity)); 442*cdf0e10cSrcweir } 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir return aRetval; 445*cdf0e10cSrcweir } 446*cdf0e10cSrcweir else 447*cdf0e10cSrcweir { 448*cdf0e10cSrcweir return rCandidate; 449*cdf0e10cSrcweir } 450*cdf0e10cSrcweir } 451*cdf0e10cSrcweir 452*cdf0e10cSrcweir B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue) 453*cdf0e10cSrcweir { 454*cdf0e10cSrcweir if(0.0 != fValue) 455*cdf0e10cSrcweir { 456*cdf0e10cSrcweir B2DPolyPolygon aRetval; 457*cdf0e10cSrcweir 458*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 459*cdf0e10cSrcweir { 460*cdf0e10cSrcweir aRetval.append(growInNormalDirection(rCandidate.getB2DPolygon(a), fValue)); 461*cdf0e10cSrcweir } 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir return aRetval; 464*cdf0e10cSrcweir } 465*cdf0e10cSrcweir else 466*cdf0e10cSrcweir { 467*cdf0e10cSrcweir return rCandidate; 468*cdf0e10cSrcweir } 469*cdf0e10cSrcweir } 470*cdf0e10cSrcweir 471*cdf0e10cSrcweir void correctGrowShrinkPolygonPair(B2DPolyPolygon& /*rOriginal*/, B2DPolyPolygon& /*rGrown*/) 472*cdf0e10cSrcweir { 473*cdf0e10cSrcweir } 474*cdf0e10cSrcweir 475*cdf0e10cSrcweir B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments) 476*cdf0e10cSrcweir { 477*cdf0e10cSrcweir B2DPolyPolygon aRetval; 478*cdf0e10cSrcweir 479*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 480*cdf0e10cSrcweir { 481*cdf0e10cSrcweir aRetval.append(reSegmentPolygon(rCandidate.getB2DPolygon(a), nSegments)); 482*cdf0e10cSrcweir } 483*cdf0e10cSrcweir 484*cdf0e10cSrcweir return aRetval; 485*cdf0e10cSrcweir } 486*cdf0e10cSrcweir 487*cdf0e10cSrcweir B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t) 488*cdf0e10cSrcweir { 489*cdf0e10cSrcweir OSL_ENSURE(rOld1.count() == rOld2.count(), "B2DPolyPolygon interpolate: Different geometry (!)"); 490*cdf0e10cSrcweir B2DPolyPolygon aRetval; 491*cdf0e10cSrcweir 492*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rOld1.count(); a++) 493*cdf0e10cSrcweir { 494*cdf0e10cSrcweir aRetval.append(interpolate(rOld1.getB2DPolygon(a), rOld2.getB2DPolygon(a), t)); 495*cdf0e10cSrcweir } 496*cdf0e10cSrcweir 497*cdf0e10cSrcweir return aRetval; 498*cdf0e10cSrcweir } 499*cdf0e10cSrcweir 500*cdf0e10cSrcweir bool isRectangle( const B2DPolyPolygon& rPoly ) 501*cdf0e10cSrcweir { 502*cdf0e10cSrcweir // exclude some cheap cases first 503*cdf0e10cSrcweir if( rPoly.count() != 1 ) 504*cdf0e10cSrcweir return false; 505*cdf0e10cSrcweir 506*cdf0e10cSrcweir return isRectangle( rPoly.getB2DPolygon(0) ); 507*cdf0e10cSrcweir } 508*cdf0e10cSrcweir 509*cdf0e10cSrcweir // #i76891# 510*cdf0e10cSrcweir B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate) 511*cdf0e10cSrcweir { 512*cdf0e10cSrcweir if(rCandidate.areControlPointsUsed()) 513*cdf0e10cSrcweir { 514*cdf0e10cSrcweir B2DPolyPolygon aRetval; 515*cdf0e10cSrcweir 516*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 517*cdf0e10cSrcweir { 518*cdf0e10cSrcweir aRetval.append(simplifyCurveSegments(rCandidate.getB2DPolygon(a))); 519*cdf0e10cSrcweir } 520*cdf0e10cSrcweir 521*cdf0e10cSrcweir return aRetval; 522*cdf0e10cSrcweir } 523*cdf0e10cSrcweir else 524*cdf0e10cSrcweir { 525*cdf0e10cSrcweir return rCandidate; 526*cdf0e10cSrcweir } 527*cdf0e10cSrcweir } 528*cdf0e10cSrcweir 529*cdf0e10cSrcweir B2DPolyPolygon reSegmentPolyPolygonEdges(const B2DPolyPolygon& rCandidate, sal_uInt32 nSubEdges, bool bHandleCurvedEdges, bool bHandleStraightEdges) 530*cdf0e10cSrcweir { 531*cdf0e10cSrcweir B2DPolyPolygon aRetval; 532*cdf0e10cSrcweir 533*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 534*cdf0e10cSrcweir { 535*cdf0e10cSrcweir aRetval.append(reSegmentPolygonEdges(rCandidate.getB2DPolygon(a), nSubEdges, bHandleCurvedEdges, bHandleStraightEdges)); 536*cdf0e10cSrcweir } 537*cdf0e10cSrcweir 538*cdf0e10cSrcweir return aRetval; 539*cdf0e10cSrcweir } 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 542*cdf0e10cSrcweir // comparators with tolerance for 2D PolyPolygons 543*cdf0e10cSrcweir 544*cdf0e10cSrcweir bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB, const double& rfSmallValue) 545*cdf0e10cSrcweir { 546*cdf0e10cSrcweir const sal_uInt32 nPolygonCount(rCandidateA.count()); 547*cdf0e10cSrcweir 548*cdf0e10cSrcweir if(nPolygonCount != rCandidateB.count()) 549*cdf0e10cSrcweir return false; 550*cdf0e10cSrcweir 551*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nPolygonCount; a++) 552*cdf0e10cSrcweir { 553*cdf0e10cSrcweir const B2DPolygon aCandidate(rCandidateA.getB2DPolygon(a)); 554*cdf0e10cSrcweir 555*cdf0e10cSrcweir if(!equal(aCandidate, rCandidateB.getB2DPolygon(a), rfSmallValue)) 556*cdf0e10cSrcweir return false; 557*cdf0e10cSrcweir } 558*cdf0e10cSrcweir 559*cdf0e10cSrcweir return true; 560*cdf0e10cSrcweir } 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB) 563*cdf0e10cSrcweir { 564*cdf0e10cSrcweir const double fSmallValue(fTools::getSmallValue()); 565*cdf0e10cSrcweir 566*cdf0e10cSrcweir return equal(rCandidateA, rCandidateB, fSmallValue); 567*cdf0e10cSrcweir } 568*cdf0e10cSrcweir 569*cdf0e10cSrcweir B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate) 570*cdf0e10cSrcweir { 571*cdf0e10cSrcweir B2DPolyPolygon aRetval; 572*cdf0e10cSrcweir 573*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 574*cdf0e10cSrcweir { 575*cdf0e10cSrcweir aRetval.append(snapPointsOfHorizontalOrVerticalEdges(rCandidate.getB2DPolygon(a))); 576*cdf0e10cSrcweir } 577*cdf0e10cSrcweir 578*cdf0e10cSrcweir return aRetval; 579*cdf0e10cSrcweir } 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir } // end of namespace tools 582*cdf0e10cSrcweir } // end of namespace basegfx 583*cdf0e10cSrcweir 584*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 585*cdf0e10cSrcweir // eof 586