34 : mGeometry( geometry.constGet() )
47 QVector<QgsLineString *> linesToProcess;
52 linesToProcess.reserve( multiCurve->
partCount() );
53 for (
int i = 0; i < multiCurve->
partCount(); ++i )
55 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
62 linesToProcess << static_cast<QgsLineString *>( curve->segmentize() );
65 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() : nullptr );
68 if ( !linesToProcess.empty() )
70 std::unique_ptr< QgsLineString > secondline;
71 for (
QgsLineString *line : qgis::as_const( linesToProcess ) )
73 QTransform transform = QTransform::fromTranslate( x, y );
75 secondline.reset( line->reversed() );
76 secondline->transform( transform );
78 line->append( secondline.get() );
79 line->addVertex( line->pointN( 0 ) );
82 polygon->setExteriorRing( line );
85 multipolygon->addGeometry( polygon );
107 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
112 , max( d + h * M_SQRT2 )
127 struct GreaterThanByMax
129 bool operator()(
const Cell *lhs,
const Cell *rhs )
131 return rhs->max > lhs->max;
135 Cell *getCentroidCell(
const QgsPolygon *polygon )
143 for (
int i = 0, j = len - 1; i < len; j = i++ )
145 double aX = exterior->
xAt( i );
146 double aY = exterior->
yAt( i );
147 double bX = exterior->
xAt( j );
148 double bY = exterior->
yAt( j );
149 double f = aX * bY - bX * aY;
150 x += ( aX + bX ) * f;
151 y += ( aY + bY ) * f;
155 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
157 return new Cell( x / area, y / area, 0.0, polygon );
162 std::unique_ptr< QgsPolygon > segmentizedPoly;
166 segmentizedPoly.reset( static_cast< QgsPolygon *>( surface->
segmentize() ) );
167 polygon = segmentizedPoly.get();
174 double cellSize = std::min( bounds.
width(), bounds.
height() );
179 double h = cellSize / 2.0;
180 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
187 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
192 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
195 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
198 if ( bboxCell->d > bestCell->d )
200 bestCell = std::move( bboxCell );
203 while ( !cellQueue.empty() )
206 std::unique_ptr< Cell > cell( cellQueue.top() );
208 Cell *currentCell = cell.get();
211 if ( currentCell->d > bestCell->d )
213 bestCell = std::move( cell );
217 if ( currentCell->max - bestCell->d <=
precision )
221 h = currentCell->h / 2.0;
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 ) );
225 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
228 distanceFromBoundary = bestCell->d;
230 return QgsPoint( bestCell->x, bestCell->y );
237 if ( distanceFromBoundary )
238 *distanceFromBoundary = std::numeric_limits<double>::max();
240 if ( !mGeometry || mGeometry->isEmpty() )
243 if ( precision <= 0 )
246 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
248 int numGeom = gc->numGeometries();
252 for (
int i = 0; i < numGeom; ++i )
259 double dist = std::numeric_limits<double>::max();
260 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
261 if ( dist > maxDist )
271 if ( distanceFromBoundary )
272 *distanceFromBoundary = maxDist;
281 double dist = std::numeric_limits<double>::max();
282 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
283 if ( distanceFromBoundary )
284 *distanceFromBoundary = dist;
295 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
321 for (
int i = 0; i < numPoints; ++i )
323 if ( !isClosed && i == numPoints - 1 )
325 else if ( !isClosed && i == 0 )
334 a = ring->
pointN( numPoints - 1 );
337 if ( i == numPoints - 1 )
340 c = ring->
pointN( i + 1 );
346 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
356 double lowerThreshold,
double upperThreshold )
365 double scale = 2.0 * std::min( p.
length(), q.
length() );
369 double dotProduct = p * q;
378 if ( dotProduct < -M_SQRT1_2 )
383 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
388 double minScore = std::numeric_limits<double>::max();
393 std::unique_ptr< QgsLineString > best( ring->
clone() );
395 QVector< QgsVector > motions;
396 motions.reserve( numPoints );
398 for (
int it = 0; it < iterations; ++it )
406 for (
int i = 0; i < numPoints; ++i )
408 if ( isClosed && i == numPoints - 1 )
409 motions << motions.at( 0 );
410 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
420 a = ring->
pointN( numPoints - 1 );
423 if ( i == numPoints - 1 )
426 c = ring->
pointN( i + 1 );
428 motions <<
calcMotion( a, b, c, lowerThreshold, upperThreshold );
435 for (
int i = 0; i < numPoints; ++i )
437 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
438 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
441 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
442 if ( newScore < minScore )
444 best.reset( ring->
clone() );
448 if ( minScore < tolerance )
454 return best.release();
460 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
464 geom = segmentizedCopy.get();
470 maxIterations, tolerance, lowerThreshold, upperThreshold );
479 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
483 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
498 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
499 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
501 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
503 int numGeom = gc->numGeometries();
504 QVector< QgsAbstractGeometry * > geometryList;
505 geometryList.reserve( numGeom );
506 for (
int i = 0; i < numGeom; ++i )
508 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
527 QVector< double > outX;
528 QVector< double > outY;
529 QVector< double > outZ;
530 QVector< double > outM;
531 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
534 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
535 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
536 bool withZ = ring->
is3D();
538 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
541 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
554 int extraNodesThisSegment = extraNodesPerSegment;
555 for (
int i = 0; i < nPoints - 1; ++i )
558 x2 = ring->
xAt( i + 1 );
560 y2 = ring->
yAt( i + 1 );
564 z2 = ring->
zAt( i + 1 );
569 m2 = ring->
mAt( i + 1 );
579 if ( extraNodesPerSegment < 0 )
582 extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
583 if ( extraNodesThisSegment >= 1 )
584 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
587 for (
int j = 0; j < extraNodesThisSegment; ++j )
589 double delta = multiplier * ( j + 1 );
590 xOut = x1 + delta * ( x2 - x1 );
591 yOut = y1 + delta * ( y2 - y1 );
593 zOut = z1 + delta * ( z2 - z1 );
595 mOut = m1 + delta * ( m2 - m1 );
605 outX << ring->
xAt( nPoints - 1 );
606 outY << ring->
yAt( nPoints - 1 );
608 outZ << ring->
zAt( nPoints - 1 );
610 outM << ring->
mAt( nPoints - 1 );
618 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
622 geom = segmentizedCopy.get();
627 return doDensify( static_cast< const QgsLineString * >( geom ), extraNodesPerSegment, distance );
636 extraNodesPerSegment, distance ) );
640 extraNodesPerSegment, distance ) );
659 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
661 int numGeom = gc->numGeometries();
662 QVector< QgsAbstractGeometry * > geometryList;
663 geometryList.reserve( numGeom );
664 for (
int i = 0; i < numGeom; ++i )
666 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
694 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
696 int numGeom = gc->numGeometries();
697 QVector< QgsAbstractGeometry * > geometryList;
698 geometryList.reserve( numGeom );
699 for (
int i = 0; i < numGeom; ++i )
726 "line_segment_dist_comparer",
727 "AB must not be collinear with the origin." );
729 "line_segment_dist_comparer",
730 "CD must not be collinear with the origin." );
744 if ( ab.
end() == cd.
end() || oad != oab )
754 if ( cdb == 0 && cda == 0 )
756 return mOrigin.sqrDist( ab.
start() ) < mOrigin.sqrDist( cd.
start() );
758 else if ( cda == cdb || cda == 0 || cdb == 0 )
761 return cdo == cda || cdo == cdb;
777 const bool aIsLeft = a.
x() < mVertex.x();
778 const bool bIsLeft = b.
x() < mVertex.x();
779 if ( aIsLeft != bIsLeft )
784 if ( a.
y() >= mVertex.y() || b.
y() >= mVertex.y() )
786 return b.
y() < a.
y();
790 return a.
y() < b.
y();
829 const double distA = ao * direction;
830 const double distB = ( origin - segment.
end() ) * direction;
832 if ( distA > 0 && distB > 0 )
838 if ( ( distA > 0 ) != ( distB > 0 ) )
839 intersectPoint = origin;
840 else if ( distA > distB )
841 intersectPoint = segment.
start();
843 intersectPoint = segment.
end();
851 if ( u < 0.0 || 1.0 < u )
858 intersectPoint = origin + direction * t;
867 if ( radius1 > radius2 )
874 QVector<QgsPointXY> points;
895 std::vector< std::unique_ptr<QgsLineString > > linesToProcess;
900 for (
int i = 0; i < multiCurve->
partCount(); ++i )
902 if ( static_cast< const QgsCurve * >( multiCurve->
geometryN( i ) )->nCoordinates() == 0 )
905 linesToProcess.emplace_back( static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() ) );
913 linesToProcess.emplace_back( static_cast<QgsLineString *>( curve->
segmentize() ) );
916 if ( linesToProcess.empty() )
919 g.mLastError = QStringLiteral(
"Input geometry was not a curve type geometry" );
923 QVector<QgsGeometry> bufferedLines;
924 bufferedLines.reserve( linesToProcess.size() );
926 for ( std::unique_ptr< QgsLineString > &line : linesToProcess )
928 QVector<QgsGeometry> parts;
930 double prevRadius = 0;
933 std::unique_ptr< double[] > widths = widthFunction( line.get() ) ;
938 double thisRadius = widths[ i ] / 2.0;
939 if ( thisRadius > 0 )
944 thisCircle =
QgsGeometry( circ.toPolygon( segments * 4 ) );
954 if ( prevRadius > 0 || thisRadius > 0 )
956 QVector< QgsPointXY > points =
generateSegmentCurve( prevPoint, prevRadius, thisPoint, thisRadius );
957 if ( !points.empty() )
962 int beforeVertex = 0;
965 double sqrDistPrev = 0;
966 for (
int j = 0; j < points.count(); ++j )
970 points[j] = sqrDistPrev < sqrDist ? pA : pB;
973 points.append( points.at( 0 ) );
975 std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >();
977 if ( poly->area() > 0 )
982 prevPoint = thisPoint;
983 prevRadius = thisRadius;
984 prevCircle = thisCircle;
995 start = std::fabs( start );
996 end = std::fabs( end );
1002 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1004 widths[line->nCoordinates() - 1] = end;
1006 double lineLength = line->length();
1007 double currentLength = 0;
1008 QgsPoint prevPoint = line->pointN( 0 );
1009 for (
int i = 1; i < line->nCoordinates() - 1; ++i )
1011 QgsPoint point = line->pointN( i );
1012 double segmentLength = point.
distance( prevPoint );
1013 currentLength += segmentLength;
1014 double lengthFraction = lineLength > 0 ? currentLength / lineLength : 1;
1015 double delta = lengthFraction * ( end - start );
1016 widths[i] = start + delta;
1029 std::unique_ptr< double [] > widths(
new double[ line->nCoordinates() ] );
1030 for (
int i = 0; i < line->nCoordinates(); ++i )
1032 widths[ i ] = line->mAt( i );
QgsAbstractGeometry * orthogonalizeGeom(const QgsAbstractGeometry *geom, int maxIterations, double tolerance, double lowerThreshold, double upperThreshold)
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
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.
double startY() const
Returns the segment's start y-coordinate.
QgsInternalGeometryEngine(const QgsGeometry &geometry)
The caller is responsible that the geometry is available and unchanged for the whole lifetime of this...
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.
OperationResult addPart(const QVector< QgsPointXY > &points, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::UnknownGeometry)
Adds a new part to a the geometry.
QgsPointXY start() const
Returns the segment's start point.
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)
double yMaximum() const
Returns the y maximum value (top side of rectangle).
A class to represent a 2D point.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
double lengthSquared() const
Returns the length of the vector.
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)
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.
double mAt(int index) const
Returns the m value of the specified node in the line string.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
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.
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...
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
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership)
bool isMeasure() const
Returns true if the geometry contains m values.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
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...
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
int pointLeftOfLine(const QgsPointXY &point) const
Tests if a point is to the left of the line segment.
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...
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
bool intersects(const QgsLineSegment2D &segment, QgsPointXY &intersectPoint) const
Finds the closest intersection point of the ray and a line segment.
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...
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
Multi curve geometry collection.
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
virtual bool isClosed() const
Returns true if the curve is closed.
Abstract base class for curved geometry type.
double startX() const
Returns the segment's start x-coordinate.
Abstract base class for all geometries.
QgsVector normalized() const
Returns the vector's normalized (or "unit") vector (ie same angle but length of 1.0).
Point geometry type, with support for z-dimension and m-values.
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.
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a tapered width buffer for a (multi)curve geometry.
double length() const
Returns the length of the vector.
double distance(double x, double y) const
Returns the distance between this point and a specified x, y coordinate.
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)
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
int partCount() const override
Returns count of parts contained in the geometry.
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
double zAt(int index) const
Returns the z-coordinate of the specified node in the line string.
Multi polygon geometry collection.
double endY() const
Returns the segment's end y-coordinate.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
double endX() const
Returns the segment's end x-coordinate.
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.
QgsPointXY end() const
Returns the segment's end point.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
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).
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
double crossProduct(QgsVector v) const
Returns the 2D cross product of this vector and another vector v.
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer using the m-values from a (multi)line geometry.
double width() const
Returns the width of the rectangle.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
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.
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 ...
double height() const
Returns the height of the rectangle.
QgsLineString * doOrthogonalize(QgsLineString *ring, int iterations, double tolerance, double lowerThreshold, double upperThreshold)
QgsGeometry poleOfInaccessibility(double precision, double *distanceFromBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...