Skip to content

Commit e259e62

Browse files
authored
Merge pull request #3349 from nyalldawson/feature_geom
Mega API break - fix QgsFeature geometry getters/setters
2 parents f7a3fd7 + b7ca001 commit e259e62

File tree

285 files changed

+2862
-3106
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

285 files changed

+2862
-3106
lines changed

doc/api_break.dox

+70
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,50 @@ attributeIndexes(), pkAttributeIndexes(), isSaveAndLoadStyleToDBSupported()</li>
224224
</li>
225225
</ul>
226226

227+
\subsection qgis_api_break_3_0_QgsFeature QgsFeature
228+
229+
<ul>
230+
<li>geometryAndOwnership() has been removed. Use geometry() instead.</li>
231+
<li>setGeometryAndOwnership() has been removed. Use setGeometry() instead.</li>
232+
<li>The setGeometry( QgsGeometry* ) method has been removed, use setGeometry( const QgsGeometry& ) instead.</li>
233+
<li>The geometry() method now returns a copy of the geometry, not a pointer. Since QgsGeometry objects are
234+
implicitly shared this is a low-cost copy, and avoids ownership and dangling pointer issues. <b>Very important: Testing that
235+
a feature has a geometry is now done using the new hasGeometry() method. Any code which compares QgsFeature::geometry() to
236+
None will need to be modified, as the method will return an empty geometry if the feature has no geometry.</b></li>
237+
<li>The temporary constGeometry() method has been removed. Use geometry() instead.</li>
238+
<li>setFields( const QgsFields*, bool ) has been removed, use setFields( const QgsFields&, bool ) instead.</li>
239+
</ul>
240+
241+
\subsection qgis_api_break_3_0_QgsGeometry QgsGeometry
242+
243+
<ul>
244+
<li>All QgsGeometry methods now accept geometry references instead of pointers, and return a QgsGeometry
245+
value instead of a pointer. The biggest impact with this change is that PyQGIS code should not compare a geometry
246+
result to None, but instead either use a boolean test (`if g.buffer(10):`) or explicitly use the isEmpty()
247+
method to determine if a geometry is valid.</li>
248+
</ul>
249+
250+
\subsection qgis_api_break_3_0_QgsGeometryAnalyzer QgsGeometryAnalyzer
251+
252+
<ul>
253+
<li>locateBetweenMeasures() and locateAlongMeasure() now take geometry references, not pointers, and return
254+
a QgsGeometry value rather than a pointer.</li>
255+
</ul>
256+
227257
\subsection qgis_api_break_3_0_QgsGroupWMSDataDialog QgsGroupWMSDataDialog
228258

229259
<ul>
230260
<li>QgsGroupWMSDataDialo has been renamed to QgsGroupWmsDataDialog</li>
231261
</ul>
232262

263+
\subsection qgis_api_break_3_0_QgsHighlight QgsHighlight
264+
265+
<ul>
266+
<li>The QgsHighlight constructor now takes a geometry reference, not a pointer.</li>
267+
</ul>
268+
269+
270+
233271
\subsection qgis_api_break_3_0_QgsVectorDataProvider QgsVectorDataProvider
234272

235273
<ul>
@@ -239,6 +277,7 @@ only affects third party c++ providers, and does not affect PyQGIS scripts.</li>
239277
<li>The SaveAsShapefile, SelectGeometryAtId, RandomSelectGeometryAtId and SequentialSelectGeometryAtId
240278
capabilities have been removed, as they were unused and had no effect.</li>
241279
<li>capabilities() now returns a typesafe QgsVectorDataProvider::Capabilities object, not an integer.</li>
280+
<li>convertToProviderType() now takes a geometry reference, not a pointer.</li>
242281
</ul>
243282

244283
\subsection qgis_api_break_3_0_QgsLabelingEngineInterface QgsLabelingEngineInterface
@@ -334,6 +373,7 @@ be returned instead of a null pointer if no transformation is required.</li>
334373

335374
<ul>
336375
<li>init(QgsMapRenderer*) has been removed. Use init(const QgsMapSettings&) instead.</li>
376+
<li>prepareGeometry and geometryRequiresPreparation now take geometry references, not pointers.</li>
337377
</ul>
338378

339379
\subsection qgis_api_break_3_0_QgsOSMElement QgsOSMElement
@@ -396,6 +436,12 @@ be returned instead of a null pointer if no transformation is required.</li>
396436
<li>setCoordinateTransform() now takes a QgsCoordinateTransform reference, not a pointer. An invalid QgsCoordinateTransform should be used instead of a null pointer if no transformation is required.</li>
397437
</ul>
398438

439+
\subsection qgis_api_break_3_0_QgsRubberBand QgsRubberBand
440+
441+
<ul>
442+
<li>setToGeometry() and addGeometry() now take geometry references, not pointers.</li>
443+
</ul>
444+
399445
\subsection qgis_api_break_3_0_QgsPalLayerSettings QgsPalLayerSettings
400446

401447
<ul>
@@ -430,6 +476,23 @@ plugins calling this method will need to be updated.</li>
430476
setExcludeAttributesWms()</li>
431477
<li>excludeAttributesWFS() and setExcludeAttributesWFS() have been renamed to excludeAttributesWfs() and
432478
setExcludeAttributesWfs()</li>
479+
<li>changeGeometry() now accepts a geometry reference, not a pointer.</li>
480+
<li>The geometryChanged() signal now uses a const QgsGeometry reference.</li>
481+
<li>The deprecated removePolygonIntersections has been removed.</li>
482+
<li>addTopologicalPoints() now takes a geometry reference, not a pointer.</li>
483+
</ul>
484+
485+
\subsection qgis_api_break_3_0_QgsVectorLayerEditBuffer QgsVectorLayerEditBuffer
486+
487+
<ul>
488+
<li>changeGeometry() now accepts a geometry reference, not a pointer.</li>
489+
<li>The geometryChanged() signal now uses a const QgsGeometry reference.</li>
490+
</ul>
491+
492+
\subsection qgis_api_break_3_0_QgsVectorLayerEditUtils QgsVectorLayerEditUtils
493+
494+
<ul>
495+
<li>addTopologicalPoints() now accepts a geometry reference, not a pointer.</li>
433496
</ul>
434497

435498
\subsection qgis_api_break_3_0_QgsVectorLayerImport QgsVectorLayerImport
@@ -441,6 +504,13 @@ pointers makes for more robust, safer code. Use an invalid (default constructed)
441504
in code which previously passed a null pointer to QgsVectorLayerImport.</li>
442505
</ul>
443506

507+
\subsection qgis_api_break_3_0_QgsVectorLayerUndoCommand QgsVectorLayerUndoCommand
508+
509+
<ul>
510+
<li>QgsVectorLayerUndoCommandChangeGeometry constructor now accepts a geometry reference, not a pointer.</li>
511+
</ul>
512+
513+
444514
\subsection qgis_api_break_3_0_QgsPointLocator QgsPointLocator
445515

446516
<ul>

python/analysis/vector/qgsgeometryanalyzer.sip

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ class QgsGeometryAnalyzer
9595
bool forceSingleGeometry = false, QgsVectorDataProvider* memoryProvider = 0, QProgressDialog* p = 0 );
9696

9797
/** Returns linear reference geometry as a multiline (or 0 if no match). Currently, the z-coordinates are considered to be the measures (no support for m-values in QGIS)*/
98-
QgsGeometry* locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry* lineGeom );
98+
QgsGeometry locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry& lineGeom );
9999
/** Returns linear reference geometry. Unlike the PostGIS function, this method always returns multipoint or 0 if no match (not geometry collection).
100100
* Currently, the z-coordinates are considered to be the measures (no support for m-values in QGIS)
101101
*/
102-
QgsGeometry* locateAlongMeasure( double measure, const QgsGeometry* lineGeom );
102+
QgsGeometry locateAlongMeasure( double measure, const QgsGeometry& lineGeom );
103103

104104
};

python/core/__init__.py

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@
2929
import string
3030
from qgis._core import *
3131

32+
# Boolean evaluation of QgsGeometry
33+
34+
35+
def _geometryNonZero(self):
36+
return not self.isEmpty()
37+
QgsGeometry.__nonzero__ = _geometryNonZero
38+
QgsGeometry.__bool__ = _geometryNonZero
39+
3240

3341
def register_function(function, arg_count, group, usesgeometry=False, referenced_columns=[QgsFeatureRequest.AllAttributes], **kwargs):
3442
"""

python/core/geometry/qgsgeometry.sip

+48-34
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,21 @@ class QgsGeometry
6565
bool isEmpty() const;
6666

6767
/** Creates a new geometry from a WKT string */
68-
static QgsGeometry* fromWkt( const QString& wkt ) /Factory/;
68+
static QgsGeometry fromWkt( const QString& wkt );
6969
/** Creates a new geometry from a QgsPoint object*/
70-
static QgsGeometry* fromPoint( const QgsPoint& point ) /Factory/;
70+
static QgsGeometry fromPoint( const QgsPoint& point );
7171
/** Creates a new geometry from a QgsMultiPoint object */
72-
static QgsGeometry* fromMultiPoint( const QgsMultiPoint& multipoint ) /Factory/;
72+
static QgsGeometry fromMultiPoint( const QgsMultiPoint& multipoint );
7373
/** Creates a new geometry from a QgsPolyline object */
74-
static QgsGeometry* fromPolyline( const QgsPolyline& polyline ) /Factory/;
74+
static QgsGeometry fromPolyline( const QgsPolyline& polyline );
7575
/** Creates a new geometry from a QgsMultiPolyline object*/
76-
static QgsGeometry* fromMultiPolyline( const QgsMultiPolyline& multiline ) /Factory/;
76+
static QgsGeometry fromMultiPolyline( const QgsMultiPolyline& multiline );
7777
/** Creates a new geometry from a QgsPolygon */
78-
static QgsGeometry* fromPolygon( const QgsPolygon& polygon ) /Factory/;
78+
static QgsGeometry fromPolygon( const QgsPolygon& polygon );
7979
/** Creates a new geometry from a QgsMultiPolygon */
80-
static QgsGeometry* fromMultiPolygon( const QgsMultiPolygon& multipoly ) /Factory/;
80+
static QgsGeometry fromMultiPolygon( const QgsMultiPolygon& multipoly );
8181
/** Creates a new geometry from a QgsRectangle */
82-
static QgsGeometry* fromRect( const QgsRectangle& rect ) /Factory/;
82+
static QgsGeometry fromRect( const QgsRectangle& rect );
8383

8484
/**
8585
* Set the geometry, feeding in a geometry in GEOS format.
@@ -393,49 +393,57 @@ class QgsGeometry
393393
*/
394394
int makeDifference( const QgsGeometry* other );
395395

396+
/** Returns the geometry formed by modifying this geometry such that it does not
397+
* intersect the other geometry.
398+
* @param other geometry that should not be intersect
399+
* @return difference geometry, or empty geometry if difference could not be calculated
400+
* @note added in QGIS 3.0
401+
*/
402+
QgsGeometry makeDifference( const QgsGeometry& other ) const;
403+
396404
/** Returns the bounding box of this feature*/
397405
QgsRectangle boundingBox() const;
398406

399407
/** Test for intersection with a rectangle (uses GEOS) */
400408
bool intersects( const QgsRectangle& r ) const;
401409

402410
/** Test for intersection with a geometry (uses GEOS) */
403-
bool intersects( const QgsGeometry* geometry ) const;
411+
bool intersects( const QgsGeometry& geometry ) const;
404412

405413
/** Test for containment of a point (uses GEOS) */
406414
bool contains( const QgsPoint* p ) const;
407415

408416
/** Test for if geometry is contained in another (uses GEOS)
409417
* @note added in 1.5 */
410-
bool contains( const QgsGeometry* geometry ) const;
418+
bool contains( const QgsGeometry& geometry ) const;
411419

412420
/** Test for if geometry is disjoint of another (uses GEOS)
413421
* @note added in 1.5 */
414-
bool disjoint( const QgsGeometry* geometry ) const;
422+
bool disjoint( const QgsGeometry& geometry ) const;
415423

416424
/** Test for if geometry equals another (uses GEOS)
417425
* @note added in 1.5 */
418-
bool equals( const QgsGeometry* geometry ) const;
426+
bool equals( const QgsGeometry& geometry ) const;
419427

420428
/** Test for if geometry touch another (uses GEOS)
421429
* @note added in 1.5 */
422-
bool touches( const QgsGeometry* geometry ) const;
430+
bool touches( const QgsGeometry& geometry ) const;
423431

424432
/** Test for if geometry overlaps another (uses GEOS)
425433
* @note added in 1.5 */
426-
bool overlaps( const QgsGeometry* geometry ) const;
434+
bool overlaps( const QgsGeometry& geometry ) const;
427435

428436
/** Test for if geometry is within another (uses GEOS)
429437
* @note added in 1.5 */
430-
bool within( const QgsGeometry* geometry ) const;
438+
bool within( const QgsGeometry& geometry ) const;
431439

432440
/** Test for if geometry crosses another (uses GEOS)
433441
* @note added in 1.5 */
434-
bool crosses( const QgsGeometry* geometry ) const;
442+
bool crosses( const QgsGeometry& geometry ) const;
435443

436444
/** Returns a buffer region around this geometry having the given width and with a specified number
437445
of segments used to approximate curves */
438-
QgsGeometry* buffer( double distance, int segments ) const /Factory/;
446+
QgsGeometry buffer( double distance, int segments ) const;
439447

440448
/** Returns a buffer region around the geometry, with additional style options.
441449
* @param distance buffer distance
@@ -446,44 +454,44 @@ class QgsGeometry
446454
* @note added in 2.4
447455
* @note needs GEOS >= 3.3 - otherwise always returns 0
448456
*/
449-
QgsGeometry* buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ) const /Factory/;
457+
QgsGeometry buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ) const;
450458

451459
/** Returns an offset line at a given distance and side from an input line.
452460
* See buffer() method for details on parameters.
453461
* @note added in 2.4
454462
* @note needs GEOS >= 3.3 - otherwise always returns 0
455463
*/
456-
QgsGeometry* offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ) const /Factory/;
464+
QgsGeometry offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ) const;
457465

458466
/** Returns a simplified version of this geometry using a specified tolerance value */
459-
QgsGeometry* simplify( double tolerance ) const /Factory/;
467+
QgsGeometry simplify( double tolerance ) const;
460468

461469
/** Returns the center of mass of a geometry
462470
* @note for line based geometries, the center point of the line is returned,
463471
* and for point based geometries, the point itself is returned
464472
*/
465-
QgsGeometry* centroid() const /Factory/;
473+
QgsGeometry centroid() const;
466474

467475
/** Returns a point within a geometry */
468-
QgsGeometry* pointOnSurface() const /Factory/;
476+
QgsGeometry pointOnSurface() const;
469477

470478
/** Returns the smallest convex polygon that contains all the points in the geometry. */
471-
QgsGeometry* convexHull() const /Factory/;
479+
QgsGeometry convexHull() const;
472480

473481
/**
474482
* Return interpolated point on line at distance
475483
* @note added in 1.9
476484
*/
477-
QgsGeometry* interpolate( double distance ) /Factory/;
485+
QgsGeometry interpolate( double distance );
478486

479487
/** Returns a geometry representing the points shared by this geometry and other. */
480-
QgsGeometry* intersection( const QgsGeometry* geometry ) const /Factory/;
488+
QgsGeometry intersection( const QgsGeometry& geometry ) const;
481489

482490
/** Returns a geometry representing all the points in this geometry and other (a
483491
* union geometry operation).
484492
* @note this operation is not called union since its a reserved word in C++.
485493
*/
486-
QgsGeometry* combine( const QgsGeometry* geometry ) const /Factory/;
494+
QgsGeometry combine( const QgsGeometry& geometry ) const;
487495

488496
/** Merges any connected lines in a LineString/MultiLineString geometry and
489497
* converts them to single line strings.
@@ -495,10 +503,10 @@ class QgsGeometry
495503
QgsGeometry mergeLines() const;
496504

497505
/** Returns a geometry representing the points making up this geometry that do not make up other. */
498-
QgsGeometry* difference( const QgsGeometry* geometry ) const /Factory/;
506+
QgsGeometry difference( const QgsGeometry& geometry ) const;
499507

500508
/** Returns a geometry representing the points making up this geometry that do not make up other. */
501-
QgsGeometry* symDifference( const QgsGeometry* geometry ) const /Factory/;
509+
QgsGeometry symDifference( const QgsGeometry& geometry ) const;
502510

503511
/** Returns an extruded version of this geometry. */
504512
QgsGeometry extrude( double x, double y );
@@ -523,7 +531,7 @@ class QgsGeometry
523531
* @return the converted geometry or nullptr if the conversion fails.
524532
* @note added in 2.2
525533
*/
526-
QgsGeometry* convertToType( Qgis::GeometryType destType, bool destMultipart = false ) const /Factory/;
534+
QgsGeometry convertToType( Qgis::GeometryType destType, bool destMultipart = false ) const;
527535

528536
/* Accessor functions for getting geometry data */
529537

@@ -556,7 +564,7 @@ class QgsGeometry
556564

557565
/** Return contents of the geometry as a list of geometries
558566
@note added in version 1.1 */
559-
QList<QgsGeometry*> asGeometryCollection() const /Factory/;
567+
QList<QgsGeometry> asGeometryCollection() const;
560568

561569
/** Return contents of the geometry as a QPointF if wkbType is WKBPoint,
562570
* otherwise returns a null QPointF.
@@ -635,7 +643,7 @@ class QgsGeometry
635643
* @param geometryList a list of QgsGeometry* as input
636644
* @returns the new computed QgsGeometry, or null
637645
*/
638-
static QgsGeometry *unaryUnion( const QList<QgsGeometry*>& geometryList ) /Factory/;
646+
static QgsGeometry unaryUnion( const QList<QgsGeometry>& geometryList );
639647

640648
/** Converts the geometry to straight line segments, if it is a curved geometry type.
641649
* @note added in QGIS 2.10
@@ -696,15 +704,15 @@ class QgsGeometry
696704
* @param point source QPointF
697705
* @note added in QGIS 2.7
698706
*/
699-
static QgsGeometry* fromQPointF( QPointF point ) /Factory/;
707+
static QgsGeometry fromQPointF( QPointF point );
700708

701709
/** Construct geometry from a QPolygonF. If the polygon is closed than
702710
* the resultant geometry will be a polygon, if it is open than the
703711
* geometry will be a polyline.
704712
* @param polygon source QPolygonF
705713
* @note added in QGIS 2.7
706714
*/
707-
static QgsGeometry* fromQPolygonF( const QPolygonF& polygon ) /Factory/;
715+
static QgsGeometry fromQPolygonF( const QPolygonF& polygon );
708716

709717
/** Creates a QgsPolyline from a QPolygonF.
710718
* @param polygon source polygon
@@ -760,7 +768,7 @@ class QgsGeometry
760768
* of the geometry for each iteration. Smaller values result in "tighter" smoothing.
761769
* @note added in 2.9
762770
*/
763-
QgsGeometry* smooth( const unsigned int iterations, const double offset ) const;
771+
QgsGeometry smooth( const unsigned int iterations, const double offset ) const;
764772

765773
/** Smooths a polygon using the Chaikin algorithm*/
766774
QgsPolygon smoothPolygon( const QgsPolygon &polygon, const unsigned int iterations = 1, const double offset = 0.25 ) const;
@@ -786,5 +794,11 @@ class QgsGeometry
786794
//! Allows direct construction of QVariants from geometry.
787795
operator QVariant() const;
788796

797+
/** Returns true if the geometry is non empty (ie, isEmpty() returns false),
798+
* or false if it is an empty, uninitialised geometry (ie, ieEmpty() returns true).
799+
* @note added in QGIS 3.0
800+
*/
801+
operator bool() const;
802+
789803
}; // class QgsGeometry
790804

0 commit comments

Comments
 (0)