1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 #ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX 23 #define _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX 24 25 #include <basegfx/point/b2dpoint.hxx> 26 #include <basegfx/vector/b2dvector.hxx> 27 #include <basegfx/polygon/b2dpolygon.hxx> 28 #include <basegfx/polygon/b3dpolypolygon.hxx> 29 #include <com/sun/star/drawing/PointSequenceSequence.hpp> 30 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> 31 #include <vector> 32 #include <set> 33 #include <basegfx/basegfxdllapi.h> 34 35 namespace rtl 36 { 37 class OUString; 38 } 39 40 ////////////////////////////////////////////////////////////////////////////// 41 42 namespace basegfx 43 { 44 // predefinitions 45 class B2DPolyPolygon; 46 class B2DRange; 47 48 namespace tools 49 { 50 // B2DPolyPolygon tools 51 52 // Check and evtl. correct orientations of all contained Polygons so that 53 // the orientations of contained polygons will variate to express areas and 54 // holes 55 BASEGFX_DLLPUBLIC B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate); 56 57 // make sure polygon with index 0L is not a hole. This may evtl. change the 58 // sequence of polygons, but allows to use polygon with index 0L to 59 // get the correct normal for the whole polyPolygon 60 BASEGFX_DLLPUBLIC B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate); 61 62 // Subdivide all contained curves. Use distanceBound value if given. 63 BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound = 0.0); 64 65 // Subdivide all contained curves. Use distanceBound value if given. Else, a convenient one 66 // is created. 67 BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound = 0.0); 68 69 // Subdivide all contained curves. Use nCount divisions if given. Else, a convenient one 70 // is created. 71 BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByCount(const B2DPolyPolygon& rCandidate, sal_uInt32 nCount = 0L); 72 73 // isInside test for B2dPoint. On border is not inside as long as not true is given 74 // in bWithBorder flag. It is assumed that the orientations of the given polygon are correct. 75 BASEGFX_DLLPUBLIC bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder = false); 76 77 /** get range of PolyPolygon. Control points are included. 78 79 For detailed description look at getRangeWithControlPoints(const B2DPolygon&). 80 This method just expands by the range of every sub-Polygon. 81 82 @param rCandidate 83 The B2DPolyPolygon eventually containing bezier segments 84 85 @return 86 The outer range including control points 87 */ 88 BASEGFX_DLLPUBLIC B2DRange getRangeWithControlPoints(const B2DPolyPolygon& rCandidate); 89 90 /** Get the range of a polyPolygon 91 92 For detailed description look at getRange(const B2DPolygon&). 93 This method just expands by the range of every sub-Polygon. 94 95 @param rCandidate 96 The B2DPolyPolygon eventually containing bezier segments 97 98 @return 99 The outer range of the polygon 100 */ 101 BASEGFX_DLLPUBLIC B2DRange getRange(const B2DPolyPolygon& rCandidate); 102 103 // get signed area of polygon 104 BASEGFX_DLLPUBLIC double getSignedArea(const B2DPolyPolygon& rCandidate); 105 106 // get area of polygon 107 BASEGFX_DLLPUBLIC double getArea(const B2DPolyPolygon& rCandidate); 108 109 /** Apply given LineDashing to given polyPolygon 110 111 For a description see applyLineDashing in b2dpolygontoos.hxx 112 */ 113 BASEGFX_DLLPUBLIC void applyLineDashing( 114 const B2DPolyPolygon& rCandidate, 115 const ::std::vector<double>& rDotDashArray, 116 B2DPolyPolygon* pLineTarget, 117 B2DPolyPolygon* pGapTarget = 0, 118 double fFullDashDotLen = 0.0); 119 120 // test if point is inside epsilon-range around the given PolyPolygon. Can be used 121 // for HitTesting. The epsilon-range is defined to be the tube around the PolyPolygon 122 // with distance fDistance and rounded edges (start and end point). 123 BASEGFX_DLLPUBLIC bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance); 124 125 /** Helper class to transport PointIndices to a PolyPolygon, 126 with an operator< for convenient sorting in a std::set usage 127 */ 128 class BASEGFX_DLLPUBLIC PointIndex 129 { 130 private: 131 sal_uInt32 mnPolygonIndex; 132 sal_uInt32 mnPointIndex; 133 134 public: PointIndex(sal_uInt32 nPolygonIndex,sal_uInt32 nPointIndex)135 PointIndex(sal_uInt32 nPolygonIndex, sal_uInt32 nPointIndex) 136 : mnPolygonIndex(nPolygonIndex), 137 mnPointIndex(nPointIndex) 138 {} 139 getPolygonIndex() const140 sal_uInt32 getPolygonIndex() const { return mnPolygonIndex; } getPointIndex() const141 sal_uInt32 getPointIndex() const { return mnPointIndex; } 142 bool operator<(const PointIndex& rComp) const; 143 }; 144 145 /** the PointIndexSet itself; it allows to define a 'selection'of 146 points in a PolyPolygon by giving the polygon and point index. 147 Adding points double makes no sense, hence the std::set 148 */ 149 typedef std::set< PointIndex > PointIndexSet; 150 151 /** Read poly-polygon from SVG. 152 153 This function imports a poly-polygon from an SVG-D 154 attribute. Currently, elliptical arc elements are not yet 155 supported (and ignored during parsing). 156 157 @param o_rPolyPoly 158 The output poly-polygon 159 160 @param rSvgDAttribute 161 A valid SVG-D attribute string 162 163 @param bHandleRelativeNextPointCompatible 164 If set to true, the old error that after a relative 'z' command 165 the current point was not reset to the first point of the current 166 polygon is kept; this is needed to read odf files. 167 If false, pure svg is used; this is needed for svg import. 168 169 @param pHelpPointIndexSet 170 If given, all points created in the target PolyPolygon 171 which are only helper points are added here using their 172 point indices; this are currently points created from 173 import of the 'a' and 'A' svg:d statements which create 174 bezier curve info as representation and maybe points 175 which are no 'real' svg:d points, but helper points. It 176 is necessary to identify these e.g. when markers need to 177 be created in the svg import 178 179 @return true, if the string was successfully parsed 180 */ 181 182 BASEGFX_DLLPUBLIC bool importFromSvgD( 183 B2DPolyPolygon& o_rPolyPoly, 184 const ::rtl::OUString& rSvgDAttribute, 185 bool bHandleRelativeNextPointCompatible, 186 PointIndexSet* pHelpPointIndexSet); 187 188 // grow for polyPolygon. Move all geometry in each point in the direction of the normal in that point 189 // with the given amount. Value may be negative. 190 BASEGFX_DLLPUBLIC B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue); 191 192 // This method will correct a pair of polyPolygons where the goal is to keep same point count 193 // to allow direct point association and also to remove self-intersections produced by shrinks. 194 // This method will eventually change both polyPolygons to reach that goal because there are cases 195 // where it is necessary to add new cut points to the original 196 BASEGFX_DLLPUBLIC void correctGrowShrinkPolygonPair(B2DPolyPolygon& rOriginal, B2DPolyPolygon& rGrown); 197 198 // force all sub-polygons to a point count of nSegments 199 BASEGFX_DLLPUBLIC B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments); 200 201 // create polygon state at t from 0.0 to 1.0 between the two polygons. Both polygons must have the same 202 // organisation, e.g. same amount of polygons 203 BASEGFX_DLLPUBLIC B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t); 204 205 // create 3d PolyPolygon from given 2d PolyPolygon. The given fZCoordinate is used to expand the 206 // third coordinate. 207 BASEGFX_DLLPUBLIC B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate = 0.0); 208 209 // create 2d PolyPolygon from given 3d PolyPolygon. All coordinates are transformed using the given 210 // matrix and the resulting x,y is used to form the new polygon. 211 BASEGFX_DLLPUBLIC B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat); 212 213 // for each contained edge in each contained polygon calculate the smallest distance. Return the index to the smallest 214 // edge in rEdgeIndex and the index to the polygon in rPolygonIndex. The relative position on the edge is returned in rCut. 215 // If nothing was found (e.g. empty input plygon), DBL_MAX is returned. 216 BASEGFX_DLLPUBLIC double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut); 217 218 // distort PolyPolygon. rOriginal describes the original range, where the given points describe the distorted 219 // corresponding points. 220 BASEGFX_DLLPUBLIC B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight); 221 222 // rotate PolyPolygon around given point with given angle. 223 BASEGFX_DLLPUBLIC B2DPolyPolygon rotateAroundPoint(const B2DPolyPolygon& rCandidate, const B2DPoint& rCenter, double fAngle); 224 225 // expand all segments (which are not yet) to curve segments. This is done with setting the control 226 // vectors on the 1/3 resp. 2/3 distances on each segment. 227 BASEGFX_DLLPUBLIC B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate); 228 229 // set continuity for the whole curve. If not a curve, nothing will change. Non-curve points are not changed, too. 230 BASEGFX_DLLPUBLIC B2DPolyPolygon setContinuity(const B2DPolyPolygon& rCandidate, B2VectorContinuity eContinuity); 231 232 /** Predicate whether a given poly-polygon is a rectangle. 233 234 @param rPoly 235 PolyPolygon to check 236 237 @return true, if the poly-polygon describes a rectangle 238 (contains exactly one polygon, polygon is closed, and the 239 points are either cw or ccw enumerations of a rectangle's 240 vertices). Note that intermediate points and duplicate 241 points are ignored. 242 */ 243 BASEGFX_DLLPUBLIC bool isRectangle( const B2DPolyPolygon& rPoly ); 244 245 /** Export poly-polygon to SVG. 246 247 This function exports a poly-polygon into an SVG-D 248 statement. Currently, output of relative point sequences 249 is not yet supported (might cause slightly larger output) 250 251 @param rPolyPoly 252 The poly-polygon to export 253 254 @param bUseRelativeCoordinates 255 When true, all coordinate values are exported as relative 256 to the current position. This tends to save some space, 257 since fewer digits needs to be written. 258 259 @param bDetectQuadraticBeziers 260 When true, the export tries to detect cubic bezier 261 segments in the input polygon, which can be represented by 262 quadratic bezier segments. Note that the generated string 263 causes versions prior to OOo2.0 to crash. 264 265 @param bHandleRelativeNextPointCompatible 266 If set to true, the old error that after a relative 'z' command 267 the current point was not reset to the first point of the current 268 polygon is kept; this is needed to read odf files. 269 If false, pure svg is used; this is needed for svg import. 270 271 @return the generated SVG-D statement (the XML d attribute 272 value alone, without any "<path ...>" or "d="...") 273 */ 274 BASEGFX_DLLPUBLIC ::rtl::OUString exportToSvgD( 275 const B2DPolyPolygon& rPolyPoly, 276 bool bUseRelativeCoordinates, 277 bool bDetectQuadraticBeziers, 278 bool bHandleRelativeNextPointCompatible); 279 280 // #i76891# Try to remove existing curve segments if they are simply edges 281 BASEGFX_DLLPUBLIC B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate); 282 283 /** split each edge of a polyPolygon in exactly nSubEdges equidistant edges 284 285 @param rCandidate 286 The source polyPolygon. If too small (no edges), nSubEdges too small (<2) 287 or neither bHandleCurvedEdgesnor bHandleStraightEdges it will just be returned. 288 Else for each edge nSubEdges will be created. Closed state is preserved. 289 290 @param nSubEdges 291 @param bHandleCurvedEdges 292 @param bHandleStraightEdges 293 Please take a look at reSegmentPolygonEdges description, these are the same. 294 */ 295 BASEGFX_DLLPUBLIC B2DPolyPolygon reSegmentPolyPolygonEdges(const B2DPolyPolygon& rCandidate, sal_uInt32 nSubEdges, bool bHandleCurvedEdges, bool bHandleStraightEdges); 296 297 ////////////////////////////////////////////////////////////////////// 298 // comparators with tolerance for 2D PolyPolygons 299 BASEGFX_DLLPUBLIC bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB, const double& rfSmallValue); 300 BASEGFX_DLLPUBLIC bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); 301 302 /** snap some polygon coordinates to discrete coordinates 303 304 This method allows to snap some polygon points to discrete (integer) values 305 which equals e.g. a snap to discrete coordinates. It will snap points of 306 horizontal and vertical edges 307 308 @param rCandidate 309 The source polygon 310 311 @return 312 The modified version of the source polygon 313 */ 314 BASEGFX_DLLPUBLIC B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate); 315 316 /** returns true if the Polygon only contains horizontal or vertical edges 317 so that it could be represented by RegionBands 318 */ 319 BASEGFX_DLLPUBLIC bool containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon& rCandidate); 320 321 /// converters for com::sun::star::drawing::PointSequence 322 BASEGFX_DLLPUBLIC B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon( 323 const com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceSource, 324 bool bCheckClosed = true); 325 BASEGFX_DLLPUBLIC void B2DPolyPolygonToUnoPointSequenceSequence( 326 const B2DPolyPolygon& rPolyPolygon, 327 com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceRetval); 328 329 /// converters for com::sun::star::drawing::PolyPolygonBezierCoords (curved polygons) 330 BASEGFX_DLLPUBLIC B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon( 331 const com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource, 332 bool bCheckClosed = true); 333 BASEGFX_DLLPUBLIC void B2DPolyPolygonToUnoPolyPolygonBezierCoords( 334 const B2DPolyPolygon& rPolyPolygon, 335 com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval); 336 337 } // end of namespace tools 338 } // end of namespace basegfx 339 340 #endif /* _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX */ 341