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)