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