Skip to content

Commit

Permalink
[processing] added ‘invalid feature handling’ option
Browse files Browse the repository at this point in the history
  • Loading branch information
volaya authored and alexbruy committed Jan 9, 2017
1 parent 3e80a52 commit e8c149e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
9 changes: 9 additions & 0 deletions python/plugins/processing/core/ProcessingConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class ProcessingConfig(object):
VECTOR_POLYGON_STYLE = 'VECTOR_POLYGON_STYLE'
SHOW_RECENT_ALGORITHMS = 'SHOW_RECENT_ALGORITHMS'
USE_SELECTED = 'USE_SELECTED'
FILTER_INVALID_GEOMETRIES = 'FILTER_INVALID_GEOMETRIES'
USE_FILENAME_AS_LAYER_NAME = 'USE_FILENAME_AS_LAYER_NAME'
KEEP_DIALOG_OPEN = 'KEEP_DIALOG_OPEN'
SHOW_DEBUG_IN_DIALOG = 'SHOW_DEBUG_IN_DIALOG'
Expand Down Expand Up @@ -84,6 +85,14 @@ def initialize():
ProcessingConfig.tr('General'),
ProcessingConfig.USE_SELECTED,
ProcessingConfig.tr('Use only selected features'), True))
invalidFeaturesOptions = [ProcessingConfig.tr('Do not filter (better performance'),
ProcessingConfig.tr('Ignore features with invalid geometries'),
ProcessingConfig.tr('Stop algorithm execution when a geometry is invalid')]
ProcessingConfig.addSetting(Setting(
ProcessingConfig.tr('General'),
ProcessingConfig.FILTER_INVALID_GEOMETRIES,
ProcessingConfig.tr('Invalid features filtering'), invalidFeaturesOptions[2],
valuetype=Setting.SELECTION, options=invalidFeaturesOptions))
ProcessingConfig.addSetting(Setting(
ProcessingConfig.tr('General'),
ProcessingConfig.USE_FILENAME_AS_LAYER_NAME,
Expand Down
31 changes: 30 additions & 1 deletion python/plugins/processing/tools/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from builtins import range
from builtins import object


__author__ = 'Victor Olaya'
__date__ = 'February 2013'
__copyright__ = '(C) 2013, Victor Olaya'
Expand All @@ -42,13 +43,14 @@
import psycopg2
from osgeo import ogr

from qgis.PyQt.QtCore import QVariant, QSettings
from qgis.PyQt.QtCore import QVariant, QSettings, QCoreApplication
from qgis.core import (Qgis, QgsFields, QgsField, QgsGeometry, QgsRectangle, QgsWkbTypes,
QgsSpatialIndex, QgsProject, QgsMapLayer, QgsVectorLayer,
QgsVectorFileWriter, QgsDistanceArea, QgsDataSourceUri, QgsCredentials,
QgsFeatureRequest, QgsWkbTypes)

from processing.core.ProcessingConfig import ProcessingConfig
from processing.core.ProcessingLog import ProcessingLog
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.tools import dataobjects, spatialite, postgis

Expand Down Expand Up @@ -95,6 +97,8 @@ def features(layer, request=QgsFeatureRequest()):
"""
class Features(object):

DO_NOT_CHECK, IGNORE, RAISE_EXCEPTION = range(3)

def __init__(self, layer, request):
self.layer = layer
self.selection = False
Expand All @@ -104,6 +108,27 @@ def __init__(self, layer, request):
self.selection = True
else:
self.iter = layer.getFeatures(request)

invalidFeaturesMethod = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)

def filterFeature(f, ignoreInvalid):
geom = f.geometry()
if geom is None:
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
self.tr('Feature with NULL geometry found.'))
elif not geom.isGeosValid():
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
if ignoreInvalid:
return False
else:
raise GeoAlgorithmExecutionException(self.tr('Features with invalid geometries found. Please fix these errors or specify the "Ignore invalid input features" flag'))
return True

if invalidFeaturesMethod == self.IGNORE:
self.iter = filter(filterFeature, self.iter, True)
elif invalidFeaturesMethod == self.RAISE_EXCEPTION:
self.iter = filter(filterFeature, self.iter, False)

def __iter__(self):
return self.iter
Expand All @@ -113,6 +138,10 @@ def __len__(self):
return int(self.layer.selectedFeatureCount())
else:
return int(self.layer.featureCount())

def tr(self, string):
return QCoreApplication.translate("FeatureIterator", string)


return Features(layer, request)

Expand Down

0 comments on commit e8c149e

Please sign in to comment.