Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsinternalgeometryengine.h - QgsInternalGeometryEngine 3 : : 4 : : --------------------- 5 : : begin : 13.1.2016 6 : : copyright : (C) 2016 by Matthias Kuhn 7 : : email : matthias@opengis.ch 8 : : *************************************************************************** 9 : : * * 10 : : * This program is free software; you can redistribute it and/or modify * 11 : : * it under the terms of the GNU General Public License as published by * 12 : : * the Free Software Foundation; either version 2 of the License, or * 13 : : * (at your option) any later version. * 14 : : * * 15 : : ***************************************************************************/ 16 : : #ifndef QGSINTERNALGEOMETRYENGINE_H 17 : : #define QGSINTERNALGEOMETRYENGINE_H 18 : : 19 : : #define SIP_NO_FILE 20 : : 21 : : #include <functional> 22 : : 23 : : #include "qgspointxy.h" 24 : : 25 : : class QgsGeometry; 26 : : class QgsAbstractGeometry; 27 : : class QgsLineString; 28 : : class QgsLineSegment2D; 29 : : class QgsFeedback; 30 : : 31 : : /** 32 : : * \ingroup core 33 : : * \brief This class offers geometry processing methods. 34 : : * 35 : : * The methods are available via QgsGeometry::[geometryfunction] 36 : : * and therefore this does not need to be accessed directly. 37 : : * 38 : : * \note not available in Python bindings 39 : : */ 40 : : 41 : 14 : class QgsInternalGeometryEngine 42 : : { 43 : : public: 44 : : 45 : : /** 46 : : * The caller is responsible that the geometry is available and unchanged 47 : : * for the whole lifetime of this object. 48 : : * \param geometry 49 : : */ 50 : : explicit QgsInternalGeometryEngine( const QgsGeometry &geometry ); 51 : : 52 : : /** 53 : : * Returns an error string referring to the last error encountered. 54 : : * 55 : : * \since QGIS 3.16 56 : : */ 57 : : QString lastError() const; 58 : : 59 : : /** 60 : : * Will extrude a line or (segmentized) curve by a given offset and return a polygon 61 : : * representation of it. 62 : : * 63 : : * \param x offset in x direction 64 : : * \param y offset in y direction 65 : : * \returns an extruded polygon 66 : : */ 67 : : QgsGeometry extrude( double x, double y ) const; 68 : : 69 : : /** 70 : : * Calculates the approximate pole of inaccessibility for a surface, which is the 71 : : * most distant internal point from the boundary of the surface. This function 72 : : * uses the 'polylabel' algorithm (Vladimir Agafonkin, 2016), which is an iterative 73 : : * approach guaranteed to find the true pole of inaccessibility within a specified 74 : : * tolerance. More precise tolerances require more iterations and will take longer 75 : : * to calculate. 76 : : * Optionally, the distance to the polygon boundary from the pole can be stored. 77 : : */ 78 : : QgsGeometry poleOfInaccessibility( double precision, double *distanceFromBoundary = nullptr ) const; 79 : : 80 : : /** 81 : : * Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries 82 : : * angles either right angles or flat lines. This is an iterative algorithm which will loop until 83 : : * either the vertices are within a specified tolerance of right angles or a set number of maximum 84 : : * iterations is reached. The angle threshold parameter specifies how close to a right angle or 85 : : * straight line an angle must be before it is attempted to be straightened. 86 : : * \since QGIS 3.0 87 : : */ 88 : : QgsGeometry orthogonalize( double tolerance = 1.0E-8, int maxIterations = 1000, double angleThreshold = 15.0 ) const; 89 : : 90 : : /** 91 : : * Densifies the geometry by adding the specified number of extra nodes within each 92 : : * segment of the geometry. 93 : : * If the geometry has z or m values present then these will be linearly interpolated 94 : : * at the added nodes. 95 : : * Curved geometry types are automatically segmentized by this routine. 96 : : * \since QGIS 3.0 97 : : */ 98 : : QgsGeometry densifyByCount( int extraNodesPerSegment ) const; 99 : : 100 : : /** 101 : : * Densifies the geometry by adding regularly placed extra nodes inside each segment 102 : : * so that the maximum distance between any two nodes does not exceed the 103 : : * specified \a distance. 104 : : * E.g. specifying a distance 3 would cause the segment [0 0] -> [10 0] 105 : : * to be converted to [0 0] -> [2.5 0] -> [5 0] -> [7.5 0] -> [10 0], since 106 : : * 3 extra nodes are required on the segment and spacing these at 2.5 increments 107 : : * allows them to be evenly spaced over the segment. 108 : : * If the geometry has z or m values present then these will be linearly interpolated 109 : : * at the added nodes. 110 : : * Curved geometry types are automatically segmentized by this routine. 111 : : * \since QGIS 3.0 112 : : */ 113 : : QgsGeometry densifyByDistance( double distance ) const; 114 : : 115 : : /** 116 : : * Calculates a variable width buffer for a (multi)curve geometry. 117 : : * 118 : : * The width of the buffer at each node in the input linestrings is calculated by 119 : : * calling the specified \a widthFunction, which must return an array of the buffer widths 120 : : * for every node in the line. 121 : : * 122 : : * The \a segments argument specifies the number of segments to approximate quarter-circle 123 : : * curves in the buffer. 124 : : * 125 : : * Non (multi)curve input geometries will return a null output geometry. 126 : : * 127 : : * \since QGIS 3.2 128 : : */ 129 : : QgsGeometry variableWidthBuffer( int segments, const std::function< std::unique_ptr< double[] >( const QgsLineString *line ) > &widthFunction ) const; 130 : : 131 : : /** 132 : : * Calculates a tapered width buffer for a (multi)curve geometry. 133 : : * 134 : : * The buffer begins at a width of \a startWidth at the start of each curve, and 135 : : * ends at a width of \a endWidth. Note that unlike QgsGeometry::buffer() methods, \a startWidth 136 : : * and \a endWidth are the diameter of the buffer at these points, not the radius. 137 : : * 138 : : * The \a segments argument specifies the number of segments to approximate quarter-circle 139 : : * curves in the buffer. 140 : : * 141 : : * Non (multi)curve input geometries will return a null output geometry. 142 : : * 143 : : * \since QGIS 3.2 144 : : */ 145 : : QgsGeometry taperedBuffer( double startWidth, double endWidth, int segments ) const; 146 : : 147 : : /** 148 : : * Calculates a variable width buffer using the m-values from a (multi)line geometry. 149 : : * 150 : : * The \a segments argument specifies the number of segments to approximate quarter-circle 151 : : * curves in the buffer. 152 : : * 153 : : * Non (multi)line input geometries will return a null output geometry. 154 : : * 155 : : * \since QGIS 3.2 156 : : */ 157 : : QgsGeometry variableWidthBufferByM( int segments ) const; 158 : : 159 : : /** 160 : : * Returns a list of \a count random points generated inside a \a polygon geometry 161 : : * (if \a acceptPoint is specified, and restrictive, the number of points returned may 162 : : * be less than \a count). 163 : : * 164 : : * Optionally, a specific random \a seed can be used when generating points. If \a seed 165 : : * is 0, then a completely random sequence of points will be generated. 166 : : * 167 : : * The \a acceptPoint function is used to filter result candidates. If the function returns 168 : : * FALSE, then the point will not be accepted and another candidate generated. 169 : : * 170 : : * The optional \a feedback argument can be used to provide cancellation support during 171 : : * the point generation. 172 : : * 173 : : * When \a acceptPoint is specified, \a maxTriesPerPoint 174 : : * defines how many attempts to perform before giving up generating 175 : : * a point. 176 : : * 177 : : * \since QGIS 3.10 178 : : */ 179 : : static QVector< QgsPointXY > randomPointsInPolygon( const QgsGeometry &polygon, int count, 180 : : const std::function< bool( const QgsPointXY & ) > &acceptPoint, unsigned long seed = 0, QgsFeedback *feedback = nullptr, int maxTriesPerPoint = 0 ); 181 : : 182 : : /** 183 : : * Attempts to convert a non-curved geometry into a curved geometry type (e.g. 184 : : * LineString to CompoundCurve, Polygon to CurvePolygon). 185 : : * 186 : : * The \a distanceTolerance specifies the maximum deviation allowed between the original location 187 : : * of vertices and where they would fall on the candidate curved geometry. 188 : : * 189 : : * This method only consider a segments as suitable for replacing with an arc if the points are all 190 : : * regularly spaced on the candidate arc. The \a pointSpacingAngleTolerance parameter specifies the maximum 191 : : * angular deviation (in radians) allowed when testing for regular point spacing. 192 : : * 193 : : * \note The API is considered EXPERIMENTAL and can be changed without a notice 194 : : * 195 : : * \since QGIS 3.14 196 : : */ 197 : : QgsGeometry convertToCurves( double distanceTolerance, double angleTolerance ) const; 198 : : 199 : : /** 200 : : * Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) 201 : : * rotated rectangle which fully encompasses the geometry. The area, angle (clockwise in degrees from North), 202 : : * width and height of the rotated bounding box will also be returned. 203 : : * 204 : : * If an error was encountered while creating the result, more information can be retrieved 205 : : * by calling lastError(). 206 : : * 207 : : * \since QGIS 3.16 208 : : */ 209 : : QgsGeometry orientedMinimumBoundingBox( double &area SIP_OUT, double &angle SIP_OUT, double &width SIP_OUT, double &height SIP_OUT ) const; 210 : : 211 : : private: 212 : : const QgsAbstractGeometry *mGeometry = nullptr; 213 : : 214 : : mutable QString mLastError; 215 : : }; 216 : : 217 : : /** 218 : : * \brief A 2D ray which extends from an origin point to an infinite distance in a given direction. 219 : : * \ingroup core 220 : : * \note not available in Python bindings 221 : : * \since QGIS 3.2 222 : : */ 223 : : class CORE_EXPORT QgsRay2D 224 : : { 225 : : public: 226 : : 227 : : /** 228 : : * Constructor for a ray starting at the given \a origin and extending an infinite distance 229 : : * in the specified \a direction. 230 : : */ 231 : : QgsRay2D( const QgsPointXY &origin, QgsVector direction ) 232 : : : origin( origin ) 233 : : , direction( direction ) 234 : : {} 235 : : 236 : : /** 237 : : * Finds the closest intersection point of the ray and a line \a segment. 238 : : * 239 : : * If found, the intersection point will be stored in \a intersectPoint. 240 : : * 241 : : * Returns TRUE if the ray intersects the line segment. 242 : : */ 243 : : bool intersects( const QgsLineSegment2D &segment, QgsPointXY &intersectPoint ) const; 244 : : 245 : : private: 246 : : 247 : : QgsPointXY origin; 248 : : QgsVector direction; 249 : : }; 250 : : 251 : : ///@cond PRIVATE 252 : : 253 : : // adapted for QGIS geometry classes from original work at https://github.com/trylock/visibility by trylock 254 : : 255 : : /** 256 : : * \brief Compares two line segments based on their distance from a given point. 257 : : * 258 : : * Assumes: (1) the line segments are intersected by some ray from the origin 259 : : * (2) the line segments do not intersect except at their endpoints 260 : : * (3) no line segment is collinear with the origin 261 : : * \ingroup core 262 : : * \since QGIS 3.2 263 : : */ 264 : : class CORE_EXPORT QgsLineSegmentDistanceComparer 265 : : { 266 : : public: 267 : : 268 : : /** 269 : : * Constructor for QgsLineSegmentDistanceComparer, comparing points 270 : : * to the specified \a origin point. 271 : : */ 272 : : explicit QgsLineSegmentDistanceComparer( const QgsPointXY &origin ) 273 : : : mOrigin( origin ) 274 : : {} 275 : : 276 : : /** 277 : : * Checks whether the line segment \a ab is closer to the origin than the 278 : : * line segment \a cd. 279 : : * \param ab line segment: left hand side of the comparison operator 280 : : * \param cd line segment: right hand side of the comparison operator 281 : : * \returns TRUE if ab < cd (ab is closer than cd) to origin 282 : : */ 283 : : bool operator()( QgsLineSegment2D ab, QgsLineSegment2D cd ) const; 284 : : 285 : : private: 286 : : 287 : : QgsPointXY mOrigin; 288 : : 289 : : }; 290 : : 291 : : 292 : : // adapted for QGIS geometry classes from original work at https://github.com/trylock/visibility by trylock 293 : : 294 : : /** 295 : : * \brief Compares angles from an origin to points clockwise, starting at the positive y-axis. 296 : : * 297 : : * \ingroup core 298 : : * \since QGIS 3.2 299 : : */ 300 : : class CORE_EXPORT QgsClockwiseAngleComparer 301 : : { 302 : : public: 303 : : explicit QgsClockwiseAngleComparer( const QgsPointXY &origin ) 304 : : : mVertex( origin ) 305 : : {} 306 : : 307 : : bool operator()( const QgsPointXY &a, const QgsPointXY &b ) const; 308 : : 309 : : private: 310 : : 311 : : QgsPointXY mVertex; 312 : : 313 : : }; 314 : : 315 : : ///@endcond PRIVATE 316 : : 317 : : #endif // QGSINTERNALGEOMETRYENGINE_H