Skip to content

Commit

Permalink
Add methods to directly buffer/offset GEOS geometry in QgsGeos
Browse files Browse the repository at this point in the history
These methods directly work with GEOS geometries and avoid the
forced conversions to/from QgsAbstractGeometry objects, and are
intended for use in chained operations where the intermediate conversions
are not required.
  • Loading branch information
nyalldawson committed Feb 12, 2025
1 parent 649dc29 commit ecf57ef
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
3 changes: 3 additions & 0 deletions python/PyQt6/core/auto_generated/geometry/qgsgeos.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ Curved geometries are not supported.

virtual QgsAbstractGeometry *buffer( double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg = 0 ) const;



virtual QgsAbstractGeometry *simplify( double tolerance, QString *errorMsg = 0 ) const;

virtual QgsAbstractGeometry *interpolate( double distance, QString *errorMsg = 0 ) const;
Expand Down Expand Up @@ -287,6 +289,7 @@ This method requires a QGIS build based on GEOS 3.7 or later.
QgsPointSequence &topologyTestPoints,
QString *errorMsg = 0, bool skipIntersectionCheck = false ) const;


virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg = 0 ) const;


Expand Down
3 changes: 3 additions & 0 deletions python/core/auto_generated/geometry/qgsgeos.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ Curved geometries are not supported.

virtual QgsAbstractGeometry *buffer( double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg = 0 ) const;



virtual QgsAbstractGeometry *simplify( double tolerance, QString *errorMsg = 0 ) const;

virtual QgsAbstractGeometry *interpolate( double distance, QString *errorMsg = 0 ) const;
Expand Down Expand Up @@ -287,6 +289,7 @@ This method requires a QGIS build based on GEOS 3.7 or later.
QgsPointSequence &topologyTestPoints,
QString *errorMsg = 0, bool skipIntersectionCheck = false ) const;


virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg = 0 ) const;


Expand Down
30 changes: 22 additions & 8 deletions src/core/geometry/qgsgeos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2094,18 +2094,24 @@ QgsAbstractGeometry *QgsGeos::buffer( double distance, int segments, QString *er

QgsAbstractGeometry *QgsGeos::buffer( double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg ) const
{
if ( !mGeos )
geos::unique_ptr geos = buffer( mGeos.get(), distance, segments, endCapStyle, joinStyle, miterLimit, errorMsg );
return fromGeos( geos.get() ).release();
}

geos::unique_ptr QgsGeos::buffer( const GEOSGeometry *geometry, double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg )
{
if ( !geometry )
{
return nullptr;
}

geos::unique_ptr geos;
try
{
geos.reset( GEOSBufferWithStyle_r( QgsGeosContext::get(), mGeos.get(), distance, segments, static_cast< int >( endCapStyle ), static_cast< int >( joinStyle ), miterLimit ) );
geos.reset( GEOSBufferWithStyle_r( QgsGeosContext::get(), geometry, distance, segments, static_cast< int >( endCapStyle ), static_cast< int >( joinStyle ), miterLimit ) );
}
CATCH_GEOS_WITH_ERRMSG( nullptr )
return fromGeos( geos.get() ).release();
return geos;
}

QgsAbstractGeometry *QgsGeos::simplify( double tolerance, QString *errorMsg ) const
Expand Down Expand Up @@ -2743,9 +2749,9 @@ geos::unique_ptr QgsGeos::createGeosPolygon( const QgsAbstractGeometry *poly, do
return geosPolygon;
}

QgsAbstractGeometry *QgsGeos::offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg ) const
geos::unique_ptr QgsGeos::offsetCurve( const GEOSGeometry *geometry, double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg )
{
if ( !mGeos )
if ( !geometry )
return nullptr;

geos::unique_ptr offset;
Expand All @@ -2755,11 +2761,19 @@ QgsAbstractGeometry *QgsGeos::offsetCurve( double distance, int segments, Qgis::
// https://github.com/qgis/QGIS/issues/53165#issuecomment-1563470832
if ( segments < 8 )
segments = 8;
offset.reset( GEOSOffsetCurve_r( QgsGeosContext::get(), mGeos.get(), distance, segments, static_cast< int >( joinStyle ), miterLimit ) );
offset.reset( GEOSOffsetCurve_r( QgsGeosContext::get(), geometry, distance, segments, static_cast< int >( joinStyle ), miterLimit ) );
}
CATCH_GEOS_WITH_ERRMSG( nullptr )
std::unique_ptr< QgsAbstractGeometry > offsetGeom = fromGeos( offset.get() );
return offsetGeom.release();
return offset;
}

QgsAbstractGeometry *QgsGeos::offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg ) const
{
geos::unique_ptr res = offsetCurve( mGeos.get(), distance, segments, joinStyle, miterLimit, errorMsg );
if ( !res )
return nullptr;

return fromGeos( res.get() ).release();
}

std::unique_ptr<QgsAbstractGeometry> QgsGeos::singleSidedBuffer( double distance, int segments, Qgis::BufferSide side, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg ) const
Expand Down
17 changes: 17 additions & 0 deletions src/core/geometry/qgsgeos.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,15 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
QgsAbstractGeometry *symDifference( const QgsAbstractGeometry *geom, QString *errorMsg = nullptr, const QgsGeometryParameters &parameters = QgsGeometryParameters() ) 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;

/**
* Directly calculates the buffer for a GEOS geometry object and returns a GEOS geometry result.
*
* \note Not available in Python bindings
* \since QGIS 3.42
*/
SIP_SKIP static geos::unique_ptr buffer( const GEOSGeometry *geometry, double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg = nullptr );

QgsAbstractGeometry *simplify( double tolerance, QString *errorMsg = nullptr ) const override;
QgsAbstractGeometry *interpolate( double distance, QString *errorMsg = nullptr ) const override;
QgsAbstractGeometry *envelope( QString *errorMsg = nullptr ) const override;
Expand Down Expand Up @@ -380,6 +389,14 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
QgsPointSequence &topologyTestPoints,
QString *errorMsg = nullptr, bool skipIntersectionCheck = false ) const override;

/**
* Directly calculates the offset curve for a GEOS geometry object and returns a GEOS geometry result.
*
* \note Not available in Python bindings
* \since QGIS 3.42
*/
SIP_SKIP static geos::unique_ptr offsetCurve( const GEOSGeometry *geometry, double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg = nullptr );

QgsAbstractGeometry *offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg = nullptr ) const override;

/**
Expand Down

0 comments on commit ecf57ef

Please sign in to comment.