Skip to content
Permalink
Browse files

Merge pull request #4078 from nyalldawson/geom_api

API changes to QgsGeometry::isEmpty()/isNull()
  • Loading branch information
nyalldawson committed Jan 30, 2017
2 parents c4165e4 + afcb75a commit 8709e1f9d5e1ba4fa2c5b2a6bdc19e1248c4c3f5
Showing with 368 additions and 290 deletions.
  1. +4 −1 doc/api_break.dox
  2. +1 −1 python/core/geometry/qgsabstractgeometry.sip
  3. +1 −0 python/core/geometry/qgscircularstring.sip
  4. +2 −0 python/core/geometry/qgscompoundcurve.sip
  5. +1 −0 python/core/geometry/qgscurvepolygon.sip
  6. +3 −11 python/core/geometry/qgsgeometry.sip
  7. +1 −0 python/core/geometry/qgsgeometrycollection.sip
  8. +1 −1 python/core/geometry/qgslinestring.sip
  9. +1 −0 python/core/geometry/qgspointv2.sip
  10. +1 −1 python/plugins/processing/algs/qgis/CheckValidity.py
  11. +1 −1 python/plugins/processing/algs/qgis/Delaunay.py
  12. +2 −2 python/plugins/processing/algs/qgis/Dissolve.py
  13. +1 −1 python/plugins/processing/algs/qgis/HypsometricCurves.py
  14. +1 −1 python/plugins/processing/algs/qgis/Intersection.py
  15. +1 −1 python/plugins/processing/algs/qgis/PolygonCentroids.py
  16. +1 −1 python/plugins/processing/algs/qgis/ReverseLineDirection.py
  17. +1 −1 python/plugins/processing/algs/qgis/SplitWithLines.py
  18. +1 −1 python/plugins/processing/tests/AlgorithmsTestBase.py
  19. +1 −1 src/analysis/interpolation/qgsinterpolator.cpp
  20. +1 −1 src/analysis/interpolation/qgstininterpolator.cpp
  21. +1 −1 src/analysis/openstreetmap/qgsosmdatabase.cpp
  22. +1 −1 src/analysis/raster/qgskde.cpp
  23. +10 −10 src/analysis/vector/qgsgeometryanalyzer.cpp
  24. +1 −1 src/analysis/vector/qgsgeometrysnapper.cpp
  25. +9 −9 src/analysis/vector/qgstransectsample.cpp
  26. +2 −2 src/analysis/vector/qgszonalstatistics.cpp
  27. +2 −2 src/app/dwg/qgsdwgimporter.cpp
  28. +1 −1 src/app/nodetool/qgsmaptoolnodetool.cpp
  29. +5 −5 src/app/qgisapp.cpp
  30. +1 −1 src/app/qgsclipboard.cpp
  31. +1 −1 src/app/qgsmaptooladdfeature.cpp
  32. +1 −1 src/app/qgsmaptooladdpart.cpp
  33. +1 −1 src/app/qgsmaptooldeletepart.cpp
  34. +1 −1 src/app/qgsmaptooldeletering.cpp
  35. +1 −1 src/app/qgsmaptoollabel.cpp
  36. +1 −1 src/app/qgsmaptoolmovefeature.cpp
  37. +6 −6 src/app/qgsmaptooloffsetcurve.cpp
  38. +2 −2 src/app/qgsmaptoolreshape.cpp
  39. +1 −1 src/app/qgsmaptoolrotatefeature.cpp
  40. +2 −2 src/app/qgsmaptoolsimplify.cpp
  41. +1 −1 src/app/qgsselectbyformdialog.cpp
  42. +1 −1 src/core/composer/qgscomposermapgrid.cpp
  43. +1 −1 src/core/geometry/qgsabstractgeometry.h
  44. +5 −0 src/core/geometry/qgscircularstring.cpp
  45. +1 −0 src/core/geometry/qgscircularstring.h
  46. +13 −0 src/core/geometry/qgscompoundcurve.cpp
  47. +1 −0 src/core/geometry/qgscompoundcurve.h
  48. +8 −0 src/core/geometry/qgscurvepolygon.cpp
  49. +1 −0 src/core/geometry/qgscurvepolygon.h
  50. +27 −28 src/core/geometry/qgsgeometry.cpp
  51. +13 −9 src/core/geometry/qgsgeometry.h
  52. +13 −0 src/core/geometry/qgsgeometrycollection.cpp
  53. +1 −0 src/core/geometry/qgsgeometrycollection.h
  54. +2 −2 src/core/geometry/qgsgeos.cpp
  55. +5 −0 src/core/geometry/qgslinestring.cpp
  56. +1 −0 src/core/geometry/qgslinestring.h
  57. +1 −0 src/core/geometry/qgspointv2.h
  58. +1 −1 src/core/layertree/qgslayertreemodel.cpp
  59. +3 −3 src/core/qgsdistancearea.cpp
  60. +56 −56 src/core/qgsexpression.cpp
  61. +1 −1 src/core/qgsfeature.cpp
  62. +1 −1 src/core/qgsgml.cpp
  63. +1 −1 src/core/qgsjsonutils.cpp
  64. +1 −1 src/core/qgslabelfeature.cpp
  65. +4 −4 src/core/qgsmaphittest.cpp
  66. +1 −1 src/core/qgsmaptopixelgeometrysimplifier.cpp
  67. +1 −1 src/core/qgsogcutils.cpp
  68. +7 −7 src/core/qgspallabeling.cpp
  69. +1 −1 src/core/qgsvectordataprovider.cpp
  70. +1 −1 src/core/qgsvectorlayer.cpp
  71. +1 −1 src/core/qgsvectorlayerdiagramprovider.cpp
  72. +2 −2 src/core/qgsvectorlayereditutils.cpp
  73. +1 −1 src/core/qgsvectorlayerundocommand.cpp
  74. +1 −1 src/core/symbology-ng/qgsellipsesymbollayer.cpp
  75. +1 −1 src/core/symbology-ng/qgsinvertedpolygonrenderer.cpp
  76. +1 −1 src/core/symbology-ng/qgssymbol.cpp
  77. +4 −4 src/core/symbology-ng/qgssymbollayerutils.cpp
  78. +1 −1 src/gui/qgsexpressionselectiondialog.cpp
  79. +2 −2 src/gui/qgshighlight.cpp
  80. +1 −1 src/gui/qgsmapcanvas.cpp
  81. +1 −1 src/gui/qgsmapcanvassnapper.cpp
  82. +2 −2 src/gui/qgsrubberband.cpp
  83. +1 −1 src/plugins/spatialquery/qgsspatialquery.cpp
  84. +3 −3 src/plugins/topology/checkDock.cpp
  85. +2 −2 src/plugins/topology/topolError.cpp
  86. +14 −14 src/plugins/topology/topolTest.cpp
  87. +3 −3 src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp
  88. +1 −1 src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
  89. +1 −1 src/providers/grass/qgis.v.in.cpp
  90. +1 −1 src/providers/mssql/qgsmssqlprovider.cpp
  91. +1 −1 src/providers/postgres/qgspostgresprovider.cpp
  92. +1 −1 src/providers/virtual/qgsvirtuallayersqlitemodule.cpp
  93. +3 −3 src/providers/wfs/qgswfsfeatureiterator.cpp
  94. +2 −2 src/providers/wfs/qgswfsprovider.cpp
  95. +2 −2 src/providers/wfs/qgswfsshareddata.cpp
  96. +1 −1 src/providers/wfs/qgswfsutils.cpp
  97. +1 −1 src/server/services/wfs/qgswfsgetfeature.cpp
  98. +3 −3 src/server/services/wms/qgswmsrenderer.cpp
  99. +3 −3 tests/src/app/testqgisappclipboard.cpp
  100. +1 −1 tests/src/core/testqgsfeature.cpp
  101. +23 −11 tests/src/core/testqgsgeometry.cpp
  102. +1 −1 tests/src/core/testqgsmaptopixelgeometrysimplifier.cpp
  103. +5 −5 tests/src/core/testqgsogrutils.cpp
  104. +1 −1 tests/src/python/test_qgsdelimitedtextprovider.py
  105. +21 −9 tests/src/python/test_qgsgeometry.py
  106. +3 −3 tests/src/python/test_qgsjsonutils.py
  107. +1 −1 tests/src/python/test_qgssymbol.py
@@ -1044,8 +1044,10 @@ QgsGeometry {#qgis_api_break_3_0_QgsGeometry}

- All QgsGeometry methods now accept geometry references instead of pointers, and return a QgsGeometry
value instead of a pointer. The biggest impact with this change is that PyQGIS code should not compare a geometry
result to None, but instead either use a boolean test (`if g.buffer(10):`) or explicitly use the isEmpty()
result to None, but instead either use a boolean test (`if g.buffer(10):`) or explicitly use the isNull()
method to determine if a geometry is valid.
- isEmpty() was renamed to isNull() to differentiate a missing geometry from a geometry which is empty (eg an
empty geometry collection)
- wkbSize() and asWkb() has been replaced by exportToWkb(). WKB representation is no longer cached within QgsGeometry
- asGeos() has been replaced by exportToGeos(). GEOS representation is no longer cached within QgsGeometry
- int addPart( const QList<QgsPoint> &points, QgsWkbTypes::GeometryType geomType ) has been renamed to addPoints
@@ -1055,6 +1057,7 @@ method to determine if a geometry is valid.
- static bool compare( const QgsMultiPolygon& p1, const QgsMultiPolygon& p2, double epsilon ) has been renamed to compareMultiPolygons
- smoothLine and smoothPolygon are no longer public API (use smooth() instead)
- avoidIntersections() got an extra argument: list of layers to include in the operation (previously read from active QgsProject)
- isGeosEmpty() was removed. Use isEmpty() instead.


QgsGeometryAnalyzer {#qgis_api_break_3_0_QgsGeometryAnalyzer}
@@ -311,7 +311,7 @@ class QgsAbstractGeometry

/** Returns true if the geometry is empty
*/
bool isEmpty() const;
virtual bool isEmpty() const;

/** Returns true if the geometry contains curved segments
*/
@@ -25,6 +25,7 @@ class QgsCircularString: public QgsCurve
QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const;
QString asJSON( int precision = 17 ) const;

bool isEmpty() const;
int numPoints() const;

/** Returns the point at index i within the circular string.
@@ -33,6 +33,8 @@ class QgsCompoundCurve: public QgsCurve
virtual QgsPointV2 endPoint() const;
virtual void points( QList<QgsPointV2>& pts ) const;
virtual int numPoints() const;
bool isEmpty() const;

/** Returns a new line string geometry corresponding to a segmentized approximation
* of the curve.
* @param tolerance segmentation tolerance
@@ -83,6 +83,7 @@ class QgsCurvePolygon: public QgsSurface

virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
virtual int nCoordinates() const;
bool isEmpty() const;
double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const;
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const;

@@ -57,12 +57,7 @@ class QgsGeometry
*/
void setGeometry( QgsAbstractGeometry* geometry /Transfer/ );

/** Returns true if the geometry is empty (ie, contains no underlying geometry
* accessible via @link geometry @endlink).
* @see geometry
* @note added in QGIS 2.10
*/
bool isEmpty() const;
bool isNull() const;

/** Creates a new geometry from a WKT string */
static QgsGeometry fromWkt( const QString& wkt );
@@ -120,6 +115,8 @@ class QgsGeometry
*/
QgsWkbTypes::GeometryType type() const;

bool isEmpty() const;

/** Returns true if WKB of the geometry is of WKBMulti* type */
bool isMultipart() const;

@@ -133,11 +130,6 @@ class QgsGeometry
*/
bool isGeosValid() const;

/** Check if the geometry is empty using GEOS
@note added in 1.5
*/
bool isGeosEmpty() const;

/** Returns the area of the geometry using GEOS
@note added in 1.5
*/
@@ -27,6 +27,7 @@ class QgsGeometryCollection: public QgsAbstractGeometry
QgsAbstractGeometry* geometryN( int n );

//methods inherited from QgsAbstractGeometry
bool isEmpty() const;
virtual int dimension() const;
virtual QString geometryType() const;
virtual void clear();
@@ -106,7 +106,7 @@ class QgsLineString: public QgsCurve
virtual int dimension() const;
virtual QgsLineString* clone() const /Factory/;
virtual void clear();

bool isEmpty() const;
virtual bool fromWkb( QgsConstWkbPtr& wkb );
virtual bool fromWkt( const QString& wkt );

@@ -245,6 +245,7 @@ class QgsPointV2: public QgsAbstractGeometry
virtual int dimension() const;
virtual QgsPointV2* clone() const /Factory/;
void clear();
bool isEmpty() const;
virtual bool fromWkb( QgsConstWkbPtr& wkb );
virtual bool fromWkt( const QString& wkt );
QByteArray asWkb() const;
@@ -137,7 +137,7 @@ def doCheck(self, feedback):
attrs = inFeat.attributes()

valid = True
if not geom.isEmpty() and not geom.isGeosEmpty():
if not geom.isNull() and not geom.isEmpty():
errors = list(geom.validateGeometry())
if errors:
# QGIS method return a summary at the end
@@ -82,7 +82,7 @@ def processAlgorithm(self, feedback):
total = 100.0 / len(features)
for current, inFeat in enumerate(features):
geom = QgsGeometry(inFeat.geometry())
if geom.isEmpty():
if geom.isNull():
continue
if geom.isMultipart():
points = geom.asMultiPoint()
@@ -93,7 +93,7 @@ def processAlgorithm(self, feedback):
first = False

tmpInGeom = inFeat.geometry()
if tmpInGeom.isEmpty() or tmpInGeom.isGeosEmpty():
if tmpInGeom.isNull() or tmpInGeom.isEmpty():
continue

errors = tmpInGeom.validateGeometry()
@@ -137,7 +137,7 @@ def processAlgorithm(self, feedback):
index_attrs = tuple([attrs[i] for i in field_indexes])

tmpInGeom = QgsGeometry(inFeat.geometry())
if tmpInGeom.isGeosEmpty():
if tmpInGeom and tmpInGeom.isEmpty():
continue
errors = tmpInGeom.validateGeometry()
if len(errors) != 0:
@@ -105,7 +105,7 @@ def processAlgorithm(self, feedback):
geom = f.geometry()
intersectedGeom = rasterGeom.intersection(geom)

if intersectedGeom.isGeosEmpty():
if intersectedGeom.isEmpty():
feedback.pushInfo(
self.tr('Feature %d does not intersect raster or '
'entirely located in NODATA area' % f.id()))
@@ -107,7 +107,7 @@ def processAlgorithm(self, feedback):
if int_com:
int_sym = geom.symDifference(tmpGeom)
int_geom = QgsGeometry(int_com.difference(int_sym))
if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
if int_geom.isEmpty() or not int_geom.isGeosValid():
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('GEOS geoprocessing error: One or '
'more input features have invalid '
@@ -80,7 +80,7 @@ def processAlgorithm(self, feedback):
inGeom = feat.geometry()
attrs = feat.attributes()

if inGeom.isEmpty():
if inGeom.isNull():
outGeom = QgsGeometry(None)
else:
outGeom = QgsGeometry(inGeom.centroid())
@@ -65,7 +65,7 @@ def processAlgorithm(self, feedback):
attrs = inFeat.attributes()

outGeom = None
if not inGeom.isEmpty():
if not inGeom.isNull():
reversedLine = inGeom.geometry().reversed()
if not reversedLine:
raise GeoAlgorithmExecutionException(
@@ -127,7 +127,7 @@ def processAlgorithm(self, feedback):
while len(inGeoms) > 0:
inGeom = inGeoms.pop()

if inGeom.isEmpty(): # this has been encountered and created a run-time error
if inGeom.isNull(): # this has been encountered and created a run-time error
continue

if split_geom_engine.intersects(inGeom.geometry()):
@@ -255,7 +255,7 @@ def check_results(self, results, params, expected):
data = file.read()

for rule in expected_result.get('rules', []):
self.assertRegexpMatches(data, rule)
self.assertRegex(data, rule)


if __name__ == '__main__':
@@ -105,7 +105,7 @@ int QgsInterpolator::cacheBaseData()

int QgsInterpolator::addVerticesToCache( const QgsGeometry& geom, bool zCoord, double attributeValue )
{
if ( geom.isEmpty() )
if ( geom.isNull() )
return 1;

bool hasZValue = false;
@@ -175,7 +175,7 @@ int QgsTINInterpolator::insertData( QgsFeature* f, bool zCoord, int attr, InputT

QgsGeometry g = f->geometry();
{
if ( g.isEmpty() )
if ( g.isNull() )
{
return 2;
}
@@ -504,7 +504,7 @@ void QgsOSMDatabase::exportSpatiaLiteWays( bool closed, const QString& tableName
sqlite3_bind_null( stmtInsert, ++col );
}

if ( !geom.isEmpty() )
if ( !geom.isNull() )
{
QByteArray wkb( geom.exportToWkb() );
sqlite3_bind_blob( stmtInsert, ++col, wkb.constData(), wkb.length(), SQLITE_STATIC );
@@ -110,7 +110,7 @@ QgsKernelDensityEstimation::Result QgsKernelDensityEstimation::prepare()
QgsKernelDensityEstimation::Result QgsKernelDensityEstimation::addFeature( const QgsFeature& feature )
{
QgsGeometry featureGeometry = feature.geometry();
if ( featureGeometry.isEmpty() )
if ( featureGeometry.isNull() )
{
return Success;
}
@@ -475,7 +475,7 @@ bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shap
++jt;
}
QList<double> values;
if ( dissolveGeometry.isEmpty() )
if ( dissolveGeometry.isNull() )
{
QgsDebugMsg( "no dissolved geometry - should not happen" );
return false;
@@ -520,7 +520,7 @@ bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shap
++jt;
}
QList<double> values;
if ( dissolveGeometry.isEmpty() )
if ( dissolveGeometry.isNull() )
{
QgsDebugMsg( "no dissolved geometry - should not happen" );
return false;
@@ -705,7 +705,7 @@ QgsGeometry QgsGeometryAnalyzer::dissolveFeature( const QgsFeature& f, const Qgs

QgsGeometry featureGeometry = f.geometry();

if ( dissolveInto.isEmpty() )
if ( dissolveInto.isNull() )
{
return featureGeometry;
}
@@ -810,7 +810,7 @@ bool QgsGeometryAnalyzer::buffer( QgsVectorLayer* layer, const QString& shapefil
if ( dissolve )
{
QgsFeature dissolveFeature;
if ( dissolveGeometry.isEmpty() )
if ( dissolveGeometry.isNull() )
{
QgsDebugMsg( "no dissolved geometry - should not happen" );
return false;
@@ -967,7 +967,7 @@ bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer*
lrsGeom = locateBetweenMeasures( measure1, measure2, featureIdIt->geometry() );
}

if ( !lrsGeom.isEmpty() )
if ( !lrsGeom.isNull() )
{
++nOutputFeatures;
addEventLayerFeature( fet, lrsGeom, featureIdIt->geometry(), fileWriter, memoryProviderFeatures, offsetField, offsetScale, forceSingleGeometry );
@@ -995,7 +995,7 @@ bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer*
void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, const QgsGeometry& geom, const QgsGeometry& lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures,
int offsetField, double offsetScale, bool forceSingleType )
{
if ( geom.isEmpty() )
if ( geom.isNull() )
{
return;
}
@@ -1020,7 +1020,7 @@ void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, const QgsGe
double offsetVal = feature.attribute( offsetField ).toDouble();
offsetVal *= offsetScale;
newGeom = createOffsetGeometry( *geomIt, lineGeom, offsetVal );
if ( newGeom.isEmpty() )
if ( newGeom.isNull() )
{
continue;
}
@@ -1040,7 +1040,7 @@ void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, const QgsGe

QgsGeometry QgsGeometryAnalyzer::createOffsetGeometry( const QgsGeometry& geom, const QgsGeometry& lineGeom, double offset )
{
if ( !geom || lineGeom.isEmpty() )
if ( !geom || lineGeom.isNull() )
{
return QgsGeometry();
}
@@ -1147,7 +1147,7 @@ QgsPoint QgsGeometryAnalyzer::createPointOffset( double x, double y, double dist

QgsGeometry QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry& lineGeom )
{
if ( lineGeom.isEmpty() )
if ( lineGeom.isNull() )
{
return QgsGeometry();
}
@@ -1189,7 +1189,7 @@ QgsGeometry QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, doub

QgsGeometry QgsGeometryAnalyzer::locateAlongMeasure( double measure, const QgsGeometry& lineGeom )
{
if ( lineGeom.isEmpty() )
if ( lineGeom.isNull() )
{
return QgsGeometry();
}
@@ -475,7 +475,7 @@ QgsFeatureList QgsGeometrySnapper::snapFeatures( const QgsFeatureList& features,

void QgsGeometrySnapper::processFeature( QgsFeature& feature, double snapTolerance, SnapMode mode )
{
if ( !feature.geometry().isEmpty() )
if ( !feature.geometry().isNull() )
feature.setGeometry( snapGeometry( feature.geometry(), snapTolerance, mode ) );
}

0 comments on commit 8709e1f

Please sign in to comment.
You can’t perform that action at this time.