Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add __nonzero__ and __bool__ methods to QgsGeometry
  • Loading branch information
nyalldawson committed Aug 1, 2016
1 parent d075b12 commit b7ca001
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 14 deletions.
8 changes: 5 additions & 3 deletions doc/api_break.dox
Expand Up @@ -220,8 +220,8 @@ attributeIndexes(), pkAttributeIndexes(), isSaveAndLoadStyleToDBSupported()</li>
<li>The setGeometry( QgsGeometry* ) method has been removed, use setGeometry( const QgsGeometry& ) instead.</li>
<li>The geometry() method now returns a copy of the geometry, not a pointer. Since QgsGeometry objects are
implicitly shared this is a low-cost copy, and avoids ownership and dangling pointer issues. <b>Very important: Testing that
a feature has a geometry is now done using the new hasGeometry() method. QgsFeature::geometry() will ALWAYS return
true, as the method will return an empty geometry if the feature has no geometry.</b></li>
a feature has a geometry is now done using the new hasGeometry() method. Any code which compares QgsFeature::geometry() to
None will need to be modified, as the method will return an empty geometry if the feature has no geometry.</b></li>
<li>The temporary constGeometry() method has been removed. Use geometry() instead.</li>
<li>setFields( const QgsFields*, bool ) has been removed, use setFields( const QgsFields&, bool ) instead.</li>
</ul>
Expand All @@ -230,7 +230,9 @@ true, as the method will return an empty geometry if the feature has no geometry

<ul>
<li>All QgsGeometry methods now accept geometry references instead of pointers, and return a QgsGeometry
value instead of a pointer.</li>
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()
method to determine if a geometry is valid.</li>
</ul>

\subsection qgis_api_break_3_0_QgsGeometryAnalyzer QgsGeometryAnalyzer
Expand Down
8 changes: 8 additions & 0 deletions python/core/__init__.py
Expand Up @@ -29,6 +29,14 @@
import string
from qgis._core import *

# Boolean evaluation of QgsGeometry


def _geometryNonZero(self):
return not self.isEmpty()
QgsGeometry.__nonzero__ = _geometryNonZero
QgsGeometry.__bool__ = _geometryNonZero


def register_function(function, arg_count, group, usesgeometry=False, referenced_columns=[QgsFeatureRequest.AllAttributes], **kwargs):
"""
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/Eliminate.py
Expand Up @@ -258,7 +258,7 @@ def processAlgorithm(self, progress):
# We have a candidate
iGeom = geom2Eliminate.intersection(selGeom)

if iGeom is None:
if not iGeom:
continue

if boundary:
Expand Down
Expand Up @@ -68,7 +68,7 @@ def processAlgorithm(self, progress):
outGeom = None
if not inGeom.isEmpty():
reversedLine = inGeom.geometry().reversed()
if reversedLine is None:
if not reversedLine:
raise GeoAlgorithmExecutionException(
self.tr('Error reversing line'))
outGeom = QgsGeometry(reversedLine)
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/Smooth.py
Expand Up @@ -75,7 +75,7 @@ def processAlgorithm(self, progress):
attrs = inFeat.attributes()

outGeom = inGeom.smooth(iterations, offset)
if outGeom is None:
if not outGeom:
raise GeoAlgorithmExecutionException(
self.tr('Error smoothing geometry'))

Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/Union.py
Expand Up @@ -117,7 +117,7 @@ def processAlgorithm(self, progress):
int_geom = geom.intersection(tmpGeom)
lstIntersectingB.append(tmpGeom)

if int_geom is None:
if not int_geom:
# There was a problem creating the intersection
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
Expand Down
8 changes: 4 additions & 4 deletions tests/src/gui/testqgsrubberband.cpp
Expand Up @@ -123,8 +123,8 @@ void TestQgsRubberband::testBoundingRect()

// Polygon extent is 10,10 to 30,30
QgsGeometry geom( QgsGeometry::fromWkt(
"POLYGON((10 10,10 30,30 30,30 10,10 10))"
) );
"POLYGON((10 10,10 30,30 30,30 10,10 10))"
) );
mRubberband = new QgsRubberBand( mCanvas, mPolygonLayer->geometryType() );
mRubberband->setIconSize( 5 ); // default, but better be explicit
mRubberband->setWidth( 1 ); // default, but better be explicit
Expand Down Expand Up @@ -173,8 +173,8 @@ void TestQgsRubberband::testVisibility()

// Check visibility after setting to valid geometry
QgsGeometry geom( QgsGeometry::fromWkt(
"POLYGON((10 10,10 30,30 30,30 10,10 10))"
) );
"POLYGON((10 10,10 30,30 30,30 10,10 10))"
) );
mRubberband->setToGeometry( geom, mPolygonLayer );
QCOMPARE( mRubberband->isVisible(), true );

Expand Down
16 changes: 13 additions & 3 deletions tests/src/python/test_qgsgeometry.py
Expand Up @@ -58,6 +58,16 @@

class TestQgsGeometry(unittest.TestCase):

def testBool(self):
""" Test boolean evaluation of QgsGeometry """
g = QgsGeometry()
self.assertFalse(g)
myWKT = 'Point (10 10)'
g = QgsGeometry.fromWkt(myWKT)
self.assertTrue(g)
g.setGeometry(None)
self.assertFalse(g)

def testWktPointLoading(self):
myWKT = 'Point (10 10)'
myGeometry = QgsGeometry.fromWkt(myWKT)
Expand Down Expand Up @@ -1516,7 +1526,7 @@ def testConvertToType(self):
######## TO LINE ########
# POINT TO LINE
point = QgsGeometry.fromPoint(QgsPoint(1, 1))
assert point.convertToType(Qgis.Line, False) is None, "convertToType with a point should return a null geometry"
self.assertFalse(point.convertToType(Qgis.Line, False)), "convertToType with a point should return a null geometry"
# MultiPoint TO LINE
multipoint = QgsGeometry.fromMultiPoint(points[0][0])
wkt = multipoint.convertToType(Qgis.Line, False).exportToWkt()
Expand Down Expand Up @@ -1581,10 +1591,10 @@ def testConvertToType(self):
assert compareWkt(expWkt, wkt), "convertToType failed: from line to polygon. Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)
# LINE ( 3 vertices, with first = last ) TO Polygon
line = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(0, 0), QgsPoint(1, 1)])
assert line.convertToType(Qgis.Polygon, False) is None, "convertToType to polygon of a 3 vertices lines with first and last vertex identical should return a null geometry"
self.assertFalse(line.convertToType(Qgis.Polygon, False), "convertToType to polygon of a 3 vertices lines with first and last vertex identical should return a null geometry")
# MULTILINE ( with a part of 3 vertices, with first = last ) TO MultiPolygon
multiline = QgsGeometry.fromMultiPolyline([points[0][0], [QgsPoint(1, 1), QgsPoint(0, 0), QgsPoint(1, 1)]])
assert multiline.convertToType(Qgis.Polygon, True) is None, "convertToType to polygon of a 3 vertices lines with first and last vertex identical should return a null geometry"
self.assertFalse(multiline.convertToType(Qgis.Polygon, True), "convertToType to polygon of a 3 vertices lines with first and last vertex identical should return a null geometry")
# LINE TO MultiPolygon
line = QgsGeometry.fromPolyline(points[0][0])
wkt = line.convertToType(Qgis.Polygon, True).exportToWkt()
Expand Down

0 comments on commit b7ca001

Please sign in to comment.