Skip to content
Permalink
Browse files

[processing] fixes for vector geoprocessing algorithms

  • Loading branch information
alexbruy committed Jan 29, 2016
1 parent 4c2c905 commit d4e400a425fab8ecd7c8ae852d4da76ce11276f1
@@ -26,12 +26,18 @@
__revision__ = '$Format:%H$'

from qgis.core import QGis, QgsFeature, QgsGeometry, QgsFeatureRequest, QgsWKBTypes

from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.ProcessingLog import ProcessingLog
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector

GEOM_25D = [QGis.WKBPoint25D, QGis.WKBLineString25D, QGis.WKBPolygon25D,
QGis.WKBMultiPoint25D, QGis.WKBMultiLineString25D,
QGis.WKBMultiPolygon25D]


class Clip(GeoAlgorithm):

@@ -54,6 +60,11 @@ def processAlgorithm(self, progress):
layerB = dataobjects.getObjectFromUri(
self.getParameterValue(Clip.OVERLAY))

geomType = layerA.dataProvider().geometryType()
if geomType in GEOM_25D:
raise GeoAlgorithmExecutionException(
self.tr('Input layer has unsupported geometry type {}').format(geomType))

writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
layerA.pendingFields(),
layerA.dataProvider().geometryType(),
@@ -88,39 +99,37 @@ def processAlgorithm(self, progress):
outFeat.setGeometry(QgsGeometry(tmpGeom))
first = False
else:
try:
cur_geom = QgsGeometry(outFeat.geometry())
new_geom = QgsGeometry(
cur_geom.combine(tmpGeom))
outFeat.setGeometry(QgsGeometry(new_geom))
except:
cur_geom = QgsGeometry(outFeat.geometry())
new_geom = QgsGeometry(cur_geom.combine(tmpGeom))
if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('GEOS geoprocessing error: One or '
'more input features have invalid '
'geometry.'))
break

outFeat.setGeometry(QgsGeometry(new_geom))
if found:
try:
cur_geom = QgsGeometry(outFeat.geometry())
new_geom = QgsGeometry(geom.intersection(cur_geom))
if new_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
int_com = QgsGeometry(geom.combine(cur_geom))
int_sym = QgsGeometry(geom.symDifference(cur_geom))
new_geom = QgsGeometry(int_com.difference(int_sym))
try:
outFeat.setGeometry(new_geom)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat)
except:
cur_geom = QgsGeometry(outFeat.geometry())
new_geom = QgsGeometry(geom.intersection(cur_geom))
if new_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
int_com = QgsGeometry(geom.combine(cur_geom))
int_sym = QgsGeometry(geom.symDifference(cur_geom))
new_geom = QgsGeometry(int_com.difference(int_sym))
if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('Feature geometry error: One or more '
'output features ignored due to '
'invalid geometry.'))
self.tr('GEOS geoprocessing error: One or more '
'input features have invalid geometry.'))
continue
try:
outFeat.setGeometry(new_geom)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat)
except:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('GEOS geoprocessing error: One or more '
'input features have invalid geometry.'))
self.tr('Feature geometry error: One or more '
'output features ignored due to '
'invalid geometry.'))
continue

current += 1
@@ -25,13 +25,18 @@

__revision__ = '$Format:%H$'

from qgis.core import QgsFeatureRequest, QgsFeature, QgsGeometry
from qgis.core import QGis, QgsFeatureRequest, QgsFeature, QgsGeometry
from processing.core.ProcessingLog import ProcessingLog
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector

GEOM_25D = [QGis.WKBPoint25D, QGis.WKBLineString25D, QGis.WKBPolygon25D,
QGis.WKBMultiPoint25D, QGis.WKBMultiLineString25D,
QGis.WKBMultiPolygon25D]


class Difference(GeoAlgorithm):

@@ -59,13 +64,14 @@ def processAlgorithm(self, progress):
layerB = dataobjects.getObjectFromUri(
self.getParameterValue(Difference.OVERLAY))

GEOS_EXCEPT = True

FEATURE_EXCEPT = True
geomType = layerA.dataProvider().geometryType()
if geomType in GEOM_25D:
raise GeoAlgorithmExecutionException(
self.tr('Input layer has unsupported geometry type {}').format(geomType))

writer = self.getOutputFromName(
Difference.OUTPUT).getVectorWriter(layerA.pendingFields(),
layerA.dataProvider().geometryType(),
geomType,
layerA.dataProvider().crs())

inFeatA = QgsFeature()
@@ -89,35 +95,27 @@ def processAlgorithm(self, progress):
request = QgsFeatureRequest().setFilterFid(i)
inFeatB = layerB.getFeatures(request).next()
tmpGeom = QgsGeometry(inFeatB.geometry())
try:
if diff_geom.intersects(tmpGeom):
diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
if diff_geom.isGeosEmpty():
GEOS_EXCEPT = False
if diff_geom.intersects(tmpGeom):
diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('GEOS geoprocessing error: One or '
'more input features have invalid '
'geometry.'))
add = False
break
except:
GEOS_EXCEPT = False
add = False
break

if add:
try:
outFeat.setGeometry(diff_geom)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat)
except:
FEATURE_EXCEPT = False
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
continue

current += 1
progress.setPercentage(int(current * total))

del writer

if not GEOS_EXCEPT:
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
self.tr('Geometry exception while computing difference'))
if not FEATURE_EXCEPT:
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
self.tr('Feature exception while computing difference'))
@@ -26,8 +26,10 @@
__revision__ = '$Format:%H$'

from qgis.core import QGis, QgsFeatureRequest, QgsFeature, QgsGeometry, QgsWKBTypes

from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.ProcessingLog import ProcessingLog
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector
@@ -41,23 +43,41 @@
for const in value:
wkbTypeGroups[const] = key

GEOM_25D = [QGis.WKBPoint25D, QGis.WKBLineString25D, QGis.WKBPolygon25D,
QGis.WKBMultiPoint25D, QGis.WKBMultiLineString25D,
QGis.WKBMultiPolygon25D]


class Intersection(GeoAlgorithm):

INPUT = 'INPUT'
INPUT2 = 'INPUT2'
OUTPUT = 'OUTPUT'

def defineCharacteristics(self):
self.name, self.i18n_name = self.trAlgorithm('Intersection')
self.group, self.i18n_group = self.trAlgorithm('Vector overlay tools')
self.addParameter(ParameterVector(self.INPUT,
self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterVector(self.INPUT2,
self.tr('Intersect layer'), [ParameterVector.VECTOR_TYPE_ANY]))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Intersection')))

def processAlgorithm(self, progress):
vlayerA = dataobjects.getObjectFromUri(
self.getParameterValue(self.INPUT))
vlayerB = dataobjects.getObjectFromUri(
self.getParameterValue(self.INPUT2))
vproviderA = vlayerA.dataProvider()

geomType = vproviderA.geometryType()
if geomType in GEOM_25D:
raise GeoAlgorithmExecutionException(
self.tr('Input layer has unsupported geometry type {}').format(geomType))

fields = vector.combineVectorFields(vlayerA, vlayerB)
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
vproviderA.geometryType(), vproviderA.crs())
geomType, vproviderA.crs())
inFeatA = QgsFeature()
inFeatB = QgsFeature()
outFeat = QgsFeature()
@@ -75,36 +95,30 @@ def processAlgorithm(self, progress):
request = QgsFeatureRequest().setFilterFid(i)
inFeatB = vlayerB.getFeatures(request).next()
tmpGeom = QgsGeometry(inFeatB.geometry())
try:
if geom.intersects(tmpGeom):
atMapB = inFeatB.attributes()
int_geom = QgsGeometry(geom.intersection(tmpGeom))
if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
int_com = geom.combine(tmpGeom)
int_sym = geom.symDifference(tmpGeom)
int_geom = QgsGeometry(int_com.difference(int_sym))
try:
if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
outFeat.setGeometry(int_geom)
attrs = []
attrs.extend(atMapA)
attrs.extend(atMapB)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat)
except:
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
continue
except:
break
if geom.intersects(tmpGeom):
atMapB = inFeatB.attributes()
int_geom = QgsGeometry(geom.intersection(tmpGeom))
if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
int_com = geom.combine(tmpGeom)
int_sym = geom.symDifference(tmpGeom)
int_geom = QgsGeometry(int_com.difference(int_sym))
if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('GEOS geoprocessing error: One or '
'more input features have invalid '
'geometry.'))
break
try:
if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
outFeat.setGeometry(int_geom)
attrs = []
attrs.extend(atMapA)
attrs.extend(atMapB)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat)
except:
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
continue

del writer

def defineCharacteristics(self):
self.name, self.i18n_name = self.trAlgorithm('Intersection')
self.group, self.i18n_group = self.trAlgorithm('Vector overlay tools')
self.addParameter(ParameterVector(self.INPUT,
self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterVector(self.INPUT2,
self.tr('Intersect layer'), [ParameterVector.VECTOR_TYPE_ANY]))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Intersection')))

1 comment on commit d4e400a

@rldhont

This comment has been minimized.

Copy link
Contributor

@rldhont rldhont commented on d4e400a Jun 10, 2016

Hi @alexbruy , Why did you restrict these process ?
Is it linked to GEOS version ?
We tests with 25D data and clip it's working.
http://hub.qgis.org/issues/14929

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