1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove 25*b1cdbd2cSJim Jagielski #include "precompiled_basegfx.hxx" 26*b1cdbd2cSJim Jagielski 27*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b3dpolygonclipper.hxx> 28*b1cdbd2cSJim Jagielski #include <osl/diagnose.h> 29*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b3dpolygontools.hxx> 30*b1cdbd2cSJim Jagielski #include <basegfx/numeric/ftools.hxx> 31*b1cdbd2cSJim Jagielski #include <basegfx/matrix/b3dhommatrix.hxx> 32*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b3dpolygontools.hxx> 33*b1cdbd2cSJim Jagielski #include <basegfx/range/b3drange.hxx> 34*b1cdbd2cSJim Jagielski #include <basegfx/point/b2dpoint.hxx> 35*b1cdbd2cSJim Jagielski #include <basegfx/range/b2drange.hxx> 36*b1cdbd2cSJim Jagielski #include <basegfx/color/bcolor.hxx> 37*b1cdbd2cSJim Jagielski 38*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 39*b1cdbd2cSJim Jagielski 40*b1cdbd2cSJim Jagielski namespace basegfx 41*b1cdbd2cSJim Jagielski { 42*b1cdbd2cSJim Jagielski namespace 43*b1cdbd2cSJim Jagielski { impIsInside(const B3DPoint & rCandidate,double fPlaneOffset,tools::B3DOrientation ePlaneOrthogonal)44*b1cdbd2cSJim Jagielski inline bool impIsInside(const B3DPoint& rCandidate, double fPlaneOffset, tools::B3DOrientation ePlaneOrthogonal) 45*b1cdbd2cSJim Jagielski { 46*b1cdbd2cSJim Jagielski if(tools::B3DORIENTATION_X == ePlaneOrthogonal) 47*b1cdbd2cSJim Jagielski { 48*b1cdbd2cSJim Jagielski return fTools::moreOrEqual(rCandidate.getX(), fPlaneOffset); 49*b1cdbd2cSJim Jagielski } 50*b1cdbd2cSJim Jagielski else if(tools::B3DORIENTATION_Y == ePlaneOrthogonal) 51*b1cdbd2cSJim Jagielski { 52*b1cdbd2cSJim Jagielski return fTools::moreOrEqual(rCandidate.getY(), fPlaneOffset); 53*b1cdbd2cSJim Jagielski } 54*b1cdbd2cSJim Jagielski else 55*b1cdbd2cSJim Jagielski { 56*b1cdbd2cSJim Jagielski return fTools::moreOrEqual(rCandidate.getZ(), fPlaneOffset); 57*b1cdbd2cSJim Jagielski } 58*b1cdbd2cSJim Jagielski } 59*b1cdbd2cSJim Jagielski impGetCut(const B3DPoint & rCurrent,const B3DPoint & rNext,double fPlaneOffset,tools::B3DOrientation ePlaneOrthogonal)60*b1cdbd2cSJim Jagielski inline double impGetCut(const B3DPoint& rCurrent, const B3DPoint& rNext, double fPlaneOffset, tools::B3DOrientation ePlaneOrthogonal) 61*b1cdbd2cSJim Jagielski { 62*b1cdbd2cSJim Jagielski if(tools::B3DORIENTATION_X == ePlaneOrthogonal) 63*b1cdbd2cSJim Jagielski { 64*b1cdbd2cSJim Jagielski return ((fPlaneOffset - rCurrent.getX())/(rNext.getX() - rCurrent.getX())); 65*b1cdbd2cSJim Jagielski } 66*b1cdbd2cSJim Jagielski else if(tools::B3DORIENTATION_Y == ePlaneOrthogonal) 67*b1cdbd2cSJim Jagielski { 68*b1cdbd2cSJim Jagielski return ((fPlaneOffset - rCurrent.getY())/(rNext.getY() - rCurrent.getY())); 69*b1cdbd2cSJim Jagielski } 70*b1cdbd2cSJim Jagielski else 71*b1cdbd2cSJim Jagielski { 72*b1cdbd2cSJim Jagielski return ((fPlaneOffset - rCurrent.getZ())/(rNext.getZ() - rCurrent.getZ())); 73*b1cdbd2cSJim Jagielski } 74*b1cdbd2cSJim Jagielski } 75*b1cdbd2cSJim Jagielski impAppendCopy(B3DPolygon & rDest,const B3DPolygon & rSource,sal_uInt32 nIndex)76*b1cdbd2cSJim Jagielski void impAppendCopy(B3DPolygon& rDest, const B3DPolygon& rSource, sal_uInt32 nIndex) 77*b1cdbd2cSJim Jagielski { 78*b1cdbd2cSJim Jagielski rDest.append(rSource.getB3DPoint(nIndex)); 79*b1cdbd2cSJim Jagielski 80*b1cdbd2cSJim Jagielski if(rSource.areBColorsUsed()) 81*b1cdbd2cSJim Jagielski { 82*b1cdbd2cSJim Jagielski rDest.setBColor(rDest.count() - 1L, rSource.getBColor(nIndex)); 83*b1cdbd2cSJim Jagielski } 84*b1cdbd2cSJim Jagielski 85*b1cdbd2cSJim Jagielski if(rSource.areNormalsUsed()) 86*b1cdbd2cSJim Jagielski { 87*b1cdbd2cSJim Jagielski rDest.setNormal(rDest.count() - 1L, rSource.getNormal(nIndex)); 88*b1cdbd2cSJim Jagielski } 89*b1cdbd2cSJim Jagielski 90*b1cdbd2cSJim Jagielski if(rSource.areTextureCoordinatesUsed()) 91*b1cdbd2cSJim Jagielski { 92*b1cdbd2cSJim Jagielski rDest.setTextureCoordinate(rDest.count() - 1L, rSource.getTextureCoordinate(nIndex)); 93*b1cdbd2cSJim Jagielski } 94*b1cdbd2cSJim Jagielski } 95*b1cdbd2cSJim Jagielski impAppendInterpolate(B3DPolygon & rDest,const B3DPolygon & rSource,sal_uInt32 nIndA,sal_uInt32 nIndB,double fCut)96*b1cdbd2cSJim Jagielski void impAppendInterpolate(B3DPolygon& rDest, const B3DPolygon& rSource, sal_uInt32 nIndA, sal_uInt32 nIndB, double fCut) 97*b1cdbd2cSJim Jagielski { 98*b1cdbd2cSJim Jagielski const B3DPoint aCurrPoint(rSource.getB3DPoint(nIndA)); 99*b1cdbd2cSJim Jagielski const B3DPoint aNextPoint(rSource.getB3DPoint(nIndB)); 100*b1cdbd2cSJim Jagielski rDest.append(interpolate(aCurrPoint, aNextPoint, fCut)); 101*b1cdbd2cSJim Jagielski 102*b1cdbd2cSJim Jagielski if(rSource.areBColorsUsed()) 103*b1cdbd2cSJim Jagielski { 104*b1cdbd2cSJim Jagielski const BColor aCurrBColor(rSource.getBColor(nIndA)); 105*b1cdbd2cSJim Jagielski const BColor aNextBColor(rSource.getBColor(nIndB)); 106*b1cdbd2cSJim Jagielski rDest.setBColor(rDest.count() - 1L, interpolate(aCurrBColor, aNextBColor, fCut)); 107*b1cdbd2cSJim Jagielski } 108*b1cdbd2cSJim Jagielski 109*b1cdbd2cSJim Jagielski if(rSource.areNormalsUsed()) 110*b1cdbd2cSJim Jagielski { 111*b1cdbd2cSJim Jagielski const B3DVector aCurrVector(rSource.getNormal(nIndA)); 112*b1cdbd2cSJim Jagielski const B3DVector aNextVector(rSource.getNormal(nIndB)); 113*b1cdbd2cSJim Jagielski rDest.setNormal(rDest.count() - 1L, interpolate(aCurrVector, aNextVector, fCut)); 114*b1cdbd2cSJim Jagielski } 115*b1cdbd2cSJim Jagielski 116*b1cdbd2cSJim Jagielski if(rSource.areTextureCoordinatesUsed()) 117*b1cdbd2cSJim Jagielski { 118*b1cdbd2cSJim Jagielski const B2DPoint aCurrTxCo(rSource.getTextureCoordinate(nIndA)); 119*b1cdbd2cSJim Jagielski const B2DPoint aNextTxCo(rSource.getTextureCoordinate(nIndB)); 120*b1cdbd2cSJim Jagielski rDest.setTextureCoordinate(rDest.count() - 1L, interpolate(aCurrTxCo, aNextTxCo, fCut)); 121*b1cdbd2cSJim Jagielski } 122*b1cdbd2cSJim Jagielski } 123*b1cdbd2cSJim Jagielski } 124*b1cdbd2cSJim Jagielski } // end of namespace basegfx 125*b1cdbd2cSJim Jagielski 126*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 127*b1cdbd2cSJim Jagielski 128*b1cdbd2cSJim Jagielski namespace basegfx 129*b1cdbd2cSJim Jagielski { 130*b1cdbd2cSJim Jagielski namespace tools 131*b1cdbd2cSJim Jagielski { clipPolygonOnOrthogonalPlane(const B3DPolygon & rCandidate,B3DOrientation ePlaneOrthogonal,bool bClipPositive,double fPlaneOffset,bool bStroke)132*b1cdbd2cSJim Jagielski B3DPolyPolygon clipPolygonOnOrthogonalPlane(const B3DPolygon& rCandidate, B3DOrientation ePlaneOrthogonal, bool bClipPositive, double fPlaneOffset, bool bStroke) 133*b1cdbd2cSJim Jagielski { 134*b1cdbd2cSJim Jagielski B3DPolyPolygon aRetval; 135*b1cdbd2cSJim Jagielski 136*b1cdbd2cSJim Jagielski if(rCandidate.count()) 137*b1cdbd2cSJim Jagielski { 138*b1cdbd2cSJim Jagielski const B3DRange aCandidateRange(getRange(rCandidate)); 139*b1cdbd2cSJim Jagielski 140*b1cdbd2cSJim Jagielski if(B3DORIENTATION_X == ePlaneOrthogonal && fTools::moreOrEqual(aCandidateRange.getMinX(), fPlaneOffset)) 141*b1cdbd2cSJim Jagielski { 142*b1cdbd2cSJim Jagielski // completely above and on the clip plane. 143*b1cdbd2cSJim Jagielski if(bClipPositive) 144*b1cdbd2cSJim Jagielski { 145*b1cdbd2cSJim Jagielski // add completely 146*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 147*b1cdbd2cSJim Jagielski } 148*b1cdbd2cSJim Jagielski } 149*b1cdbd2cSJim Jagielski else if(B3DORIENTATION_X == ePlaneOrthogonal && fTools::lessOrEqual(aCandidateRange.getMaxX(), fPlaneOffset)) 150*b1cdbd2cSJim Jagielski { 151*b1cdbd2cSJim Jagielski // completely below and on the clip plane. 152*b1cdbd2cSJim Jagielski if(!bClipPositive) 153*b1cdbd2cSJim Jagielski { 154*b1cdbd2cSJim Jagielski // add completely 155*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 156*b1cdbd2cSJim Jagielski } 157*b1cdbd2cSJim Jagielski } 158*b1cdbd2cSJim Jagielski else if(B3DORIENTATION_Y == ePlaneOrthogonal && fTools::moreOrEqual(aCandidateRange.getMinY(), fPlaneOffset)) 159*b1cdbd2cSJim Jagielski { 160*b1cdbd2cSJim Jagielski // completely above and on the clip plane. 161*b1cdbd2cSJim Jagielski if(bClipPositive) 162*b1cdbd2cSJim Jagielski { 163*b1cdbd2cSJim Jagielski // add completely 164*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 165*b1cdbd2cSJim Jagielski } 166*b1cdbd2cSJim Jagielski } 167*b1cdbd2cSJim Jagielski else if(B3DORIENTATION_Y == ePlaneOrthogonal && fTools::lessOrEqual(aCandidateRange.getMaxY(), fPlaneOffset)) 168*b1cdbd2cSJim Jagielski { 169*b1cdbd2cSJim Jagielski // completely below and on the clip plane. 170*b1cdbd2cSJim Jagielski if(!bClipPositive) 171*b1cdbd2cSJim Jagielski { 172*b1cdbd2cSJim Jagielski // add completely 173*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 174*b1cdbd2cSJim Jagielski } 175*b1cdbd2cSJim Jagielski } 176*b1cdbd2cSJim Jagielski else if(B3DORIENTATION_Z == ePlaneOrthogonal && fTools::moreOrEqual(aCandidateRange.getMinZ(), fPlaneOffset)) 177*b1cdbd2cSJim Jagielski { 178*b1cdbd2cSJim Jagielski // completely above and on the clip plane. 179*b1cdbd2cSJim Jagielski if(bClipPositive) 180*b1cdbd2cSJim Jagielski { 181*b1cdbd2cSJim Jagielski // add completely 182*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 183*b1cdbd2cSJim Jagielski } 184*b1cdbd2cSJim Jagielski } 185*b1cdbd2cSJim Jagielski else if(B3DORIENTATION_Z == ePlaneOrthogonal && fTools::lessOrEqual(aCandidateRange.getMaxZ(), fPlaneOffset)) 186*b1cdbd2cSJim Jagielski { 187*b1cdbd2cSJim Jagielski // completely below and on the clip plane. 188*b1cdbd2cSJim Jagielski if(!bClipPositive) 189*b1cdbd2cSJim Jagielski { 190*b1cdbd2cSJim Jagielski // add completely 191*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 192*b1cdbd2cSJim Jagielski } 193*b1cdbd2cSJim Jagielski } 194*b1cdbd2cSJim Jagielski else 195*b1cdbd2cSJim Jagielski { 196*b1cdbd2cSJim Jagielski // prepare loop(s) 197*b1cdbd2cSJim Jagielski B3DPolygon aNewPolygon; 198*b1cdbd2cSJim Jagielski B3DPoint aCurrent(rCandidate.getB3DPoint(0L)); 199*b1cdbd2cSJim Jagielski const sal_uInt32 nPointCount(rCandidate.count()); 200*b1cdbd2cSJim Jagielski const sal_uInt32 nEdgeCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1L); 201*b1cdbd2cSJim Jagielski bool bCurrentInside(impIsInside(aCurrent, fPlaneOffset, ePlaneOrthogonal) == bClipPositive); 202*b1cdbd2cSJim Jagielski 203*b1cdbd2cSJim Jagielski if(bCurrentInside) 204*b1cdbd2cSJim Jagielski { 205*b1cdbd2cSJim Jagielski impAppendCopy(aNewPolygon, rCandidate, 0L); 206*b1cdbd2cSJim Jagielski } 207*b1cdbd2cSJim Jagielski 208*b1cdbd2cSJim Jagielski if(bStroke) 209*b1cdbd2cSJim Jagielski { 210*b1cdbd2cSJim Jagielski // open polygon, create clipped line snippets. 211*b1cdbd2cSJim Jagielski for(sal_uInt32 a(0L); a < nEdgeCount; a++) 212*b1cdbd2cSJim Jagielski { 213*b1cdbd2cSJim Jagielski // get next point data 214*b1cdbd2cSJim Jagielski const sal_uInt32 nNextIndex((a + 1L == nPointCount) ? 0L : a + 1L); 215*b1cdbd2cSJim Jagielski const B3DPoint aNext(rCandidate.getB3DPoint(nNextIndex)); 216*b1cdbd2cSJim Jagielski const bool bNextInside(impIsInside(aNext, fPlaneOffset, ePlaneOrthogonal) == bClipPositive); 217*b1cdbd2cSJim Jagielski 218*b1cdbd2cSJim Jagielski if(bCurrentInside != bNextInside) 219*b1cdbd2cSJim Jagielski { 220*b1cdbd2cSJim Jagielski // change inside/outside 221*b1cdbd2cSJim Jagielski if(bNextInside) 222*b1cdbd2cSJim Jagielski { 223*b1cdbd2cSJim Jagielski // entering, finish existing and start new line polygon 224*b1cdbd2cSJim Jagielski if(aNewPolygon.count() > 1L) 225*b1cdbd2cSJim Jagielski { 226*b1cdbd2cSJim Jagielski aRetval.append(aNewPolygon); 227*b1cdbd2cSJim Jagielski } 228*b1cdbd2cSJim Jagielski 229*b1cdbd2cSJim Jagielski aNewPolygon.clear(); 230*b1cdbd2cSJim Jagielski } 231*b1cdbd2cSJim Jagielski 232*b1cdbd2cSJim Jagielski // calculate and add cut point 233*b1cdbd2cSJim Jagielski const double fCut(impGetCut(aCurrent, aNext, fPlaneOffset, ePlaneOrthogonal)); 234*b1cdbd2cSJim Jagielski impAppendInterpolate(aNewPolygon, rCandidate, a, nNextIndex, fCut); 235*b1cdbd2cSJim Jagielski 236*b1cdbd2cSJim Jagielski // pepare next step 237*b1cdbd2cSJim Jagielski bCurrentInside = bNextInside; 238*b1cdbd2cSJim Jagielski } 239*b1cdbd2cSJim Jagielski 240*b1cdbd2cSJim Jagielski if(bNextInside) 241*b1cdbd2cSJim Jagielski { 242*b1cdbd2cSJim Jagielski impAppendCopy(aNewPolygon, rCandidate, nNextIndex); 243*b1cdbd2cSJim Jagielski } 244*b1cdbd2cSJim Jagielski 245*b1cdbd2cSJim Jagielski // pepare next step 246*b1cdbd2cSJim Jagielski aCurrent = aNext; 247*b1cdbd2cSJim Jagielski } 248*b1cdbd2cSJim Jagielski 249*b1cdbd2cSJim Jagielski if(aNewPolygon.count() > 1L) 250*b1cdbd2cSJim Jagielski { 251*b1cdbd2cSJim Jagielski aRetval.append(aNewPolygon); 252*b1cdbd2cSJim Jagielski } 253*b1cdbd2cSJim Jagielski } 254*b1cdbd2cSJim Jagielski else 255*b1cdbd2cSJim Jagielski { 256*b1cdbd2cSJim Jagielski // closed polygon, create single clipped closed polygon 257*b1cdbd2cSJim Jagielski for(sal_uInt32 a(0L); a < nEdgeCount; a++) 258*b1cdbd2cSJim Jagielski { 259*b1cdbd2cSJim Jagielski // get next point data, use offset 260*b1cdbd2cSJim Jagielski const sal_uInt32 nNextIndex((a + 1L == nPointCount) ? 0L : a + 1L); 261*b1cdbd2cSJim Jagielski const B3DPoint aNext(rCandidate.getB3DPoint(nNextIndex)); 262*b1cdbd2cSJim Jagielski const bool bNextInside(impIsInside(aNext, fPlaneOffset, ePlaneOrthogonal) == bClipPositive); 263*b1cdbd2cSJim Jagielski 264*b1cdbd2cSJim Jagielski if(bCurrentInside != bNextInside) 265*b1cdbd2cSJim Jagielski { 266*b1cdbd2cSJim Jagielski // calculate and add cut point 267*b1cdbd2cSJim Jagielski const double fCut(impGetCut(aCurrent, aNext, fPlaneOffset, ePlaneOrthogonal)); 268*b1cdbd2cSJim Jagielski impAppendInterpolate(aNewPolygon, rCandidate, a, nNextIndex, fCut); 269*b1cdbd2cSJim Jagielski 270*b1cdbd2cSJim Jagielski // pepare next step 271*b1cdbd2cSJim Jagielski bCurrentInside = bNextInside; 272*b1cdbd2cSJim Jagielski } 273*b1cdbd2cSJim Jagielski 274*b1cdbd2cSJim Jagielski if(bNextInside && nNextIndex) 275*b1cdbd2cSJim Jagielski { 276*b1cdbd2cSJim Jagielski impAppendCopy(aNewPolygon, rCandidate, nNextIndex); 277*b1cdbd2cSJim Jagielski } 278*b1cdbd2cSJim Jagielski 279*b1cdbd2cSJim Jagielski // pepare next step 280*b1cdbd2cSJim Jagielski aCurrent = aNext; 281*b1cdbd2cSJim Jagielski } 282*b1cdbd2cSJim Jagielski 283*b1cdbd2cSJim Jagielski if(aNewPolygon.count() > 2L) 284*b1cdbd2cSJim Jagielski { 285*b1cdbd2cSJim Jagielski aNewPolygon.setClosed(true); 286*b1cdbd2cSJim Jagielski aRetval.append(aNewPolygon); 287*b1cdbd2cSJim Jagielski } 288*b1cdbd2cSJim Jagielski } 289*b1cdbd2cSJim Jagielski } 290*b1cdbd2cSJim Jagielski } 291*b1cdbd2cSJim Jagielski 292*b1cdbd2cSJim Jagielski return aRetval; 293*b1cdbd2cSJim Jagielski } 294*b1cdbd2cSJim Jagielski clipPolyPolygonOnOrthogonalPlane(const B3DPolyPolygon & rCandidate,B3DOrientation ePlaneOrthogonal,bool bClipPositive,double fPlaneOffset,bool bStroke)295*b1cdbd2cSJim Jagielski B3DPolyPolygon clipPolyPolygonOnOrthogonalPlane(const B3DPolyPolygon& rCandidate, B3DOrientation ePlaneOrthogonal, bool bClipPositive, double fPlaneOffset, bool bStroke) 296*b1cdbd2cSJim Jagielski { 297*b1cdbd2cSJim Jagielski B3DPolyPolygon aRetval; 298*b1cdbd2cSJim Jagielski 299*b1cdbd2cSJim Jagielski for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 300*b1cdbd2cSJim Jagielski { 301*b1cdbd2cSJim Jagielski aRetval.append(clipPolygonOnOrthogonalPlane(rCandidate.getB3DPolygon(a), ePlaneOrthogonal, bClipPositive, fPlaneOffset, bStroke)); 302*b1cdbd2cSJim Jagielski } 303*b1cdbd2cSJim Jagielski 304*b1cdbd2cSJim Jagielski return aRetval; 305*b1cdbd2cSJim Jagielski } 306*b1cdbd2cSJim Jagielski clipPolyPolygonOnRange(const B3DPolyPolygon & rCandidate,const B2DRange & rRange,bool bInside,bool bStroke)307*b1cdbd2cSJim Jagielski B3DPolyPolygon clipPolyPolygonOnRange(const B3DPolyPolygon& rCandidate, const B2DRange& rRange, bool bInside, bool bStroke) 308*b1cdbd2cSJim Jagielski { 309*b1cdbd2cSJim Jagielski B3DPolyPolygon aRetval; 310*b1cdbd2cSJim Jagielski 311*b1cdbd2cSJim Jagielski for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 312*b1cdbd2cSJim Jagielski { 313*b1cdbd2cSJim Jagielski aRetval.append(clipPolygonOnRange(rCandidate.getB3DPolygon(a), rRange, bInside, bStroke)); 314*b1cdbd2cSJim Jagielski } 315*b1cdbd2cSJim Jagielski 316*b1cdbd2cSJim Jagielski return aRetval; 317*b1cdbd2cSJim Jagielski } 318*b1cdbd2cSJim Jagielski clipPolygonOnRange(const B3DPolygon & rCandidate,const B2DRange & rRange,bool bInside,bool bStroke)319*b1cdbd2cSJim Jagielski B3DPolyPolygon clipPolygonOnRange(const B3DPolygon& rCandidate, const B2DRange& rRange, bool bInside, bool bStroke) 320*b1cdbd2cSJim Jagielski { 321*b1cdbd2cSJim Jagielski B3DPolyPolygon aRetval; 322*b1cdbd2cSJim Jagielski 323*b1cdbd2cSJim Jagielski if(rRange.isEmpty()) 324*b1cdbd2cSJim Jagielski { 325*b1cdbd2cSJim Jagielski // clipping against an empty range. Nothing is inside an empty range, so the polygon 326*b1cdbd2cSJim Jagielski // is outside the range. So only return if not inside is wanted 327*b1cdbd2cSJim Jagielski if(!bInside && rCandidate.count()) 328*b1cdbd2cSJim Jagielski { 329*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 330*b1cdbd2cSJim Jagielski } 331*b1cdbd2cSJim Jagielski } 332*b1cdbd2cSJim Jagielski else if(rCandidate.count()) 333*b1cdbd2cSJim Jagielski { 334*b1cdbd2cSJim Jagielski const B3DRange aCandidateRange3D(getRange(rCandidate)); 335*b1cdbd2cSJim Jagielski const B2DRange aCandidateRange( 336*b1cdbd2cSJim Jagielski aCandidateRange3D.getMinX(), aCandidateRange3D.getMinY(), 337*b1cdbd2cSJim Jagielski aCandidateRange3D.getMaxX(), aCandidateRange3D.getMaxY()); 338*b1cdbd2cSJim Jagielski 339*b1cdbd2cSJim Jagielski if(rRange.isInside(aCandidateRange)) 340*b1cdbd2cSJim Jagielski { 341*b1cdbd2cSJim Jagielski // candidate is completely inside given range, nothing to do. Is also true with curves. 342*b1cdbd2cSJim Jagielski if(bInside) 343*b1cdbd2cSJim Jagielski { 344*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 345*b1cdbd2cSJim Jagielski } 346*b1cdbd2cSJim Jagielski } 347*b1cdbd2cSJim Jagielski else if(!rRange.overlaps(aCandidateRange)) 348*b1cdbd2cSJim Jagielski { 349*b1cdbd2cSJim Jagielski // candidate is completely outside given range, nothing to do. Is also true with curves. 350*b1cdbd2cSJim Jagielski if(!bInside) 351*b1cdbd2cSJim Jagielski { 352*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 353*b1cdbd2cSJim Jagielski } 354*b1cdbd2cSJim Jagielski } 355*b1cdbd2cSJim Jagielski else 356*b1cdbd2cSJim Jagielski { 357*b1cdbd2cSJim Jagielski // clip against the six planes of the range 358*b1cdbd2cSJim Jagielski // against lower X 359*b1cdbd2cSJim Jagielski aRetval = clipPolygonOnOrthogonalPlane(rCandidate, tools::B3DORIENTATION_X, bInside, rRange.getMinX(), bStroke); 360*b1cdbd2cSJim Jagielski 361*b1cdbd2cSJim Jagielski if(aRetval.count()) 362*b1cdbd2cSJim Jagielski { 363*b1cdbd2cSJim Jagielski // against lower Y 364*b1cdbd2cSJim Jagielski if(1L == aRetval.count()) 365*b1cdbd2cSJim Jagielski { 366*b1cdbd2cSJim Jagielski aRetval = clipPolygonOnOrthogonalPlane(aRetval.getB3DPolygon(0L), tools::B3DORIENTATION_Y, bInside, rRange.getMinY(), bStroke); 367*b1cdbd2cSJim Jagielski } 368*b1cdbd2cSJim Jagielski else 369*b1cdbd2cSJim Jagielski { 370*b1cdbd2cSJim Jagielski aRetval = clipPolyPolygonOnOrthogonalPlane(aRetval, tools::B3DORIENTATION_Y, bInside, rRange.getMinY(), bStroke); 371*b1cdbd2cSJim Jagielski } 372*b1cdbd2cSJim Jagielski 373*b1cdbd2cSJim Jagielski if(aRetval.count()) 374*b1cdbd2cSJim Jagielski { 375*b1cdbd2cSJim Jagielski // against higher X 376*b1cdbd2cSJim Jagielski if(1L == aRetval.count()) 377*b1cdbd2cSJim Jagielski { 378*b1cdbd2cSJim Jagielski aRetval = clipPolygonOnOrthogonalPlane(aRetval.getB3DPolygon(0L), tools::B3DORIENTATION_X, !bInside, rRange.getMaxX(), bStroke); 379*b1cdbd2cSJim Jagielski } 380*b1cdbd2cSJim Jagielski else 381*b1cdbd2cSJim Jagielski { 382*b1cdbd2cSJim Jagielski aRetval = clipPolyPolygonOnOrthogonalPlane(aRetval, tools::B3DORIENTATION_X, !bInside, rRange.getMaxX(), bStroke); 383*b1cdbd2cSJim Jagielski } 384*b1cdbd2cSJim Jagielski 385*b1cdbd2cSJim Jagielski if(aRetval.count()) 386*b1cdbd2cSJim Jagielski { 387*b1cdbd2cSJim Jagielski // against higher Y 388*b1cdbd2cSJim Jagielski if(1L == aRetval.count()) 389*b1cdbd2cSJim Jagielski { 390*b1cdbd2cSJim Jagielski aRetval = clipPolygonOnOrthogonalPlane(aRetval.getB3DPolygon(0L), tools::B3DORIENTATION_Y, !bInside, rRange.getMaxY(), bStroke); 391*b1cdbd2cSJim Jagielski } 392*b1cdbd2cSJim Jagielski else 393*b1cdbd2cSJim Jagielski { 394*b1cdbd2cSJim Jagielski aRetval = clipPolyPolygonOnOrthogonalPlane(aRetval, tools::B3DORIENTATION_Y, !bInside, rRange.getMaxY(), bStroke); 395*b1cdbd2cSJim Jagielski } 396*b1cdbd2cSJim Jagielski } 397*b1cdbd2cSJim Jagielski } 398*b1cdbd2cSJim Jagielski } 399*b1cdbd2cSJim Jagielski } 400*b1cdbd2cSJim Jagielski } 401*b1cdbd2cSJim Jagielski 402*b1cdbd2cSJim Jagielski return aRetval; 403*b1cdbd2cSJim Jagielski } 404*b1cdbd2cSJim Jagielski clipPolyPolygonOnRange(const B3DPolyPolygon & rCandidate,const B3DRange & rRange,bool bInside,bool bStroke)405*b1cdbd2cSJim Jagielski B3DPolyPolygon clipPolyPolygonOnRange(const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bInside, bool bStroke) 406*b1cdbd2cSJim Jagielski { 407*b1cdbd2cSJim Jagielski B3DPolyPolygon aRetval; 408*b1cdbd2cSJim Jagielski 409*b1cdbd2cSJim Jagielski for(sal_uInt32 a(0L); a < rCandidate.count(); a++) 410*b1cdbd2cSJim Jagielski { 411*b1cdbd2cSJim Jagielski aRetval.append(clipPolygonOnRange(rCandidate.getB3DPolygon(a), rRange, bInside, bStroke)); 412*b1cdbd2cSJim Jagielski } 413*b1cdbd2cSJim Jagielski 414*b1cdbd2cSJim Jagielski return aRetval; 415*b1cdbd2cSJim Jagielski } 416*b1cdbd2cSJim Jagielski clipPolygonOnRange(const B3DPolygon & rCandidate,const B3DRange & rRange,bool bInside,bool bStroke)417*b1cdbd2cSJim Jagielski B3DPolyPolygon clipPolygonOnRange(const B3DPolygon& rCandidate, const B3DRange& rRange, bool bInside, bool bStroke) 418*b1cdbd2cSJim Jagielski { 419*b1cdbd2cSJim Jagielski B3DPolyPolygon aRetval; 420*b1cdbd2cSJim Jagielski 421*b1cdbd2cSJim Jagielski if(rRange.isEmpty()) 422*b1cdbd2cSJim Jagielski { 423*b1cdbd2cSJim Jagielski // clipping against an empty range. Nothing is inside an empty range, so the polygon 424*b1cdbd2cSJim Jagielski // is outside the range. So only return if not inside is wanted 425*b1cdbd2cSJim Jagielski if(!bInside && rCandidate.count()) 426*b1cdbd2cSJim Jagielski { 427*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 428*b1cdbd2cSJim Jagielski } 429*b1cdbd2cSJim Jagielski } 430*b1cdbd2cSJim Jagielski else if(rCandidate.count()) 431*b1cdbd2cSJim Jagielski { 432*b1cdbd2cSJim Jagielski const B3DRange aCandidateRange(getRange(rCandidate)); 433*b1cdbd2cSJim Jagielski 434*b1cdbd2cSJim Jagielski if(rRange.isInside(aCandidateRange)) 435*b1cdbd2cSJim Jagielski { 436*b1cdbd2cSJim Jagielski // candidate is completely inside given range, nothing to do. Is also true with curves. 437*b1cdbd2cSJim Jagielski if(bInside) 438*b1cdbd2cSJim Jagielski { 439*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 440*b1cdbd2cSJim Jagielski } 441*b1cdbd2cSJim Jagielski } 442*b1cdbd2cSJim Jagielski else if(!rRange.overlaps(aCandidateRange)) 443*b1cdbd2cSJim Jagielski { 444*b1cdbd2cSJim Jagielski // candidate is completely outside given range, nothing to do. Is also true with curves. 445*b1cdbd2cSJim Jagielski if(!bInside) 446*b1cdbd2cSJim Jagielski { 447*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 448*b1cdbd2cSJim Jagielski } 449*b1cdbd2cSJim Jagielski } 450*b1cdbd2cSJim Jagielski else 451*b1cdbd2cSJim Jagielski { 452*b1cdbd2cSJim Jagielski // clip against X,Y first and see if there's something left 453*b1cdbd2cSJim Jagielski const B2DRange aCandidateRange2D(rRange.getMinX(), rRange.getMinY(), rRange.getMaxX(), rRange.getMaxY()); 454*b1cdbd2cSJim Jagielski aRetval = clipPolygonOnRange(rCandidate, aCandidateRange2D, bInside, bStroke); 455*b1cdbd2cSJim Jagielski 456*b1cdbd2cSJim Jagielski if(aRetval.count()) 457*b1cdbd2cSJim Jagielski { 458*b1cdbd2cSJim Jagielski // against lower Z 459*b1cdbd2cSJim Jagielski if(1L == aRetval.count()) 460*b1cdbd2cSJim Jagielski { 461*b1cdbd2cSJim Jagielski aRetval = clipPolygonOnOrthogonalPlane(aRetval.getB3DPolygon(0L), tools::B3DORIENTATION_Z, bInside, rRange.getMinZ(), bStroke); 462*b1cdbd2cSJim Jagielski } 463*b1cdbd2cSJim Jagielski else 464*b1cdbd2cSJim Jagielski { 465*b1cdbd2cSJim Jagielski aRetval = clipPolyPolygonOnOrthogonalPlane(aRetval, tools::B3DORIENTATION_Z, bInside, rRange.getMinZ(), bStroke); 466*b1cdbd2cSJim Jagielski } 467*b1cdbd2cSJim Jagielski 468*b1cdbd2cSJim Jagielski if(aRetval.count()) 469*b1cdbd2cSJim Jagielski { 470*b1cdbd2cSJim Jagielski // against higher Z 471*b1cdbd2cSJim Jagielski if(1L == aRetval.count()) 472*b1cdbd2cSJim Jagielski { 473*b1cdbd2cSJim Jagielski aRetval = clipPolygonOnOrthogonalPlane(aRetval.getB3DPolygon(0L), tools::B3DORIENTATION_Z, !bInside, rRange.getMaxZ(), bStroke); 474*b1cdbd2cSJim Jagielski } 475*b1cdbd2cSJim Jagielski else 476*b1cdbd2cSJim Jagielski { 477*b1cdbd2cSJim Jagielski aRetval = clipPolyPolygonOnOrthogonalPlane(aRetval, tools::B3DORIENTATION_Z, !bInside, rRange.getMaxZ(), bStroke); 478*b1cdbd2cSJim Jagielski } 479*b1cdbd2cSJim Jagielski } 480*b1cdbd2cSJim Jagielski } 481*b1cdbd2cSJim Jagielski } 482*b1cdbd2cSJim Jagielski } 483*b1cdbd2cSJim Jagielski 484*b1cdbd2cSJim Jagielski return aRetval; 485*b1cdbd2cSJim Jagielski } 486*b1cdbd2cSJim Jagielski clipPolygonOnPlane(const B3DPolygon & rCandidate,const B3DPoint & rPointOnPlane,const B3DVector & rPlaneNormal,bool bClipPositive,bool bStroke)487*b1cdbd2cSJim Jagielski B3DPolyPolygon clipPolygonOnPlane(const B3DPolygon& rCandidate, const B3DPoint& rPointOnPlane, const B3DVector& rPlaneNormal, bool bClipPositive, bool bStroke) 488*b1cdbd2cSJim Jagielski { 489*b1cdbd2cSJim Jagielski B3DPolyPolygon aRetval; 490*b1cdbd2cSJim Jagielski 491*b1cdbd2cSJim Jagielski if(rPlaneNormal.equalZero()) 492*b1cdbd2cSJim Jagielski { 493*b1cdbd2cSJim Jagielski // not really a plane definition, return polygon 494*b1cdbd2cSJim Jagielski aRetval.append(rCandidate); 495*b1cdbd2cSJim Jagielski } 496*b1cdbd2cSJim Jagielski else if(rCandidate.count()) 497*b1cdbd2cSJim Jagielski { 498*b1cdbd2cSJim Jagielski // build transform to project planeNormal on X-Axis and pointOnPlane to null point 499*b1cdbd2cSJim Jagielski B3DHomMatrix aMatrixTransform; 500*b1cdbd2cSJim Jagielski aMatrixTransform.translate(-rPointOnPlane.getX(), -rPointOnPlane.getY(), -rPointOnPlane.getZ()); 501*b1cdbd2cSJim Jagielski const double fRotInXY(atan2(rPlaneNormal.getY(), rPlaneNormal.getX())); 502*b1cdbd2cSJim Jagielski const double fRotInXZ(atan2(-rPlaneNormal.getZ(), rPlaneNormal.getXYLength())); 503*b1cdbd2cSJim Jagielski if(!fTools::equalZero(fRotInXY) || !fTools::equalZero(fRotInXZ)) 504*b1cdbd2cSJim Jagielski { 505*b1cdbd2cSJim Jagielski aMatrixTransform.rotate(0.0, fRotInXZ, fRotInXY); 506*b1cdbd2cSJim Jagielski } 507*b1cdbd2cSJim Jagielski 508*b1cdbd2cSJim Jagielski // transform polygon to clip scenario 509*b1cdbd2cSJim Jagielski B3DPolygon aCandidate(rCandidate); 510*b1cdbd2cSJim Jagielski aCandidate.transform(aMatrixTransform); 511*b1cdbd2cSJim Jagielski 512*b1cdbd2cSJim Jagielski // clip on YZ plane 513*b1cdbd2cSJim Jagielski aRetval = clipPolygonOnOrthogonalPlane(aCandidate, tools::B3DORIENTATION_X, bClipPositive, 0.0, bStroke); 514*b1cdbd2cSJim Jagielski 515*b1cdbd2cSJim Jagielski if(aRetval.count()) 516*b1cdbd2cSJim Jagielski { 517*b1cdbd2cSJim Jagielski // if there is a result, it needs to be transformed back 518*b1cdbd2cSJim Jagielski aMatrixTransform.invert(); 519*b1cdbd2cSJim Jagielski aRetval.transform(aMatrixTransform); 520*b1cdbd2cSJim Jagielski } 521*b1cdbd2cSJim Jagielski } 522*b1cdbd2cSJim Jagielski 523*b1cdbd2cSJim Jagielski return aRetval; 524*b1cdbd2cSJim Jagielski } 525*b1cdbd2cSJim Jagielski clipPolyPolygonOnPlane(const B3DPolyPolygon & rCandidate,const B3DPoint & rPointOnPlane,const B3DVector & rPlaneNormal,bool bClipPositive,bool bStroke)526*b1cdbd2cSJim Jagielski B3DPolyPolygon clipPolyPolygonOnPlane(const B3DPolyPolygon& rCandidate, const B3DPoint& rPointOnPlane, const B3DVector& rPlaneNormal, bool bClipPositive, bool bStroke) 527*b1cdbd2cSJim Jagielski { 528*b1cdbd2cSJim Jagielski B3DPolyPolygon aRetval; 529*b1cdbd2cSJim Jagielski 530*b1cdbd2cSJim Jagielski if(rPlaneNormal.equalZero()) 531*b1cdbd2cSJim Jagielski { 532*b1cdbd2cSJim Jagielski // not really a plane definition, return polygon 533*b1cdbd2cSJim Jagielski aRetval = rCandidate; 534*b1cdbd2cSJim Jagielski } 535*b1cdbd2cSJim Jagielski else if(rCandidate.count()) 536*b1cdbd2cSJim Jagielski { 537*b1cdbd2cSJim Jagielski // build transform to project planeNormal on X-Axis and pointOnPlane to null point 538*b1cdbd2cSJim Jagielski B3DHomMatrix aMatrixTransform; 539*b1cdbd2cSJim Jagielski aMatrixTransform.translate(-rPointOnPlane.getX(), -rPointOnPlane.getY(), -rPointOnPlane.getZ()); 540*b1cdbd2cSJim Jagielski const double fRotInXY(atan2(rPlaneNormal.getY(), rPlaneNormal.getX())); 541*b1cdbd2cSJim Jagielski const double fRotInXZ(atan2(-rPlaneNormal.getZ(), rPlaneNormal.getXYLength())); 542*b1cdbd2cSJim Jagielski if(!fTools::equalZero(fRotInXY) || !fTools::equalZero(fRotInXZ)) 543*b1cdbd2cSJim Jagielski { 544*b1cdbd2cSJim Jagielski aMatrixTransform.rotate(0.0, fRotInXZ, fRotInXY); 545*b1cdbd2cSJim Jagielski } 546*b1cdbd2cSJim Jagielski 547*b1cdbd2cSJim Jagielski // transform polygon to clip scenario 548*b1cdbd2cSJim Jagielski aRetval = rCandidate; 549*b1cdbd2cSJim Jagielski aRetval.transform(aMatrixTransform); 550*b1cdbd2cSJim Jagielski 551*b1cdbd2cSJim Jagielski // clip on YZ plane 552*b1cdbd2cSJim Jagielski aRetval = clipPolyPolygonOnOrthogonalPlane(aRetval, tools::B3DORIENTATION_X, bClipPositive, 0.0, bStroke); 553*b1cdbd2cSJim Jagielski 554*b1cdbd2cSJim Jagielski if(aRetval.count()) 555*b1cdbd2cSJim Jagielski { 556*b1cdbd2cSJim Jagielski // if there is a result, it needs to be transformed back 557*b1cdbd2cSJim Jagielski aMatrixTransform.invert(); 558*b1cdbd2cSJim Jagielski aRetval.transform(aMatrixTransform); 559*b1cdbd2cSJim Jagielski } 560*b1cdbd2cSJim Jagielski } 561*b1cdbd2cSJim Jagielski 562*b1cdbd2cSJim Jagielski return aRetval; 563*b1cdbd2cSJim Jagielski } 564*b1cdbd2cSJim Jagielski 565*b1cdbd2cSJim Jagielski } // end of namespace tools 566*b1cdbd2cSJim Jagielski } // end of namespace basegfx 567*b1cdbd2cSJim Jagielski 568*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 569*b1cdbd2cSJim Jagielski 570*b1cdbd2cSJim Jagielski // eof 571