Skip to content

Commit e8c149e

Browse files
volayaalexbruy
authored andcommittedJan 9, 2017
[processing] added ‘invalid feature handling’ option
1 parent 3e80a52 commit e8c149e

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed
 

‎python/plugins/processing/core/ProcessingConfig.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class ProcessingConfig(object):
5252
VECTOR_POLYGON_STYLE = 'VECTOR_POLYGON_STYLE'
5353
SHOW_RECENT_ALGORITHMS = 'SHOW_RECENT_ALGORITHMS'
5454
USE_SELECTED = 'USE_SELECTED'
55+
FILTER_INVALID_GEOMETRIES = 'FILTER_INVALID_GEOMETRIES'
5556
USE_FILENAME_AS_LAYER_NAME = 'USE_FILENAME_AS_LAYER_NAME'
5657
KEEP_DIALOG_OPEN = 'KEEP_DIALOG_OPEN'
5758
SHOW_DEBUG_IN_DIALOG = 'SHOW_DEBUG_IN_DIALOG'
@@ -84,6 +85,14 @@ def initialize():
8485
ProcessingConfig.tr('General'),
8586
ProcessingConfig.USE_SELECTED,
8687
ProcessingConfig.tr('Use only selected features'), True))
88+
invalidFeaturesOptions = [ProcessingConfig.tr('Do not filter (better performance'),
89+
ProcessingConfig.tr('Ignore features with invalid geometries'),
90+
ProcessingConfig.tr('Stop algorithm execution when a geometry is invalid')]
91+
ProcessingConfig.addSetting(Setting(
92+
ProcessingConfig.tr('General'),
93+
ProcessingConfig.FILTER_INVALID_GEOMETRIES,
94+
ProcessingConfig.tr('Invalid features filtering'), invalidFeaturesOptions[2],
95+
valuetype=Setting.SELECTION, options=invalidFeaturesOptions))
8796
ProcessingConfig.addSetting(Setting(
8897
ProcessingConfig.tr('General'),
8998
ProcessingConfig.USE_FILENAME_AS_LAYER_NAME,

‎python/plugins/processing/tools/vector.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from builtins import range
2525
from builtins import object
2626

27+
2728
__author__ = 'Victor Olaya'
2829
__date__ = 'February 2013'
2930
__copyright__ = '(C) 2013, Victor Olaya'
@@ -42,13 +43,14 @@
4243
import psycopg2
4344
from osgeo import ogr
4445

45-
from qgis.PyQt.QtCore import QVariant, QSettings
46+
from qgis.PyQt.QtCore import QVariant, QSettings, QCoreApplication
4647
from qgis.core import (Qgis, QgsFields, QgsField, QgsGeometry, QgsRectangle, QgsWkbTypes,
4748
QgsSpatialIndex, QgsProject, QgsMapLayer, QgsVectorLayer,
4849
QgsVectorFileWriter, QgsDistanceArea, QgsDataSourceUri, QgsCredentials,
4950
QgsFeatureRequest, QgsWkbTypes)
5051

5152
from processing.core.ProcessingConfig import ProcessingConfig
53+
from processing.core.ProcessingLog import ProcessingLog
5254
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
5355
from processing.tools import dataobjects, spatialite, postgis
5456

@@ -95,6 +97,8 @@ def features(layer, request=QgsFeatureRequest()):
9597
"""
9698
class Features(object):
9799

100+
DO_NOT_CHECK, IGNORE, RAISE_EXCEPTION = range(3)
101+
98102
def __init__(self, layer, request):
99103
self.layer = layer
100104
self.selection = False
@@ -104,6 +108,27 @@ def __init__(self, layer, request):
104108
self.selection = True
105109
else:
106110
self.iter = layer.getFeatures(request)
111+
112+
invalidFeaturesMethod = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
113+
114+
def filterFeature(f, ignoreInvalid):
115+
geom = f.geometry()
116+
if geom is None:
117+
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
118+
self.tr('Feature with NULL geometry found.'))
119+
elif not geom.isGeosValid():
120+
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
121+
self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
122+
if ignoreInvalid:
123+
return False
124+
else:
125+
raise GeoAlgorithmExecutionException(self.tr('Features with invalid geometries found. Please fix these errors or specify the "Ignore invalid input features" flag'))
126+
return True
127+
128+
if invalidFeaturesMethod == self.IGNORE:
129+
self.iter = filter(filterFeature, self.iter, True)
130+
elif invalidFeaturesMethod == self.RAISE_EXCEPTION:
131+
self.iter = filter(filterFeature, self.iter, False)
107132

108133
def __iter__(self):
109134
return self.iter
@@ -113,6 +138,10 @@ def __len__(self):
113138
return int(self.layer.selectedFeatureCount())
114139
else:
115140
return int(self.layer.featureCount())
141+
142+
def tr(self, string):
143+
return QCoreApplication.translate("FeatureIterator", string)
144+
116145

117146
return Features(layer, request)
118147

0 commit comments

Comments
 (0)
Please sign in to comment.