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