34   : mGeometry( geometry.constGet() )
    47   QVector<QgsLineString *> linesToProcess;
    52     for ( 
int i = 0; i < multiCurve->
partCount(); ++i )
    54       linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
    61     linesToProcess << static_cast<QgsLineString *>( curve->segmentize() );
    64   std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ? 
new QgsMultiPolygon() : nullptr );
    67   if ( !linesToProcess.empty() )
    69     std::unique_ptr< QgsLineString > secondline;
    70     for ( 
QgsLineString *line : qgis::as_const( linesToProcess ) )
    72       QTransform transform = QTransform::fromTranslate( x, y );
    74       secondline.reset( line->reversed() );
    75       secondline->transform( transform );
    77       line->append( secondline.get() );
    78       line->addVertex( line->pointN( 0 ) );
    81       polygon->setExteriorRing( line );
    84         multipolygon->addGeometry( polygon );
   106     Cell( 
double x, 
double y, 
double h, 
const QgsPolygon *polygon )
   111       , max( d + h * M_SQRT2 )
   126 struct GreaterThanByMax
   128   bool operator()( 
const Cell *lhs, 
const Cell *rhs )
   130     return rhs->max > lhs->max;
   134 Cell *getCentroidCell( 
const QgsPolygon *polygon )
   142   for ( 
int i = 0, j = len - 1; i < len; j = i++ )
   144     double aX = exterior->
xAt( i );
   145     double aY = exterior->
yAt( i );
   146     double bX = exterior->
xAt( j );
   147     double bY = exterior->
yAt( j );
   148     double f = aX * bY - bX * aY;
   149     x += ( aX + bX ) * f;
   150     y += ( aY + bY ) * f;
   154     return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
   156     return new Cell( x / area, y / area, 0.0, polygon );
   159 QgsPoint surfacePoleOfInaccessibility( 
const QgsSurface *surface, 
double precision, 
double &distanceFromBoundary )
   161   std::unique_ptr< QgsPolygon > segmentizedPoly;
   165     segmentizedPoly.reset( static_cast< QgsPolygon *>( surface->
segmentize() ) );
   166     polygon = segmentizedPoly.get();
   173   double cellSize = std::min( bounds.
width(), bounds.
height() );
   178   double h = cellSize / 2.0;
   179   std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
   186       cellQueue.push( 
new Cell( x + h, y + h, h, polygon ) );
   191   std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
   194   std::unique_ptr< Cell > bboxCell( 
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
   197   if ( bboxCell->d > bestCell->d )
   199     bestCell = std::move( bboxCell );
   202   while ( !cellQueue.empty() )
   205     std::unique_ptr< Cell > cell( cellQueue.top() );
   207     Cell *currentCell = cell.get();
   210     if ( currentCell->d > bestCell->d )
   212       bestCell = std::move( cell );
   216     if ( currentCell->max - bestCell->d <= precision )
   220     h = currentCell->h / 2.0;
   221     cellQueue.push( 
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
   222     cellQueue.push( 
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
   223     cellQueue.push( 
new Cell( currentCell->x - h, currentCell->y + h, h, polygon ) );
   224     cellQueue.push( 
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
   227   distanceFromBoundary = bestCell->d;
   229   return QgsPoint( bestCell->x, bestCell->y );
   236   if ( distanceFromBoundary )
   237     *distanceFromBoundary = std::numeric_limits<double>::max();
   239   if ( !mGeometry || mGeometry->isEmpty() )
   242   if ( precision <= 0 )
   245   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
   247     int numGeom = gc->numGeometries();
   251     for ( 
int i = 0; i < numGeom; ++i )
   258       double dist = std::numeric_limits<double>::max();
   259       QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
   260       if ( dist > maxDist )
   270     if ( distanceFromBoundary )
   271       *distanceFromBoundary = maxDist;
   280     double dist = std::numeric_limits<double>::max();
   281     QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
   282     if ( distanceFromBoundary )
   283       *distanceFromBoundary = dist;
   294   return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
   320   for ( 
int i = 0; i < numPoints; ++i )
   322     if ( !isClosed && i == numPoints - 1 )
   324     else if ( !isClosed && i == 0 )
   333         a = ring->
pointN( numPoints - 1 );
   336       if ( i == numPoints - 1 )
   339         c = ring->
pointN( i + 1 );
   345       sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
   355                       double lowerThreshold, 
double upperThreshold )
   364   double scale = 2.0 * std::min( p.
length(), q.
length() );
   368   double dotProduct = p * q;
   377   if ( dotProduct < -M_SQRT1_2 )
   382   return new_v.
normalized() * ( 0.1 * dotProduct * scale );
   387   double minScore = std::numeric_limits<double>::max();
   392   std::unique_ptr< QgsLineString > best( ring->
clone() );
   394   QVector< QgsVector >  motions;
   395   motions.reserve( numPoints );
   397   for ( 
int it = 0; it < iterations; ++it )
   405     for ( 
int i = 0; i < numPoints; ++i )
   407       if ( isClosed && i == numPoints - 1 )
   408         motions << motions.at( 0 ); 
   409       else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
   419           a = ring->
pointN( numPoints - 1 );
   422         if ( i == numPoints - 1 )
   425           c = ring->
pointN( i + 1 );
   427         motions << 
calcMotion( a, b, c, lowerThreshold, upperThreshold );
   434     for ( 
int i = 0; i < numPoints; ++i )
   436       ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
   437       ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
   440     double newScore = 
squareness( ring, lowerThreshold, upperThreshold );
   441     if ( newScore < minScore )
   443       best.reset( ring->
clone() );
   447     if ( minScore < tolerance )
   453   return best.release();
   459   std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
   463     geom = segmentizedCopy.get();
   469                             maxIterations, tolerance, lowerThreshold, upperThreshold );
   478                              maxIterations, tolerance, lowerThreshold, upperThreshold ) );
   482                                maxIterations, tolerance, lowerThreshold, upperThreshold ) );
   497   double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
   498   double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
   500   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
   502     int numGeom = gc->numGeometries();
   503     QVector< QgsAbstractGeometry * > geometryList;
   504     geometryList.reserve( numGeom );
   505     for ( 
int i = 0; i < numGeom; ++i )
   507       geometryList << 
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
   526   QVector< double > outX;
   527   QVector< double > outY;
   528   QVector< double > outZ;
   529   QVector< double > outM;
   530   double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
   533   outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
   534   outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
   535   bool withZ = ring->
is3D();
   537     outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
   540     outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
   553   int extraNodesThisSegment = extraNodesPerSegment;
   554   for ( 
int i = 0; i < nPoints - 1; ++i )
   557     x2 = ring->
xAt( i + 1 );
   559     y2 = ring->
yAt( i + 1 );
   563       z2 = ring->
zAt( i + 1 );
   568       m2 = ring->
mAt( i + 1 );
   578     if ( extraNodesPerSegment < 0 )
   581       extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
   582       if ( extraNodesThisSegment >= 1 )
   583         multiplier = 1.0 / ( extraNodesThisSegment + 1 );
   586     for ( 
int j = 0; j < extraNodesThisSegment; ++j )
   588       double delta = multiplier * ( j + 1 );
   589       xOut = x1 + delta * ( x2 - x1 );
   590       yOut = y1 + delta * ( y2 - y1 );
   592         zOut = z1 + delta * ( z2 - z1 );
   594         mOut = m1 + delta * ( m2 - m1 );
   604   outX << ring->
xAt( nPoints - 1 );
   605   outY << ring->
yAt( nPoints - 1 );
   607     outZ << ring->
zAt( nPoints - 1 );
   609     outM << ring->
mAt( nPoints - 1 );
   617   std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
   621     geom = segmentizedCopy.get();
   626     return doDensify( static_cast< const QgsLineString * >( geom ), extraNodesPerSegment, distance );
   635                                         extraNodesPerSegment, distance ) );
   639                                           extraNodesPerSegment, distance ) );
   658   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
   660     int numGeom = gc->numGeometries();
   661     QVector< QgsAbstractGeometry * > geometryList;
   662     geometryList.reserve( numGeom );
   663     for ( 
int i = 0; i < numGeom; ++i )
   665       geometryList << 
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
   693   if ( 
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
   695     int numGeom = gc->numGeometries();
   696     QVector< QgsAbstractGeometry * > geometryList;
   697     geometryList.reserve( numGeom );
   698     for ( 
int i = 0; i < numGeom; ++i )
   725               "line_segment_dist_comparer",
   726               "AB must not be collinear with the origin." );
   728               "line_segment_dist_comparer",
   729               "CD must not be collinear with the origin." );
   743     if ( ab.
end() == cd.
end() || oad != oab )
   753     if ( cdb == 0 && cda == 0 )
   755       return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
   757     else if ( cda == cdb || cda == 0 || cdb == 0 )
   760       return cdo == cda || cdo == cdb;
   776   const bool aIsLeft = a.
x() < mVertex.x();
   777   const bool bIsLeft = b.
x() < mVertex.x();
   778   if ( aIsLeft != bIsLeft )
   783     if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
   785       return b.
y() < a.
y();
   789       return a.
y() < b.
y();
   828       const double distA = ao * direction;
   829       const double distB = ( origin - segment.
end() ) * direction;
   831       if ( distA > 0 && distB > 0 )
   837         if ( ( distA > 0 ) != ( distB > 0 ) )
   838           intersectPoint = origin;
   839         else if ( distA > distB ) 
   840           intersectPoint = segment.
start(); 
   842           intersectPoint = segment.
end();
   850     if ( u < 0.0 || 1.0 < u )
   857       intersectPoint = origin + direction * t;
   866   if ( radius1 > radius2 )
   873   QVector<QgsPointXY> points;
   894   std::vector< std::unique_ptr<QgsLineString > > linesToProcess;
   899     for ( 
int i = 0; i < multiCurve->
partCount(); ++i )
   901       if ( static_cast< const QgsCurve * >( multiCurve->
geometryN( i ) )->nCoordinates() == 0 )
   904       linesToProcess.emplace_back( static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() ) );
   912       linesToProcess.emplace_back( static_cast<QgsLineString *>( curve->
segmentize() ) );
   915   if ( linesToProcess.empty() )
   918     g.mLastError = QStringLiteral( 
"Input geometry was not a curve type geometry" );
   922   QVector<QgsGeometry> bufferedLines;
   924   for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
   926     QVector<QgsGeometry> parts;
   928     double prevRadius = 0;
   931     std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
   936       double thisRadius = widths[ i ] / 2.0;
   937       if ( thisRadius > 0 )
   942         thisCircle = 
QgsGeometry( circ.toPolygon( segments * 4 ) );
   952         if ( prevRadius > 0 || thisRadius > 0 )
   954           QVector< QgsPointXY > points = 
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
   955           if ( !points.empty() )
   960             int beforeVertex = 0;
   963             double sqrDistPrev = 0;
   964             for ( 
int j = 0; j < points.count(); ++j )
   968               points[j] = sqrDistPrev < sqrDist ? pA : pB;
   971             points.append( points.at( 0 ) );
   973             std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >();
   975             if ( poly->area() > 0 )
   980       prevPoint = thisPoint;
   981       prevRadius = thisRadius;
   982       prevCircle = thisCircle;
   993   start = std::fabs( start );
   994   end = std::fabs( end );
  1000     std::unique_ptr< double [] > widths( 
new double[ line->nCoordinates() ] );
  1002     widths[line->nCoordinates() - 1] = end;
  1004     double lineLength = line->length();
  1005     double currentLength = 0;
  1006     QgsPoint prevPoint = line->pointN( 0 );
  1007     for ( 
int i = 1; i < line->nCoordinates() - 1; ++i )
  1009       QgsPoint point = line->pointN( i );
  1010       double segmentLength = point.
distance( prevPoint );
  1011       currentLength += segmentLength;
  1012       double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
  1013       double delta = lengthFraction * ( end - start );
  1014       widths[i] = start + delta;
  1027     std::unique_ptr< double [] > widths( 
new double[ line->nCoordinates() ] );
  1028     for ( 
int i = 0; i < line->nCoordinates(); ++i )
  1030       widths[ i ] = line->mAt( i );
 bool isMeasure() const
Returns true if the geometry contains m values. 
 
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a tapered width buffer for a (multi)curve geometry. 
 
QgsAbstractGeometry * orthogonalizeGeom(const QgsAbstractGeometry *geom, int maxIterations, double tolerance, double lowerThreshold, double upperThreshold)
 
QgsLineString * doDensify(const QgsLineString *ring, int extraNodesPerSegment=-1, double distance=1)
 
QgsVector calcMotion(const QgsPoint &a, const QgsPoint &b, const QgsPoint &c, double lowerThreshold, double upperThreshold)
 
A rectangle specified with double values. 
 
QgsInternalGeometryEngine(const QgsGeometry &geometry)
The caller is responsible that the geometry is available and unchanged for the whole lifetime of this...
 
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer using the m-values from a (multi)line geometry. 
 
double zAt(int index) const
Returns the z-coordinate of the specified node in the line string. 
 
OperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry. 
 
QgsGeometry variableWidthBuffer(int segments, const std::function< std::unique_ptr< double[] >(const QgsLineString *line) > &widthFunction) const
Calculates a variable width buffer for a (multi)curve geometry. 
 
double normalizedDotProduct(const QgsPoint &a, const QgsPoint &b, const QgsPoint &c)
 
QVector< QgsPointXY > generateSegmentCurve(const QgsPoint ¢er1, const double radius1, const QgsPoint ¢er2, const double radius2)
 
QgsGeometry poleOfInaccessibility(double precision, double *distanceFromBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
 
double distance(double x, double y) const
Returns the distance between this point and a specified x, y coordinate. 
 
A class to represent a 2D point. 
 
double endY() const
Returns the segment's end y-coordinate. 
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference) 
 
const QgsCurve * interiorRing(int i) const
 
bool intersects(const QgsLineSegment2D &segment, QgsPointXY &intersectPoint) const
Finds the closest intersection point of the ray and a line segment. 
 
A geometry is the spatial representation of a feature. 
 
double crossProduct(QgsVector v) const
Returns the 2D cross product of this vector and another vector v. 
 
void setYAt(int index, double y)
Sets the y-coordinate of the specified node in the line string. 
 
double squareness(QgsLineString *ring, double lowerThreshold, double upperThreshold)
 
double pointDistanceToBoundary(double x, double y) const
Returns the distance from a point to the boundary of the polygon (either the exterior ring or any clo...
 
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy. 
 
static int circleCircleOuterTangents(const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
 
void setXAt(int index, double x)
Sets the x-coordinate of the specified node in the line string. 
 
void reverse()
Reverses the line segment, so that the start and end points are flipped. 
 
int numPoints() const override
Returns the number of points in the curve. 
 
QgsPointXY closestVertex(const QgsPointXY &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
 
QgsPointXY end() const
Returns the segment's end point. 
 
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership) 
 
int numInteriorRings() const
 
double startX() const
Returns the segment's start x-coordinate. 
 
double width() const
Returns the width of the rectangle. 
 
double mAt(int index) const
Returns the m value of the specified node in the line string. 
 
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer. 
 
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string. 
 
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
 
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
 
Multi curve geometry collection. 
 
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry. 
 
int pointLeftOfLine(const QgsPointXY &point) const
Tests if a point is to the left of the line segment. 
 
QgsPoint * clone() const override
Clones the geometry by performing a deep copy. 
 
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
 
Abstract base class for curved geometry type. 
 
Abstract base class for all geometries. 
 
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry. 
 
Point geometry type, with support for z-dimension and m-values. 
 
double length() const
Returns the length of the vector. 
 
QgsAbstractGeometry * densifyGeometry(const QgsAbstractGeometry *geom, int extraNodesPerSegment=1, double distance=1)
 
Represents a single 2D line segment, consisting of a 2D start and end vertex only. 
 
QgsLineString * clone() const override
Clones the geometry by performing a deep copy. 
 
A class to represent a vector. 
 
virtual bool isClosed() const
Returns true if the curve is closed. 
 
double yMinimum() const
Returns the y minimum value (bottom side of rectangle). 
 
double xMaximum() const
Returns the x maximum value (right side of rectangle). 
 
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves. 
 
bool dotProductWithinAngleTolerance(double dotProduct, double lowerThreshold, double upperThreshold)
 
int partCount() const override
Returns count of parts contained in the geometry. 
 
double endX() const
Returns the segment's end x-coordinate. 
 
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon. 
 
Multi polygon geometry collection. 
 
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy. 
 
static bool isCurvedType(Type type)
Returns true if the WKB type is a curved type or can contain curved geometries. 
 
Line string geometry type, with support for z-dimension and m-values. 
 
static int leftOfLine(double x, double y, double x1, double y1, double x2, double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> ( x2, y2). 
 
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection. 
 
QgsPoint pointN(int i) const
Returns the specified point from inside the line string. 
 
double xMinimum() const
Returns the x minimum value (left side of rectangle). 
 
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string. 
 
double yMaximum() const
Returns the y maximum value (top side of rectangle). 
 
QgsGeometry orthogonalize(double tolerance=1.0E-8, int maxIterations=1000, double angleThreshold=15.0) const
Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries angl...
 
const QgsCurve * exteriorRing() const
 
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
 
double startY() const
Returns the segment's start y-coordinate. 
 
int nCoordinates() const override
Returns the number of nodes contained in the geometry. 
 
double lengthSquared() const
Returns the length of the vector. 
 
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry. 
 
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves. 
 
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries)
Compute the unary union on a list of geometries. 
 
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects. 
 
bool is3D() const
Returns true if the geometry is 3D and contains a z-value. 
 
QgsGeometry extrude(double x, double y) const
Will extrude a line or (segmentized) curve by a given offset and return a polygon representation of i...
 
QgsPointXY start() const
Returns the segment's start point. 
 
QgsVector normalized() const
Returns the vector's normalized (or "unit") vector (ie same angle but length of 1.0). 
 
double height() const
Returns the height of the rectangle. 
 
QgsLineString * doOrthogonalize(QgsLineString *ring, int iterations, double tolerance, double lowerThreshold, double upperThreshold)