32 : mGeometry( geometry.constGet() )
45 QVector<QgsLineString *> linesToProcess;
50 for (
int i = 0; i < multiCurve->
partCount(); ++i )
52 linesToProcess << static_cast<QgsLineString *>( multiCurve->
geometryN( i )->
clone() );
59 linesToProcess << static_cast<QgsLineString *>( curve->segmentize() );
62 std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ?
new QgsMultiPolygon() : nullptr );
65 if ( !linesToProcess.empty() )
67 std::unique_ptr< QgsLineString > secondline;
68 for (
QgsLineString *line : qgis::as_const( linesToProcess ) )
70 QTransform transform = QTransform::fromTranslate( x, y );
72 secondline.reset( line->reversed() );
73 secondline->transform( transform );
75 line->append( secondline.get() );
76 line->addVertex( line->pointN( 0 ) );
79 polygon->setExteriorRing( line );
82 multipolygon->addGeometry( polygon );
104 Cell(
double x,
double y,
double h,
const QgsPolygon *polygon )
109 , max( d + h * M_SQRT2 )
124 struct GreaterThanByMax
126 bool operator()(
const Cell *lhs,
const Cell *rhs )
128 return rhs->max > lhs->max;
132 Cell *getCentroidCell(
const QgsPolygon *polygon )
140 for (
int i = 0, j = len - 1; i < len; j = i++ )
142 double aX = exterior->
xAt( i );
143 double aY = exterior->
yAt( i );
144 double bX = exterior->
xAt( j );
145 double bY = exterior->
yAt( j );
146 double f = aX * bY - bX * aY;
147 x += ( aX + bX ) * f;
148 y += ( aY + bY ) * f;
152 return new Cell( exterior->
xAt( 0 ), exterior->
yAt( 0 ), 0, polygon );
154 return new Cell( x / area, y / area, 0.0, polygon );
157 QgsPoint surfacePoleOfInaccessibility(
const QgsSurface *surface,
double precision,
double &distanceFromBoundary )
159 std::unique_ptr< QgsPolygon > segmentizedPoly;
163 segmentizedPoly.reset( static_cast< QgsPolygon *>( surface->
segmentize() ) );
164 polygon = segmentizedPoly.get();
171 double cellSize = std::min( bounds.
width(), bounds.
height() );
176 double h = cellSize / 2.0;
177 std::priority_queue< Cell *, std::vector<Cell *>, GreaterThanByMax > cellQueue;
184 cellQueue.push(
new Cell( x + h, y + h, h, polygon ) );
189 std::unique_ptr< Cell > bestCell( getCentroidCell( polygon ) );
192 std::unique_ptr< Cell > bboxCell(
new Cell( bounds.
xMinimum() + bounds.
width() / 2.0,
195 if ( bboxCell->d > bestCell->d )
197 bestCell = std::move( bboxCell );
200 while ( !cellQueue.empty() )
203 std::unique_ptr< Cell > cell( cellQueue.top() );
205 Cell *currentCell = cell.get();
208 if ( currentCell->d > bestCell->d )
210 bestCell = std::move( cell );
214 if ( currentCell->max - bestCell->d <= precision )
218 h = currentCell->h / 2.0;
219 cellQueue.push(
new Cell( currentCell->x - h, currentCell->y - h, h, polygon ) );
220 cellQueue.push(
new Cell( currentCell->x + h, currentCell->y - h, h, polygon ) );
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 ) );
225 distanceFromBoundary = bestCell->d;
227 return QgsPoint( bestCell->x, bestCell->y );
234 if ( distanceFromBoundary )
235 *distanceFromBoundary = DBL_MAX;
237 if ( !mGeometry || mGeometry->isEmpty() )
240 if ( precision <= 0 )
243 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
245 int numGeom = gc->numGeometries();
249 for (
int i = 0; i < numGeom; ++i )
256 double dist = DBL_MAX;
257 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
258 if ( dist > maxDist )
268 if ( distanceFromBoundary )
269 *distanceFromBoundary = maxDist;
278 double dist = DBL_MAX;
279 QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
280 if ( distanceFromBoundary )
281 *distanceFromBoundary = dist;
292 return lowerThreshold > std::fabs( dotProduct ) || std::fabs( dotProduct ) > upperThreshold;
318 for (
int i = 0; i < numPoints; ++i )
320 if ( !isClosed && i == numPoints - 1 )
322 else if ( !isClosed && i == 0 )
331 a = ring->
pointN( numPoints - 1 );
334 if ( i == numPoints - 1 )
337 c = ring->
pointN( i + 1 );
343 sum += 2.0 * std::min( std::fabs( dotProduct - 1.0 ), std::min( std::fabs( dotProduct ), std::fabs( dotProduct + 1 ) ) );
353 double lowerThreshold,
double upperThreshold )
362 double scale = 2.0 * std::min( p.
length(), q.
length() );
366 double dotProduct = p * q;
375 if ( dotProduct < -M_SQRT1_2 )
380 return new_v.
normalized() * ( 0.1 * dotProduct * scale );
385 double minScore = DBL_MAX;
390 std::unique_ptr< QgsLineString > best( ring->
clone() );
392 for (
int it = 0; it < iterations; ++it )
394 QVector< QgsVector > motions;
395 motions.reserve( numPoints );
401 for (
int i = 0; i < numPoints; ++i )
403 if ( isClosed && i == numPoints - 1 )
404 motions << motions.at( 0 );
405 else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
415 a = ring->
pointN( numPoints - 1 );
418 if ( i == numPoints - 1 )
421 c = ring->
pointN( i + 1 );
423 motions <<
calcMotion( a, b, c, lowerThreshold, upperThreshold );
430 for (
int i = 0; i < numPoints; ++i )
432 ring->
setXAt( i, ring->
xAt( i ) + motions.at( i ).x() );
433 ring->
setYAt( i, ring->
yAt( i ) + motions.at( i ).y() );
436 double newScore =
squareness( ring, lowerThreshold, upperThreshold );
437 if ( newScore < minScore )
439 best.reset( ring->
clone() );
443 if ( minScore < tolerance )
449 return best.release();
455 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
459 geom = segmentizedCopy.get();
465 maxIterations, tolerance, lowerThreshold, upperThreshold );
474 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
478 maxIterations, tolerance, lowerThreshold, upperThreshold ) );
493 double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
494 double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );
496 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
498 int numGeom = gc->numGeometries();
499 QVector< QgsAbstractGeometry * > geometryList;
500 geometryList.reserve( numGeom );
501 for (
int i = 0; i < numGeom; ++i )
503 geometryList <<
orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
522 QVector< double > outX;
523 QVector< double > outY;
524 QVector< double > outZ;
525 QVector< double > outM;
526 double multiplier = 1.0 / double( extraNodesPerSegment + 1 );
529 outX.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
530 outY.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
531 bool withZ = ring->
is3D();
533 outZ.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
536 outM.reserve( ( extraNodesPerSegment + 1 ) * nPoints );
549 int extraNodesThisSegment = extraNodesPerSegment;
550 for (
int i = 0; i < nPoints - 1; ++i )
553 x2 = ring->
xAt( i + 1 );
555 y2 = ring->
yAt( i + 1 );
559 z2 = ring->
zAt( i + 1 );
564 m2 = ring->
mAt( i + 1 );
574 if ( extraNodesPerSegment < 0 )
577 extraNodesThisSegment = std::floor( std::sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) / distance );
578 if ( extraNodesThisSegment >= 1 )
579 multiplier = 1.0 / ( extraNodesThisSegment + 1 );
582 for (
int j = 0; j < extraNodesThisSegment; ++j )
584 double delta = multiplier * ( j + 1 );
585 xOut = x1 + delta * ( x2 - x1 );
586 yOut = y1 + delta * ( y2 - y1 );
588 zOut = z1 + delta * ( z2 - z1 );
590 mOut = m1 + delta * ( m2 - m1 );
600 outX << ring->
xAt( nPoints - 1 );
601 outY << ring->
yAt( nPoints - 1 );
603 outZ << ring->
zAt( nPoints - 1 );
605 outM << ring->
mAt( nPoints - 1 );
613 std::unique_ptr< QgsAbstractGeometry > segmentizedCopy;
617 geom = segmentizedCopy.get();
622 return doDensify( static_cast< const QgsLineString * >( geom ), extraNodesPerSegment, distance );
631 extraNodesPerSegment, distance ) );
635 extraNodesPerSegment, distance ) );
654 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
656 int numGeom = gc->numGeometries();
657 QVector< QgsAbstractGeometry * > geometryList;
658 geometryList.reserve( numGeom );
659 for (
int i = 0; i < numGeom; ++i )
661 geometryList <<
densifyGeometry( gc->geometryN( i ), extraNodesPerSegment );
689 if (
const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
691 int numGeom = gc->numGeometries();
692 QVector< QgsAbstractGeometry * > geometryList;
693 geometryList.reserve( numGeom );
694 for (
int i = 0; i < numGeom; ++i )
bool isMeasure() const
Returns true if the geometry contains m values.
const QgsCurve * interiorRing(int i) const
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...
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.
double normalizedDotProduct(const QgsPoint &a, const QgsPoint &b, const QgsPoint &c)
QgsGeometry poleOfInaccessibility(double precision, double *distanceFromBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
A geometry is the spatial representation of a feature.
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.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
void setXAt(int index, double x)
Sets the x-coordinate of the specified node in the line string.
int numPoints() const override
Returns the number of points in the curve.
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership)
int numInteriorRings() const
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.
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.
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.
const QgsCurve * exteriorRing() const
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)
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).
bool dotProductWithinAngleTolerance(double dotProduct, double lowerThreshold, double upperThreshold)
int partCount() const override
Returns count of parts contained in the geometry.
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
Multi polygon geometry collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the 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.
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...
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Densifies the geometry by adding the specified number of extra nodes within each segment of the geome...
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
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...
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)