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 #ifndef _BGFX_POLYGON_B2DPOLYGON_HXX 25*b1cdbd2cSJim Jagielski #define _BGFX_POLYGON_B2DPOLYGON_HXX 26*b1cdbd2cSJim Jagielski 27*b1cdbd2cSJim Jagielski #include <sal/types.h> 28*b1cdbd2cSJim Jagielski #include <o3tl/cow_wrapper.hxx> 29*b1cdbd2cSJim Jagielski #include <basegfx/vector/b2enums.hxx> 30*b1cdbd2cSJim Jagielski #include <basegfx/range/b2drange.hxx> 31*b1cdbd2cSJim Jagielski 32*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 33*b1cdbd2cSJim Jagielski // predeclarations 34*b1cdbd2cSJim Jagielski class ImplB2DPolygon; 35*b1cdbd2cSJim Jagielski 36*b1cdbd2cSJim Jagielski namespace basegfx 37*b1cdbd2cSJim Jagielski { 38*b1cdbd2cSJim Jagielski class B2DPolygon; 39*b1cdbd2cSJim Jagielski class B2DPoint; 40*b1cdbd2cSJim Jagielski class B2DVector; 41*b1cdbd2cSJim Jagielski class B2DHomMatrix; 42*b1cdbd2cSJim Jagielski class B2DCubicBezier; 43*b1cdbd2cSJim Jagielski } // end of namespace basegfx 44*b1cdbd2cSJim Jagielski 45*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 46*b1cdbd2cSJim Jagielski 47*b1cdbd2cSJim Jagielski namespace basegfx 48*b1cdbd2cSJim Jagielski { 49*b1cdbd2cSJim Jagielski class B2DPolygon 50*b1cdbd2cSJim Jagielski { 51*b1cdbd2cSJim Jagielski public: 52*b1cdbd2cSJim Jagielski typedef o3tl::cow_wrapper< ImplB2DPolygon > ImplType; 53*b1cdbd2cSJim Jagielski 54*b1cdbd2cSJim Jagielski private: 55*b1cdbd2cSJim Jagielski // internal data. 56*b1cdbd2cSJim Jagielski ImplType mpPolygon; 57*b1cdbd2cSJim Jagielski 58*b1cdbd2cSJim Jagielski public: 59*b1cdbd2cSJim Jagielski /// diverse constructors 60*b1cdbd2cSJim Jagielski B2DPolygon(); 61*b1cdbd2cSJim Jagielski B2DPolygon(const B2DPolygon& rPolygon); 62*b1cdbd2cSJim Jagielski B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount); 63*b1cdbd2cSJim Jagielski ~B2DPolygon(); 64*b1cdbd2cSJim Jagielski 65*b1cdbd2cSJim Jagielski /// assignment operator 66*b1cdbd2cSJim Jagielski B2DPolygon& operator=(const B2DPolygon& rPolygon); 67*b1cdbd2cSJim Jagielski 68*b1cdbd2cSJim Jagielski /// unshare this polygon with all internally shared instances 69*b1cdbd2cSJim Jagielski void makeUnique(); 70*b1cdbd2cSJim Jagielski 71*b1cdbd2cSJim Jagielski /// compare operators 72*b1cdbd2cSJim Jagielski bool operator==(const B2DPolygon& rPolygon) const; 73*b1cdbd2cSJim Jagielski bool operator!=(const B2DPolygon& rPolygon) const; 74*b1cdbd2cSJim Jagielski 75*b1cdbd2cSJim Jagielski /// member count 76*b1cdbd2cSJim Jagielski sal_uInt32 count() const; 77*b1cdbd2cSJim Jagielski 78*b1cdbd2cSJim Jagielski /// Coordinate interface 79*b1cdbd2cSJim Jagielski basegfx::B2DPoint getB2DPoint(sal_uInt32 nIndex) const; 80*b1cdbd2cSJim Jagielski void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); 81*b1cdbd2cSJim Jagielski 82*b1cdbd2cSJim Jagielski /// Coordinate insert/append 83*b1cdbd2cSJim Jagielski void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount = 1); 84*b1cdbd2cSJim Jagielski void append(const basegfx::B2DPoint& rPoint, sal_uInt32 nCount); 85*b1cdbd2cSJim Jagielski void append(const basegfx::B2DPoint& rPoint); 86*b1cdbd2cSJim Jagielski void reserve(sal_uInt32 nCount); 87*b1cdbd2cSJim Jagielski 88*b1cdbd2cSJim Jagielski /// Basic ControlPoint interface 89*b1cdbd2cSJim Jagielski basegfx::B2DPoint getPrevControlPoint(sal_uInt32 nIndex) const; 90*b1cdbd2cSJim Jagielski basegfx::B2DPoint getNextControlPoint(sal_uInt32 nIndex) const; 91*b1cdbd2cSJim Jagielski void setPrevControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); 92*b1cdbd2cSJim Jagielski void setNextControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); 93*b1cdbd2cSJim Jagielski void setControlPoints(sal_uInt32 nIndex, const basegfx::B2DPoint& rPrev, const basegfx::B2DPoint& rNext); 94*b1cdbd2cSJim Jagielski 95*b1cdbd2cSJim Jagielski /// ControlPoint resets 96*b1cdbd2cSJim Jagielski void resetPrevControlPoint(sal_uInt32 nIndex); 97*b1cdbd2cSJim Jagielski void resetNextControlPoint(sal_uInt32 nIndex); 98*b1cdbd2cSJim Jagielski void resetControlPoints(sal_uInt32 nIndex); 99*b1cdbd2cSJim Jagielski void resetControlPoints(); 100*b1cdbd2cSJim Jagielski 101*b1cdbd2cSJim Jagielski /// Bezier segment append with control points. The current last polygon point is implicitly taken as start point. 102*b1cdbd2cSJim Jagielski void appendBezierSegment(const basegfx::B2DPoint& rNextControlPoint, const basegfx::B2DPoint& rPrevControlPoint, const basegfx::B2DPoint& rPoint); 103*b1cdbd2cSJim Jagielski 104*b1cdbd2cSJim Jagielski /// ControlPoint checks 105*b1cdbd2cSJim Jagielski bool areControlPointsUsed() const; 106*b1cdbd2cSJim Jagielski bool isPrevControlPointUsed(sal_uInt32 nIndex) const; 107*b1cdbd2cSJim Jagielski bool isNextControlPointUsed(sal_uInt32 nIndex) const; 108*b1cdbd2cSJim Jagielski B2VectorContinuity getContinuityInPoint(sal_uInt32 nIndex) const; 109*b1cdbd2cSJim Jagielski 110*b1cdbd2cSJim Jagielski /** check edge for being a bezier segment 111*b1cdbd2cSJim Jagielski 112*b1cdbd2cSJim Jagielski This test the existance of control vectors, but do not apply 113*b1cdbd2cSJim Jagielski testAndSolveTrivialBezier() to the bezier segment, so it is still useful 114*b1cdbd2cSJim Jagielski to do so. 115*b1cdbd2cSJim Jagielski Since it can use internal data representations, it is faster 116*b1cdbd2cSJim Jagielski than using getBezierSegment() and applying isBezier() on it. 117*b1cdbd2cSJim Jagielski 118*b1cdbd2cSJim Jagielski @param nIndex 119*b1cdbd2cSJim Jagielski Index of the addressed edge's start point 120*b1cdbd2cSJim Jagielski 121*b1cdbd2cSJim Jagielski @return 122*b1cdbd2cSJim Jagielski true if edge exists and at least one control vector is used 123*b1cdbd2cSJim Jagielski */ 124*b1cdbd2cSJim Jagielski bool isBezierSegment(sal_uInt32 nIndex) const; 125*b1cdbd2cSJim Jagielski 126*b1cdbd2cSJim Jagielski /** bezier segment access 127*b1cdbd2cSJim Jagielski 128*b1cdbd2cSJim Jagielski This method also works when it is no bezier segment at all and will fill 129*b1cdbd2cSJim Jagielski the given B2DCubicBezier as needed. 130*b1cdbd2cSJim Jagielski In any case, the given B2DCubicBezier will be filled, if necessary with 131*b1cdbd2cSJim Jagielski the single start point (if no valid edge exists). 132*b1cdbd2cSJim Jagielski 133*b1cdbd2cSJim Jagielski @param nIndex 134*b1cdbd2cSJim Jagielski Index of the addressed edge's start point 135*b1cdbd2cSJim Jagielski 136*b1cdbd2cSJim Jagielski @param rTarget 137*b1cdbd2cSJim Jagielski The B2DCubicBezier to be filled. It's data WILL be changed. 138*b1cdbd2cSJim Jagielski */ 139*b1cdbd2cSJim Jagielski void getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const; 140*b1cdbd2cSJim Jagielski 141*b1cdbd2cSJim Jagielski /** Default adaptive subdivision access 142*b1cdbd2cSJim Jagielski 143*b1cdbd2cSJim Jagielski This method will return a default adapive subdivision of the polygon. 144*b1cdbd2cSJim Jagielski If the polygon does not contain any bezier curve segments, it will 145*b1cdbd2cSJim Jagielski just return itself. 146*b1cdbd2cSJim Jagielski 147*b1cdbd2cSJim Jagielski The subdivision is created on first request and buffered, so when using 148*b1cdbd2cSJim Jagielski this subdivision You have the guarantee for fast accesses for multiple 149*b1cdbd2cSJim Jagielski usages. It is intended for tooling usage for tasks which would be hard 150*b1cdbd2cSJim Jagielski to accomplish on bezier segments (e.g. isInEpsilonRange). 151*b1cdbd2cSJim Jagielski 152*b1cdbd2cSJim Jagielski The current default subdivision uses adaptiveSubdivideByCount with 9 153*b1cdbd2cSJim Jagielski subdivisions which gives 10 edges and 11 points per segment and is 154*b1cdbd2cSJim Jagielski usually pretty usable for processing purposes. There is no parameter 155*b1cdbd2cSJim Jagielski passing here ATM but it may be changed on demand. If needed, a TYPE 156*b1cdbd2cSJim Jagielski and PARAMETER (both defaulted) may be added to allow for switching 157*b1cdbd2cSJim Jagielski between the different kinds of subdivisiond and passing them one 158*b1cdbd2cSJim Jagielski parameter. 159*b1cdbd2cSJim Jagielski 160*b1cdbd2cSJim Jagielski The lifetime of the buffered subdivision is based on polygon changes. 161*b1cdbd2cSJim Jagielski When changing the polygon, it will be flushed. It is buffered at the 162*b1cdbd2cSJim Jagielski refcounted implementation class, so it will survive copy by value and 163*b1cdbd2cSJim Jagielski combinations in PolyPolygons. 164*b1cdbd2cSJim Jagielski 165*b1cdbd2cSJim Jagielski @return 166*b1cdbd2cSJim Jagielski The default (and buffered) subdivision of this polygon. It may 167*b1cdbd2cSJim Jagielski be this polygon itself when it has no bezier segments. It is guaranteed 168*b1cdbd2cSJim Jagielski to have no more bezier segments 169*b1cdbd2cSJim Jagielski */ 170*b1cdbd2cSJim Jagielski B2DPolygon getDefaultAdaptiveSubdivision() const; 171*b1cdbd2cSJim Jagielski 172*b1cdbd2cSJim Jagielski /** Get the B2DRange (Rectangle dimensions) of this B2DPolygon 173*b1cdbd2cSJim Jagielski 174*b1cdbd2cSJim Jagielski A polygon may have up to three ranges: 175*b1cdbd2cSJim Jagielski 176*b1cdbd2cSJim Jagielski (a) the range of the polygon points 177*b1cdbd2cSJim Jagielski (b) the range of the polygon points and control points 178*b1cdbd2cSJim Jagielski (c) the outer range of the subdivided bezier curve 179*b1cdbd2cSJim Jagielski 180*b1cdbd2cSJim Jagielski Ranges (a) and (c) are produced by tools::getRange(); resp. this 181*b1cdbd2cSJim Jagielski getB2DRange(). tools::getRangeWithControlPoints handles case (b). 182*b1cdbd2cSJim Jagielski 183*b1cdbd2cSJim Jagielski To get range (c) a simple solution would be to subdivide the polygon 184*b1cdbd2cSJim Jagielski and use getRange() on it. Since subdivision is expensive and decreases 185*b1cdbd2cSJim Jagielski the polygon quality, i added this new method. It will use a 186*b1cdbd2cSJim Jagielski methodology suggested by HDU. First, it gets the range (a). 187*b1cdbd2cSJim Jagielski Then it iterates over the bezier segments and for each it 188*b1cdbd2cSJim Jagielski first tests if the outer range of the bezier segment is already 189*b1cdbd2cSJim Jagielski contained in the result range. 190*b1cdbd2cSJim Jagielski 191*b1cdbd2cSJim Jagielski The subdivision itself uses getAllExtremumPositions() to only 192*b1cdbd2cSJim Jagielski calculate extremum points and to expand the result accordingly. 193*b1cdbd2cSJim Jagielski Thus it calculates maximal four extremum points on the bezier 194*b1cdbd2cSJim Jagielski segment, no split is used at all. 195*b1cdbd2cSJim Jagielski 196*b1cdbd2cSJim Jagielski @return 197*b1cdbd2cSJim Jagielski The outer range of the bezier curve/polygon 198*b1cdbd2cSJim Jagielski */ 199*b1cdbd2cSJim Jagielski B2DRange getB2DRange() const; 200*b1cdbd2cSJim Jagielski 201*b1cdbd2cSJim Jagielski /** insert other 2D polygons 202*b1cdbd2cSJim Jagielski 203*b1cdbd2cSJim Jagielski The default (with nIndex2 == 0 && nCount == 0) inserts the whole 204*b1cdbd2cSJim Jagielski rPoly at position nIndex 205*b1cdbd2cSJim Jagielski 206*b1cdbd2cSJim Jagielski @param nIndex 207*b1cdbd2cSJim Jagielski Target index for points to be inserted 208*b1cdbd2cSJim Jagielski 209*b1cdbd2cSJim Jagielski @param rPoly 210*b1cdbd2cSJim Jagielski The source for new points 211*b1cdbd2cSJim Jagielski 212*b1cdbd2cSJim Jagielski @param nIndex2 213*b1cdbd2cSJim Jagielski The index to the first source point into rPoly 214*b1cdbd2cSJim Jagielski 215*b1cdbd2cSJim Jagielski @param nCount 216*b1cdbd2cSJim Jagielski How many points to add from rPoly to this polygon. Null 217*b1cdbd2cSJim Jagielski means to copy all (starting from nIndex2) 218*b1cdbd2cSJim Jagielski */ 219*b1cdbd2cSJim Jagielski void insert(sal_uInt32 nIndex, const B2DPolygon& rPoly, sal_uInt32 nIndex2 = 0, sal_uInt32 nCount = 0); 220*b1cdbd2cSJim Jagielski 221*b1cdbd2cSJim Jagielski /** append other 2D polygons 222*b1cdbd2cSJim Jagielski 223*b1cdbd2cSJim Jagielski The default (nIndex ==0 && nCount == 0) will append 224*b1cdbd2cSJim Jagielski the whole rPoly 225*b1cdbd2cSJim Jagielski 226*b1cdbd2cSJim Jagielski @param rPoly 227*b1cdbd2cSJim Jagielski The source polygon 228*b1cdbd2cSJim Jagielski 229*b1cdbd2cSJim Jagielski @param nIndex 230*b1cdbd2cSJim Jagielski The index to the first point of rPoly to append 231*b1cdbd2cSJim Jagielski 232*b1cdbd2cSJim Jagielski @param nCount 233*b1cdbd2cSJim Jagielski The number of points to append from rPoly, starting 234*b1cdbd2cSJim Jagielski from nIndex. If zero, as much as possibel is appended 235*b1cdbd2cSJim Jagielski */ 236*b1cdbd2cSJim Jagielski void append(const B2DPolygon& rPoly, sal_uInt32 nIndex = 0, sal_uInt32 nCount = 0); 237*b1cdbd2cSJim Jagielski 238*b1cdbd2cSJim Jagielski /// remove points 239*b1cdbd2cSJim Jagielski void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); 240*b1cdbd2cSJim Jagielski 241*b1cdbd2cSJim Jagielski /// clear all points 242*b1cdbd2cSJim Jagielski void clear(); 243*b1cdbd2cSJim Jagielski 244*b1cdbd2cSJim Jagielski /// closed state interface 245*b1cdbd2cSJim Jagielski bool isClosed() const; 246*b1cdbd2cSJim Jagielski void setClosed(bool bNew); 247*b1cdbd2cSJim Jagielski 248*b1cdbd2cSJim Jagielski /// flip polygon direction 249*b1cdbd2cSJim Jagielski void flip(); 250*b1cdbd2cSJim Jagielski 251*b1cdbd2cSJim Jagielski /// test if Polygon has double points 252*b1cdbd2cSJim Jagielski bool hasDoublePoints() const; 253*b1cdbd2cSJim Jagielski 254*b1cdbd2cSJim Jagielski /// remove double points, at the begin/end and follow-ups, too 255*b1cdbd2cSJim Jagielski void removeDoublePoints(); 256*b1cdbd2cSJim Jagielski 257*b1cdbd2cSJim Jagielski /// apply transformation given in matrix form 258*b1cdbd2cSJim Jagielski void transform(const basegfx::B2DHomMatrix& rMatrix); 259*b1cdbd2cSJim Jagielski 260*b1cdbd2cSJim Jagielski // point iterators (same iterator validity conditions as for vector) 261*b1cdbd2cSJim Jagielski const B2DPoint* begin() const; 262*b1cdbd2cSJim Jagielski const B2DPoint* end() const; 263*b1cdbd2cSJim Jagielski B2DPoint* begin(); 264*b1cdbd2cSJim Jagielski B2DPoint* end(); 265*b1cdbd2cSJim Jagielski }; 266*b1cdbd2cSJim Jagielski 267*b1cdbd2cSJim Jagielski // typedef for a vector of B2DPolygons 268*b1cdbd2cSJim Jagielski typedef ::std::vector< B2DPolygon > B2DPolygonVector; 269*b1cdbd2cSJim Jagielski 270*b1cdbd2cSJim Jagielski } // end of namespace basegfx 271*b1cdbd2cSJim Jagielski 272*b1cdbd2cSJim Jagielski ////////////////////////////////////////////////////////////////////////////// 273*b1cdbd2cSJim Jagielski 274*b1cdbd2cSJim Jagielski #endif /* _BGFX_POLYGON_B2DPOLYGON_HXX */ 275