diff --git a/python/core/auto_generated/geometry/qgsgeometryengine.sip.in b/python/core/auto_generated/geometry/qgsgeometryengine.sip.in index 7d747e3d299..bca92e7aec6 100644 --- a/python/core/auto_generated/geometry/qgsgeometryengine.sip.in +++ b/python/core/auto_generated/geometry/qgsgeometryengine.sip.in @@ -89,42 +89,42 @@ tests against other geometries. .. seealso:: :py:func:`geometryChanged` %End - virtual QgsAbstractGeometry *intersection( const QgsAbstractGeometry *geom, QString *errorMsg = 0 ) const = 0 /Factory/; + virtual QgsAbstractGeometry *intersection( const QgsAbstractGeometry *geom, QString *errorMsg = 0, double gridSize = -1 ) const = 0 /Factory/; %Docstring Calculate the intersection of this and ``geom``. .. versionadded:: 3.0 %End - virtual QgsAbstractGeometry *difference( const QgsAbstractGeometry *geom, QString *errorMsg = 0 ) const = 0 /Factory/; + virtual QgsAbstractGeometry *difference( const QgsAbstractGeometry *geom, QString *errorMsg = 0, double gridSize = -1 ) const = 0 /Factory/; %Docstring Calculate the difference of this and ``geom``. .. versionadded:: 3.0 %End - virtual QgsAbstractGeometry *combine( const QgsAbstractGeometry *geom, QString *errorMsg = 0 ) const = 0 /Factory/; + virtual QgsAbstractGeometry *combine( const QgsAbstractGeometry *geom, QString *errorMsg = 0, double gridSize = -1 ) const = 0 /Factory/; %Docstring Calculate the combination of this and ``geom``. .. versionadded:: 3.0 %End - virtual QgsAbstractGeometry *combine( const QVector &geomList, QString *errorMsg ) const = 0 /Factory/; + virtual QgsAbstractGeometry *combine( const QVector &geomList, QString *errorMsg, double gridSize = -1 ) const = 0 /Factory/; %Docstring Calculate the combination of this and ``geometries``. .. versionadded:: 3.0 %End - virtual QgsAbstractGeometry *combine( const QVector< QgsGeometry > &geometries, QString *errorMsg = 0 ) const = 0 /Factory/; + virtual QgsAbstractGeometry *combine( const QVector< QgsGeometry > &geometries, QString *errorMsg = 0, double gridSize = -1 ) const = 0 /Factory/; %Docstring Calculate the combination of this and ``geometries``. .. versionadded:: 3.0 %End - virtual QgsAbstractGeometry *symDifference( const QgsAbstractGeometry *geom, QString *errorMsg = 0 ) const = 0 /Factory/; + virtual QgsAbstractGeometry *symDifference( const QgsAbstractGeometry *geom, QString *errorMsg = 0, double gridSize = -1 ) const = 0 /Factory/; %Docstring Calculate the symmetric difference of this and ``geom``. @@ -330,7 +330,6 @@ Logs an error ``message`` encountered during an operation. QgsGeometryEngine( const QgsAbstractGeometry *geometry ); }; - /************************************************************************ * This file has been generated automatically from * * * diff --git a/src/core/geometry/qgsgeometryengine.h b/src/core/geometry/qgsgeometryengine.h index 543fcc26a3a..08cde462327 100644 --- a/src/core/geometry/qgsgeometryengine.h +++ b/src/core/geometry/qgsgeometryengine.h @@ -110,42 +110,42 @@ class CORE_EXPORT QgsGeometryEngine * * \since QGIS 3.0 \a geom is a pointer */ - virtual QgsAbstractGeometry *intersection( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY; + virtual QgsAbstractGeometry *intersection( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, double gridSize = -1 ) const = 0 SIP_FACTORY; /** * Calculate the difference of this and \a geom. * * \since QGIS 3.0 \a geom is a pointer */ - virtual QgsAbstractGeometry *difference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY; + virtual QgsAbstractGeometry *difference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, double gridSize = -1 ) const = 0 SIP_FACTORY; /** * Calculate the combination of this and \a geom. * * \since QGIS 3.0 \a geom is a pointer */ - virtual QgsAbstractGeometry *combine( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY; + virtual QgsAbstractGeometry *combine( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, double gridSize = -1 ) const = 0 SIP_FACTORY; /** * Calculate the combination of this and \a geometries. * * \since QGIS 3.0 \a geom is a pointer */ - virtual QgsAbstractGeometry *combine( const QVector &geomList, QString *errorMsg ) const = 0 SIP_FACTORY; + virtual QgsAbstractGeometry *combine( const QVector &geomList, QString *errorMsg, double gridSize = -1 ) const = 0 SIP_FACTORY; /** * Calculate the combination of this and \a geometries. * * \since QGIS 3.0 \a geom is a pointer */ - virtual QgsAbstractGeometry *combine( const QVector< QgsGeometry > &geometries, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY; + virtual QgsAbstractGeometry *combine( const QVector< QgsGeometry > &geometries, QString *errorMsg = nullptr, double gridSize = -1 ) const = 0 SIP_FACTORY; /** * Calculate the symmetric difference of this and \a geom. * * \since QGIS 3.0 \a geom is a pointer */ - virtual QgsAbstractGeometry *symDifference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY; + virtual QgsAbstractGeometry *symDifference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, double gridSize = -1 ) const = 0 SIP_FACTORY; virtual QgsAbstractGeometry *buffer( double distance, int segments, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY; /** @@ -358,4 +358,3 @@ class CORE_EXPORT QgsGeometryEngine }; #endif // QGSGEOMETRYENGINE_H - diff --git a/src/core/geometry/qgsgeos.cpp b/src/core/geometry/qgsgeos.cpp index 96fc8424a43..3e40ae57315 100644 --- a/src/core/geometry/qgsgeos.cpp +++ b/src/core/geometry/qgsgeos.cpp @@ -277,14 +277,14 @@ void QgsGeos::cacheGeos() const mGeos = asGeos( mGeometry, mPrecision ); } -QgsAbstractGeometry *QgsGeos::intersection( const QgsAbstractGeometry *geom, QString *errorMsg ) const +QgsAbstractGeometry *QgsGeos::intersection( const QgsAbstractGeometry *geom, QString *errorMsg, double gridSize ) const { - return overlay( geom, OverlayIntersection, errorMsg ).release(); + return overlay( geom, OverlayIntersection, errorMsg, gridSize ).release(); } -QgsAbstractGeometry *QgsGeos::difference( const QgsAbstractGeometry *geom, QString *errorMsg ) const +QgsAbstractGeometry *QgsGeos::difference( const QgsAbstractGeometry *geom, QString *errorMsg, double gridSize ) const { - return overlay( geom, OverlayDifference, errorMsg ).release(); + return overlay( geom, OverlayDifference, errorMsg, gridSize ).release(); } std::unique_ptr QgsGeos::clip( const QgsRectangle &rect, QString *errorMsg ) const @@ -313,7 +313,7 @@ std::unique_ptr QgsGeos::clip( const QgsRectangle &rect, QS -void QgsGeos::subdivideRecursive( const GEOSGeometry *currentPart, int maxNodes, int depth, QgsGeometryCollection *parts, const QgsRectangle &clipRect ) const +void QgsGeos::subdivideRecursive( const GEOSGeometry *currentPart, int maxNodes, int depth, QgsGeometryCollection *parts, const QgsRectangle &clipRect, double gridSize ) const { int partType = GEOSGeomTypeId_r( geosinit()->ctxt, currentPart ); if ( qgsDoubleNear( clipRect.width(), 0.0 ) && qgsDoubleNear( clipRect.height(), 0.0 ) ) @@ -334,7 +334,7 @@ void QgsGeos::subdivideRecursive( const GEOSGeometry *currentPart, int maxNodes, int partCount = GEOSGetNumGeometries_r( geosinit()->ctxt, currentPart ); for ( int i = 0; i < partCount; ++i ) { - subdivideRecursive( GEOSGetGeometryN_r( geosinit()->ctxt, currentPart, i ), maxNodes, depth, parts, clipRect ); + subdivideRecursive( GEOSGetGeometryN_r( geosinit()->ctxt, currentPart, i ), maxNodes, depth, parts, clipRect, gridSize ); } return; } @@ -394,15 +394,15 @@ void QgsGeos::subdivideRecursive( const GEOSGeometry *currentPart, int maxNodes, if ( clipPart1 ) { - subdivideRecursive( clipPart1.get(), maxNodes, depth, parts, halfClipRect1 ); + subdivideRecursive( clipPart1.get(), maxNodes, depth, parts, halfClipRect1, gridSize ); } if ( clipPart2 ) { - subdivideRecursive( clipPart2.get(), maxNodes, depth, parts, halfClipRect2 ); + subdivideRecursive( clipPart2.get(), maxNodes, depth, parts, halfClipRect2, gridSize ); } } -std::unique_ptr QgsGeos::subdivide( int maxNodes, QString *errorMsg ) const +std::unique_ptr QgsGeos::subdivide( int maxNodes, QString *errorMsg, double gridSize ) const { if ( !mGeos ) { @@ -415,19 +415,19 @@ std::unique_ptr QgsGeos::subdivide( int maxNodes, QString * std::unique_ptr< QgsGeometryCollection > parts = QgsGeometryFactory::createCollectionOfType( mGeometry->wkbType() ); try { - subdivideRecursive( mGeos.get(), maxNodes, 0, parts.get(), mGeometry->boundingBox() ); + subdivideRecursive( mGeos.get(), maxNodes, 0, parts.get(), mGeometry->boundingBox(), gridSize ); } CATCH_GEOS_WITH_ERRMSG( nullptr ) return std::move( parts ); } -QgsAbstractGeometry *QgsGeos::combine( const QgsAbstractGeometry *geom, QString *errorMsg ) const +QgsAbstractGeometry *QgsGeos::combine( const QgsAbstractGeometry *geom, QString *errorMsg, double gridSize ) const { - return overlay( geom, OverlayUnion, errorMsg ).release(); + return overlay( geom, OverlayUnion, errorMsg, gridSize ).release(); } -QgsAbstractGeometry *QgsGeos::combine( const QVector &geomList, QString *errorMsg ) const +QgsAbstractGeometry *QgsGeos::combine( const QVector &geomList, QString *errorMsg, double gridSize ) const { QVector< GEOSGeometry * > geosGeometries; geosGeometries.reserve( geomList.size() ); @@ -443,7 +443,11 @@ QgsAbstractGeometry *QgsGeos::combine( const QVector &geo try { geos::unique_ptr geomCollection = createGeosCollection( GEOS_GEOMETRYCOLLECTION, geosGeometries ); +#if ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 ) + geomUnion.reset( GEOSUnaryUnionPrec_r( geosinit()->ctxt, geomCollection.get(), gridSize ) ); +#else geomUnion.reset( GEOSUnaryUnion_r( geosinit()->ctxt, geomCollection.get() ) ); +#endif } CATCH_GEOS_WITH_ERRMSG( nullptr ) @@ -451,7 +455,7 @@ QgsAbstractGeometry *QgsGeos::combine( const QVector &geo return result.release(); } -QgsAbstractGeometry *QgsGeos::combine( const QVector &geomList, QString *errorMsg ) const +QgsAbstractGeometry *QgsGeos::combine( const QVector &geomList, QString *errorMsg, double gridSize ) const { QVector< GEOSGeometry * > geosGeometries; geosGeometries.reserve( geomList.size() ); @@ -467,7 +471,13 @@ QgsAbstractGeometry *QgsGeos::combine( const QVector &geomList, QSt try { geos::unique_ptr geomCollection = createGeosCollection( GEOS_GEOMETRYCOLLECTION, geosGeometries ); + +#if (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 ) + geomUnion.reset( GEOSUnaryUnionPrec_r( geosinit()->ctxt, geomCollection.get(), gridSize ) ); +#else geomUnion.reset( GEOSUnaryUnion_r( geosinit()->ctxt, geomCollection.get() ) ); +#endif + } CATCH_GEOS_WITH_ERRMSG( nullptr ) @@ -475,9 +485,9 @@ QgsAbstractGeometry *QgsGeos::combine( const QVector &geomList, QSt return result.release(); } -QgsAbstractGeometry *QgsGeos::symDifference( const QgsAbstractGeometry *geom, QString *errorMsg ) const +QgsAbstractGeometry *QgsGeos::symDifference( const QgsAbstractGeometry *geom, QString *errorMsg, double gridSize ) const { - return overlay( geom, OverlaySymDifference, errorMsg ).release(); + return overlay( geom, OverlaySymDifference, errorMsg, gridSize ).release(); } double QgsGeos::distance( const QgsAbstractGeometry *geom, QString *errorMsg ) const @@ -1660,7 +1670,7 @@ geos::unique_ptr QgsGeos::asGeos( const QgsAbstractGeometry *geom, double precis return nullptr; } -std::unique_ptr QgsGeos::overlay( const QgsAbstractGeometry *geom, Overlay op, QString *errorMsg ) const +std::unique_ptr QgsGeos::overlay( const QgsAbstractGeometry *geom, Overlay op, QString *errorMsg, double gridSize ) const { if ( !mGeos || !geom ) { @@ -1679,16 +1689,28 @@ std::unique_ptr QgsGeos::overlay( const QgsAbstractGeometry switch ( op ) { case OverlayIntersection: +#if (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 ) + opGeom.reset( GEOSIntersectionPrec_r( geosinit()->ctxt, mGeos.get(), geosGeom.get(), gridSize ) ); +#else opGeom.reset( GEOSIntersection_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) ); +#endif break; case OverlayDifference: +#if (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 ) + opGeom.reset( GEOSDifferencePrec_r( geosinit()->ctxt, mGeos.get(), geosGeom.get(), gridSize ) ); +#else opGeom.reset( GEOSDifference_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) ); +#endif break; case OverlayUnion: { +#if (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 ) + geos::unique_ptr unionGeometry( GEOSUnionPrec_r( geosinit()->ctxt, mGeos.get(), geosGeom.get(), gridSize ) ); +#else geos::unique_ptr unionGeometry( GEOSUnion_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) ); +#endif if ( unionGeometry && GEOSGeomTypeId_r( geosinit()->ctxt, unionGeometry.get() ) == GEOS_MULTILINESTRING ) { @@ -1704,7 +1726,11 @@ std::unique_ptr QgsGeos::overlay( const QgsAbstractGeometry break; case OverlaySymDifference: +#if (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 ) + opGeom.reset( GEOSSymDifferencePrec_r( geosinit()->ctxt, mGeos.get(), geosGeom.get(), gridSize ) ); +#else opGeom.reset( GEOSSymDifference_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) ); +#endif break; } return fromGeos( opGeom.get() ); diff --git a/src/core/geometry/qgsgeos.h b/src/core/geometry/qgsgeos.h index 964c867ca61..e751bdf4e1e 100644 --- a/src/core/geometry/qgsgeos.h +++ b/src/core/geometry/qgsgeos.h @@ -138,8 +138,8 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine void geometryChanged() override; void prepareGeometry() override; - QgsAbstractGeometry *intersection( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const override; - QgsAbstractGeometry *difference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const override; + QgsAbstractGeometry *intersection( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, double gridSize = -1 ) const override; + QgsAbstractGeometry *difference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, double gridSize = -1 ) const override; /** * Performs a fast, non-robust intersection between the geometry and @@ -161,12 +161,12 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine * * \since QGIS 3.0 */ - std::unique_ptr< QgsAbstractGeometry > subdivide( int maxNodes, QString *errorMsg = nullptr ) const; + std::unique_ptr< QgsAbstractGeometry > subdivide( int maxNodes, QString *errorMsg = nullptr, double gridSize = -1 ) const; - QgsAbstractGeometry *combine( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const override; - QgsAbstractGeometry *combine( const QVector &geomList, QString *errorMsg ) const override; - QgsAbstractGeometry *combine( const QVector< QgsGeometry > &, QString *errorMsg = nullptr ) const override; - QgsAbstractGeometry *symDifference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr ) const override; + QgsAbstractGeometry *combine( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, double gridSize = -1 ) const override; + QgsAbstractGeometry *combine( const QVector &geomList, QString *errorMsg, double gridSize = -1 ) const override; + QgsAbstractGeometry *combine( const QVector< QgsGeometry > &, QString *errorMsg = nullptr, double gridSize = -1 ) const override; + QgsAbstractGeometry *symDifference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, double gridSize = -1 ) const override; QgsAbstractGeometry *buffer( double distance, int segments, QString *errorMsg = nullptr ) const override; QgsAbstractGeometry *buffer( double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg = nullptr ) const override; QgsAbstractGeometry *simplify( double tolerance, QString *errorMsg = nullptr ) const override; @@ -622,7 +622,7 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine //geos util functions void cacheGeos() const; - std::unique_ptr< QgsAbstractGeometry > overlay( const QgsAbstractGeometry *geom, Overlay op, QString *errorMsg = nullptr ) const; + std::unique_ptr< QgsAbstractGeometry > overlay( const QgsAbstractGeometry *geom, Overlay op, QString *errorMsg = nullptr, double gridSize = -1 ) const; bool relation( const QgsAbstractGeometry *geom, Relation r, QString *errorMsg = nullptr ) const; static GEOSCoordSequence *createCoordinateSequence( const QgsCurve *curve, double precision, bool forceClose = false ); static std::unique_ptr< QgsLineString > sequenceToLinestring( const GEOSGeometry *geos, bool hasZ, bool hasM ); @@ -652,7 +652,7 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine static int lineContainedInLine( const GEOSGeometry *line1, const GEOSGeometry *line2 ); static int pointContainedInLine( const GEOSGeometry *point, const GEOSGeometry *line ); static int geomDigits( const GEOSGeometry *geom ); - void subdivideRecursive( const GEOSGeometry *currentPart, int maxNodes, int depth, QgsGeometryCollection *parts, const QgsRectangle &clipRect ) const; + void subdivideRecursive( const GEOSGeometry *currentPart, int maxNodes, int depth, QgsGeometryCollection *parts, const QgsRectangle &clipRect, double gridSize = -1 ) const; }; /// @cond PRIVATE