Skip to content

Commit 9872b48

Browse files
committed
Remove caching of GEOS representation within QgsGeometry (legacy)
1 parent d729951 commit 9872b48

15 files changed

+89
-74
lines changed

doc/api_break.dox

+1
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ value instead of a pointer. The biggest impact with this change is that PyQGIS c
844844
result to None, but instead either use a boolean test (`if g.buffer(10):`) or explicitly use the isEmpty()
845845
method to determine if a geometry is valid.
846846
- wkbSize() and asWkb() has been replaced by exportToWkb(). WKB representation is no longer cached within QgsGeometry
847+
- asGeos() has been replaced by exportToGeos(). GEOS representation is no longer cached within QgsGeometry
847848
- int addPart( const QList<QgsPoint> &points, QgsWkbTypes::GeometryType geomType ) has been renamed to addPoints
848849
- int addPart( const QList<QgsPointV2> &points, QgsWkbTypes::GeometryType geomType ) has been renamed to addPointsV2
849850
- static bool compare( const QgsPolyline& p1, const QgsPolyline& p2, double epsilon ) has been renamed to comparePolylines

python/core/geometry/qgsgeometry.sip

+3-3
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ class QgsGeometry
103103
*/
104104
void fromWkb( const QByteArray& wkb );
105105

106-
/** Returns a geos geometry. QgsGeometry retains ownership of the geometry, so the returned object should not be deleted.
106+
/** Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destroy_r)
107107
* @param precision The precision of the grid to which to snap the geometry vertices. If 0, no snapping is performed.
108-
* @note this method was added in version 1.1
108+
* @note added in version 3.0
109109
* @note not available in python bindings
110110
*/
111-
// const GEOSGeometry* asGeos( double precision = 0 ) const;
111+
// GEOSGeometry* exportToGeos( double precision = 0 ) const;
112112

113113
/** Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
114114
* @see type

src/analysis/vector/qgsgeometryanalyzer.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,9 @@ QgsGeometry QgsGeometryAnalyzer::createOffsetGeometry( const QgsGeometry& geom,
10631063
{
10641064
if ( geom.type() == QgsWkbTypes::LineGeometry )
10651065
{
1066-
GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, ( *inputGeomIt ).asGeos(), -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ );
1066+
GEOSGeometry* inputGeomItGeos = inputGeomIt->exportToGeos();
1067+
GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, inputGeomItGeos, -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ );
1068+
GEOSGeom_destroy_r( geosctxt, inputGeomItGeos );
10671069
if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) )
10681070
{
10691071
return QgsGeometry();

src/analysis/vector/qgszonalstatistics.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -419,16 +419,17 @@ void QgsZonalStatistics::statisticsFromMiddlePointTest( void* band, const QgsGeo
419419
cellCenterY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
420420
stats.reset();
421421

422-
const GEOSGeometry* polyGeos = poly.asGeos();
422+
GEOSGeometry* polyGeos = poly.exportToGeos();
423423
if ( !polyGeos )
424424
{
425425
return;
426426
}
427427

428428
GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler();
429-
const GEOSPreparedGeometry* polyGeosPrepared = GEOSPrepare_r( geosctxt, poly.asGeos() );
429+
const GEOSPreparedGeometry* polyGeosPrepared = GEOSPrepare_r( geosctxt, polyGeos );
430430
if ( !polyGeosPrepared )
431431
{
432+
GEOSGeom_destroy_r( geosctxt, polyGeos );
432433
return;
433434
}
434435

@@ -464,6 +465,7 @@ void QgsZonalStatistics::statisticsFromMiddlePointTest( void* band, const QgsGeo
464465
GEOSGeom_destroy_r( geosctxt, currentCellCenter );
465466
CPLFree( scanLine );
466467
GEOSPreparedGeom_destroy_r( geosctxt, polyGeosPrepared );
468+
GEOSGeom_destroy_r( geosctxt, polyGeos );
467469
}
468470

469471
void QgsZonalStatistics::statisticsFromPreciseIntersection( void* band, const QgsGeometry& poly, int pixelOffsetX,

src/app/qgsmaptooloffsetcurve.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ void QgsMapToolOffsetCurve::setOffsetForRubberBand( double offset )
368368
}
369369

370370
QgsGeometry geomCopy( mOriginalGeometry );
371-
const GEOSGeometry* geosGeom = geomCopy.asGeos();
371+
GEOSGeometry* geosGeom = geomCopy.exportToGeos();
372372
if ( geosGeom )
373373
{
374374
QSettings s;
@@ -377,6 +377,7 @@ void QgsMapToolOffsetCurve::setOffsetForRubberBand( double offset )
377377
double mitreLimit = s.value( QStringLiteral( "/qgis/digitizing/offset_miter_limit" ), 5.0 ).toDouble();
378378

379379
GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( QgsGeometry::getGEOSHandler(), geosGeom, offset, quadSegments, joinStyle, mitreLimit );
380+
GEOSGeom_destroy_r( QgsGeometry::getGEOSHandler(), geosGeom );
380381
if ( !offsetGeom )
381382
{
382383
deleteRubberBandAndGeometry();

src/core/geometry/qgsgeometry.cpp

+5-10
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,10 @@ email : morb at ozemail dot com dot au
5454

5555
struct QgsGeometryPrivate
5656
{
57-
QgsGeometryPrivate(): ref( 1 ), geometry( nullptr ), mGeos( nullptr ) {}
58-
~QgsGeometryPrivate() { delete geometry; GEOSGeom_destroy_r( QgsGeos::getGEOSHandler(), mGeos ); }
57+
QgsGeometryPrivate(): ref( 1 ), geometry( nullptr ) {}
58+
~QgsGeometryPrivate() { delete geometry; }
5959
QAtomicInt ref;
6060
QgsAbstractGeometry* geometry;
61-
mutable GEOSGeometry* mGeos;
6261
};
6362

6463
QgsGeometry::QgsGeometry(): d( new QgsGeometryPrivate() )
@@ -269,18 +268,14 @@ void QgsGeometry::fromWkb( const QByteArray &wkb )
269268
d->geometry = QgsGeometryFactory::geomFromWkb( ptr );
270269
}
271270

272-
const GEOSGeometry* QgsGeometry::asGeos( double precision ) const
271+
GEOSGeometry* QgsGeometry::exportToGeos( double precision ) const
273272
{
274273
if ( !d->geometry )
275274
{
276275
return nullptr;
277276
}
278277

279-
if ( !d->mGeos )
280-
{
281-
d->mGeos = QgsGeos::asGeos( d->geometry, precision );
282-
}
283-
return d->mGeos;
278+
return QgsGeos::asGeos( d->geometry, precision );
284279
}
285280

286281

@@ -320,7 +315,7 @@ void QgsGeometry::fromGeos( GEOSGeometry *geos )
320315
detach( false );
321316
delete d->geometry;
322317
d->geometry = QgsGeos::fromGeos( geos );
323-
d->mGeos = geos;
318+
GEOSGeom_destroy_r( QgsGeos::getGEOSHandler(), geos );
324319
}
325320

326321
QgsPoint QgsGeometry::closestVertex( const QgsPoint& point, int& atVertex, int& beforeVertex, int& afterVertex, double& sqrDist ) const

src/core/geometry/qgsgeometry.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,12 @@ class CORE_EXPORT QgsGeometry
156156
*/
157157
void fromWkb( const QByteArray& wkb );
158158

159-
/** Returns a geos geometry. QgsGeometry retains ownership of the geometry, so the returned object should not be deleted.
159+
/** Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destroy_r)
160160
* @param precision The precision of the grid to which to snap the geometry vertices. If 0, no snapping is performed.
161-
* @note this method was added in version 1.1
161+
* @note added in 3.0
162162
* @note not available in python bindings
163163
*/
164-
const GEOSGeometry* asGeos( double precision = 0 ) const;
164+
GEOSGeometry* exportToGeos( double precision = 0 ) const;
165165

166166
/** Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
167167
* @see type

src/core/geometry/qgswkbptr.h

+3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class CORE_EXPORT QgsWkbPtr
6666
}
6767

6868
public:
69+
//! Construct WKB pointer from QByteArray
6970
QgsWkbPtr( QByteArray& wkb );
7071
QgsWkbPtr( unsigned char *p, int size );
7172

@@ -82,6 +83,7 @@ class CORE_EXPORT QgsWkbPtr
8283
inline QgsWkbPtr &operator<<( const unsigned int &v ) { write( v ); return *this; }
8384
inline QgsWkbPtr &operator<<( const char &v ) { write( v ); return *this; }
8485
inline QgsWkbPtr &operator<<( const QgsWkbTypes::Type &v ) { write( v ); return *this; }
86+
//! Append data from a byte array
8587
inline QgsWkbPtr &operator<<( const QByteArray &data ) { write( data ); return *this; }
8688

8789
inline void operator+=( int n ) { verifyBound( n ); mP += n; }
@@ -119,6 +121,7 @@ class CORE_EXPORT QgsConstWkbPtr
119121
}
120122

121123
public:
124+
//! Construct WKB pointer from QByteArray
122125
explicit QgsConstWkbPtr( const QByteArray& wkb );
123126
QgsConstWkbPtr( const unsigned char *p, int size );
124127
QgsWkbTypes::Type readHeader() const;

src/core/qgsgeometryvalidator.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ void QgsGeometryValidator::run()
220220
if ( settings.value( QStringLiteral( "/qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 )
221221
{
222222
char *r = nullptr;
223-
const GEOSGeometry *g0 = mG.asGeos();
223+
GEOSGeometry *g0 = mG.exportToGeos();
224224
GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler();
225225
if ( !g0 )
226226
{
@@ -229,7 +229,9 @@ void QgsGeometryValidator::run()
229229
else
230230
{
231231
GEOSGeometry *g1 = nullptr;
232-
if ( GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 ) != 1 )
232+
char res = GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 );
233+
GEOSGeom_destroy_r( handle, g0 );
234+
if ( res != 1 )
233235
{
234236
if ( g1 )
235237
{

src/core/qgslabelfeature.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ QgsLabelFeature::QgsLabelFeature( QgsFeatureId id, GEOSGeometry* geometry, QSize
3535
, mIsObstacle( false )
3636
, mObstacleFactor( 1 )
3737
, mInfo( nullptr )
38+
, mPermissibleZoneGeos( nullptr )
3839
, mPermissibleZoneGeosPrepared( nullptr )
3940
{
4041
}
@@ -48,7 +49,10 @@ QgsLabelFeature::~QgsLabelFeature()
4849
GEOSGeom_destroy_r( QgsGeometry::getGEOSHandler(), mObstacleGeometry );
4950

5051
if ( mPermissibleZoneGeosPrepared )
52+
{
5153
GEOSPreparedGeom_destroy_r( QgsGeometry::getGEOSHandler(), mPermissibleZoneGeosPrepared );
54+
GEOSGeom_destroy_r( QgsGeometry::getGEOSHandler(), mPermissibleZoneGeos );
55+
}
5256

5357
delete mInfo;
5458
}
@@ -68,15 +72,17 @@ void QgsLabelFeature::setPermissibleZone( const QgsGeometry &geometry )
6872
if ( mPermissibleZoneGeosPrepared )
6973
{
7074
GEOSPreparedGeom_destroy_r( QgsGeometry::getGEOSHandler(), mPermissibleZoneGeosPrepared );
75+
GEOSGeom_destroy_r( QgsGeometry::getGEOSHandler(), mPermissibleZoneGeos );
7176
mPermissibleZoneGeosPrepared = nullptr;
77+
mPermissibleZoneGeos = nullptr;
7278
}
7379

7480
if ( mPermissibleZone.isEmpty() )
7581
return;
7682

77-
const GEOSGeometry* zoneGeos = mPermissibleZone.asGeos();
78-
if ( !zoneGeos )
83+
mPermissibleZoneGeos = mPermissibleZone.exportToGeos();
84+
if ( !mPermissibleZoneGeos )
7985
return;
8086

81-
mPermissibleZoneGeosPrepared = GEOSPrepare_r( QgsGeometry::getGEOSHandler(), zoneGeos );
87+
mPermissibleZoneGeosPrepared = GEOSPrepare_r( QgsGeometry::getGEOSHandler(), mPermissibleZoneGeos );
8288
}

src/core/qgslabelfeature.h

+3
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ class CORE_EXPORT QgsLabelFeature
394394

395395
private:
396396

397+
//! GEOS geometry on which mPermissibleZoneGeosPrepared is based on
398+
GEOSGeometry* mPermissibleZoneGeos;
399+
397400
// TODO - not required when QgsGeometry caches geos preparedness
398401
const GEOSPreparedGeometry* mPermissibleZoneGeosPrepared;
399402

src/core/qgspallabeling.cpp

+12-19
Original file line numberDiff line numberDiff line change
@@ -1851,17 +1851,16 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
18511851
geom = QgsGeometry( geom.geometry()->boundary() );
18521852
}
18531853

1854-
const GEOSGeometry* geos_geom = nullptr;
1854+
GEOSGeometry* geos_geom_clone = nullptr;
18551855
if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, ct, doClip ? &extentGeom : nullptr ) )
18561856
{
18571857
geom = QgsPalLabeling::prepareGeometry( geom, context, ct, doClip ? &extentGeom : nullptr );
18581858

18591859
if ( geom.isEmpty() )
18601860
return;
18611861
}
1862-
geos_geom = geom.asGeos();
1862+
geos_geom_clone = geom.exportToGeos();
18631863

1864-
const GEOSGeometry* geosObstacleGeom = nullptr;
18651864
QScopedPointer<QgsGeometry> scopedObstacleGeom;
18661865
if ( isObstacle )
18671866
{
@@ -1870,16 +1869,12 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
18701869
scopedObstacleGeom.reset( new QgsGeometry( QgsPalLabeling::prepareGeometry( *obstacleGeometry, context, ct, doClip ? &extentGeom : nullptr ) ) );
18711870
obstacleGeometry = scopedObstacleGeom.data();
18721871
}
1873-
if ( obstacleGeometry )
1874-
{
1875-
geosObstacleGeom = obstacleGeometry->asGeos();
1876-
}
18771872
}
18781873

18791874
if ( minFeatureSize > 0 && !checkMinimumSizeMM( context, geom, minFeatureSize ) )
18801875
return;
18811876

1882-
if ( !geos_geom )
1877+
if ( !geos_geom_clone )
18831878
return; // invalid geometry
18841879

18851880
// likelihood exists label will be registered with PAL and may be drawn
@@ -1907,11 +1902,10 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
19071902
}
19081903
}
19091904

1910-
GEOSGeometry* geos_geom_clone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );
19111905
GEOSGeometry* geosObstacleGeomClone = nullptr;
1912-
if ( geosObstacleGeom )
1906+
if ( obstacleGeometry )
19131907
{
1914-
geosObstacleGeomClone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geosObstacleGeom );
1908+
geosObstacleGeomClone = obstacleGeometry->exportToGeos();
19151909
}
19161910

19171911

@@ -2384,21 +2378,18 @@ void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, QgsRenderConte
23842378
geom = simplifier.simplify( geom );
23852379
}
23862380

2387-
const GEOSGeometry* geos_geom = nullptr;
2381+
GEOSGeometry* geos_geom_clone = nullptr;
23882382
QScopedPointer<QgsGeometry> scopedPreparedGeom;
23892383

23902384
if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, ct, &extentGeom ) )
23912385
{
23922386
geom = QgsPalLabeling::prepareGeometry( geom, context, ct, &extentGeom );
23932387
}
2394-
geos_geom = geom.asGeos();
2388+
geos_geom_clone = geom.exportToGeos();
23952389

2396-
if ( !geos_geom )
2390+
if ( !geos_geom_clone )
23972391
return; // invalid geometry
23982392

2399-
GEOSGeometry* geos_geom_clone;
2400-
geos_geom_clone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );
2401-
24022393
// feature to the layer
24032394
*obstacleFeature = new QgsLabelFeature( f.id(), geos_geom_clone, QSizeF( 0, 0 ) );
24042395
( *obstacleFeature )->setIsObstacle( true );
@@ -3416,8 +3407,10 @@ QgsGeometry QgsPalLabeling::prepareGeometry( const QgsGeometry& geometry, QgsRen
34163407
}
34173408
}
34183409

3419-
if ( !geom.asGeos() )
3420-
return QgsGeometry(); // there is something really wrong with the geometry
3410+
// MD: exporting geometry to GEOS just to see if the geometry is wrong...?
3411+
// if still needed, we could have a more specific test here
3412+
//if ( !geom.asGeos() )
3413+
// return QgsGeometry(); // there is something really wrong with the geometry
34213414

34223415
// fix invalid polygons
34233416
if ( geom.type() == QgsWkbTypes::PolygonGeometry && !geom.isGeosValid() )

src/core/qgstracer.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,9 @@ bool QgsTracer::initGraph()
533533
{
534534
t2a.start();
535535
// GEOSNode_r may throw an exception
536-
GEOSGeometry* allNoded = GEOSNode_r( QgsGeometry::getGEOSHandler(), allGeom.asGeos() );
536+
GEOSGeometry* allGeomGeos = allGeom.exportToGeos();
537+
GEOSGeometry* allNoded = GEOSNode_r( QgsGeometry::getGEOSHandler(), allGeomGeos );
538+
GEOSGeom_destroy_r( QgsGeometry::getGEOSHandler(), allGeomGeos );
537539
timeNodingCall = t2a.elapsed();
538540

539541
QgsGeometry* noded = new QgsGeometry;

src/core/qgsvectorlayerdiagramprovider.cpp

+7-15
Original file line numberDiff line numberDiff line change
@@ -224,44 +224,36 @@ QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& fea
224224
extentGeom.rotate( -mapSettings.rotation(), mapSettings.visibleExtent().center() );
225225
}
226226

227-
const GEOSGeometry* geos_geom = nullptr;
227+
GEOSGeometry* geomCopy = nullptr;
228228
QScopedPointer<QgsGeometry> scopedPreparedGeom;
229229
if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, mSettings.coordinateTransform(), &extentGeom ) )
230230
{
231231
scopedPreparedGeom.reset( new QgsGeometry( QgsPalLabeling::prepareGeometry( geom, context, mSettings.coordinateTransform(), &extentGeom ) ) );
232232
QgsGeometry* preparedGeom = scopedPreparedGeom.data();
233233
if ( preparedGeom->isEmpty() )
234234
return nullptr;
235-
geos_geom = preparedGeom->asGeos();
235+
geomCopy = preparedGeom->exportToGeos();
236236
}
237237
else
238238
{
239-
geos_geom = geom.asGeos();
239+
geomCopy = geom.exportToGeos();
240240
}
241241

242-
if ( !geos_geom )
242+
if ( !geomCopy )
243243
return nullptr; // invalid geometry
244244

245-
GEOSGeometry* geomCopy = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );
246-
247-
const GEOSGeometry* geosObstacleGeom = nullptr;
245+
GEOSGeometry* geosObstacleGeomClone = nullptr;
248246
QScopedPointer<QgsGeometry> scopedObstacleGeom;
249247
if ( mSettings.isObstacle() && obstacleGeometry && QgsPalLabeling::geometryRequiresPreparation( *obstacleGeometry, context, mSettings.coordinateTransform(), &extentGeom ) )
250248
{
251249
QgsGeometry preparedObstacleGeom = QgsPalLabeling::prepareGeometry( *obstacleGeometry, context, mSettings.coordinateTransform(), &extentGeom );
252-
geosObstacleGeom = preparedObstacleGeom.asGeos();
250+
geosObstacleGeomClone = preparedObstacleGeom.exportToGeos();
253251
}
254252
else if ( mSettings.isObstacle() && obstacleGeometry )
255253
{
256-
geosObstacleGeom = obstacleGeometry->asGeos();
257-
}
258-
GEOSGeometry* geosObstacleGeomClone = nullptr;
259-
if ( geosObstacleGeom )
260-
{
261-
geosObstacleGeomClone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geosObstacleGeom );
254+
geosObstacleGeomClone = obstacleGeometry->exportToGeos();
262255
}
263256

264-
265257
double diagramWidth = 0;
266258
double diagramHeight = 0;
267259
if ( dr )

0 commit comments

Comments
 (0)