mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
[processing] fixes for vector geoprocessing algorithms
This commit is contained in:
parent
4c2c905c32
commit
d4e400a425
@ -26,12 +26,18 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
|||||||
__revision__ = '$Format:%H$'
|
__revision__ = '$Format:%H$'
|
||||||
|
|
||||||
from qgis.core import QGis, QgsFeature, QgsGeometry, QgsFeatureRequest, QgsWKBTypes
|
from qgis.core import QGis, QgsFeature, QgsGeometry, QgsFeatureRequest, QgsWKBTypes
|
||||||
|
|
||||||
from processing.core.GeoAlgorithm import GeoAlgorithm
|
from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||||
from processing.core.ProcessingLog import ProcessingLog
|
from processing.core.ProcessingLog import ProcessingLog
|
||||||
|
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||||
from processing.core.parameters import ParameterVector
|
from processing.core.parameters import ParameterVector
|
||||||
from processing.core.outputs import OutputVector
|
from processing.core.outputs import OutputVector
|
||||||
from processing.tools import dataobjects, vector
|
from processing.tools import dataobjects, vector
|
||||||
|
|
||||||
|
GEOM_25D = [QGis.WKBPoint25D, QGis.WKBLineString25D, QGis.WKBPolygon25D,
|
||||||
|
QGis.WKBMultiPoint25D, QGis.WKBMultiLineString25D,
|
||||||
|
QGis.WKBMultiPolygon25D]
|
||||||
|
|
||||||
|
|
||||||
class Clip(GeoAlgorithm):
|
class Clip(GeoAlgorithm):
|
||||||
|
|
||||||
@ -54,6 +60,11 @@ class Clip(GeoAlgorithm):
|
|||||||
layerB = dataobjects.getObjectFromUri(
|
layerB = dataobjects.getObjectFromUri(
|
||||||
self.getParameterValue(Clip.OVERLAY))
|
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(
|
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
|
||||||
layerA.pendingFields(),
|
layerA.pendingFields(),
|
||||||
layerA.dataProvider().geometryType(),
|
layerA.dataProvider().geometryType(),
|
||||||
@ -88,39 +99,37 @@ class Clip(GeoAlgorithm):
|
|||||||
outFeat.setGeometry(QgsGeometry(tmpGeom))
|
outFeat.setGeometry(QgsGeometry(tmpGeom))
|
||||||
first = False
|
first = False
|
||||||
else:
|
else:
|
||||||
try:
|
cur_geom = QgsGeometry(outFeat.geometry())
|
||||||
cur_geom = QgsGeometry(outFeat.geometry())
|
new_geom = QgsGeometry(cur_geom.combine(tmpGeom))
|
||||||
new_geom = QgsGeometry(
|
if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
|
||||||
cur_geom.combine(tmpGeom))
|
|
||||||
outFeat.setGeometry(QgsGeometry(new_geom))
|
|
||||||
except:
|
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
self.tr('GEOS geoprocessing error: One or '
|
self.tr('GEOS geoprocessing error: One or '
|
||||||
'more input features have invalid '
|
'more input features have invalid '
|
||||||
'geometry.'))
|
'geometry.'))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
outFeat.setGeometry(QgsGeometry(new_geom))
|
||||||
if found:
|
if found:
|
||||||
try:
|
cur_geom = QgsGeometry(outFeat.geometry())
|
||||||
cur_geom = QgsGeometry(outFeat.geometry())
|
new_geom = QgsGeometry(geom.intersection(cur_geom))
|
||||||
new_geom = QgsGeometry(geom.intersection(cur_geom))
|
if new_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
|
||||||
if new_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
|
int_com = QgsGeometry(geom.combine(cur_geom))
|
||||||
int_com = QgsGeometry(geom.combine(cur_geom))
|
int_sym = QgsGeometry(geom.symDifference(cur_geom))
|
||||||
int_sym = QgsGeometry(geom.symDifference(cur_geom))
|
new_geom = QgsGeometry(int_com.difference(int_sym))
|
||||||
new_geom = QgsGeometry(int_com.difference(int_sym))
|
if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
|
||||||
try:
|
|
||||||
outFeat.setGeometry(new_geom)
|
|
||||||
outFeat.setAttributes(attrs)
|
|
||||||
writer.addFeature(outFeat)
|
|
||||||
except:
|
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
self.tr('Feature geometry error: One or more '
|
self.tr('GEOS geoprocessing error: One or more '
|
||||||
'output features ignored due to '
|
'input features have invalid geometry.'))
|
||||||
'invalid geometry.'))
|
|
||||||
continue
|
continue
|
||||||
|
try:
|
||||||
|
outFeat.setGeometry(new_geom)
|
||||||
|
outFeat.setAttributes(attrs)
|
||||||
|
writer.addFeature(outFeat)
|
||||||
except:
|
except:
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
self.tr('GEOS geoprocessing error: One or more '
|
self.tr('Feature geometry error: One or more '
|
||||||
'input features have invalid geometry.'))
|
'output features ignored due to '
|
||||||
|
'invalid geometry.'))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
current += 1
|
current += 1
|
||||||
|
@ -25,13 +25,18 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
|||||||
|
|
||||||
__revision__ = '$Format:%H$'
|
__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.ProcessingLog import ProcessingLog
|
||||||
from processing.core.GeoAlgorithm import GeoAlgorithm
|
from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||||
|
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||||
from processing.core.parameters import ParameterVector
|
from processing.core.parameters import ParameterVector
|
||||||
from processing.core.outputs import OutputVector
|
from processing.core.outputs import OutputVector
|
||||||
from processing.tools import dataobjects, vector
|
from processing.tools import dataobjects, vector
|
||||||
|
|
||||||
|
GEOM_25D = [QGis.WKBPoint25D, QGis.WKBLineString25D, QGis.WKBPolygon25D,
|
||||||
|
QGis.WKBMultiPoint25D, QGis.WKBMultiLineString25D,
|
||||||
|
QGis.WKBMultiPolygon25D]
|
||||||
|
|
||||||
|
|
||||||
class Difference(GeoAlgorithm):
|
class Difference(GeoAlgorithm):
|
||||||
|
|
||||||
@ -59,13 +64,14 @@ class Difference(GeoAlgorithm):
|
|||||||
layerB = dataobjects.getObjectFromUri(
|
layerB = dataobjects.getObjectFromUri(
|
||||||
self.getParameterValue(Difference.OVERLAY))
|
self.getParameterValue(Difference.OVERLAY))
|
||||||
|
|
||||||
GEOS_EXCEPT = True
|
geomType = layerA.dataProvider().geometryType()
|
||||||
|
if geomType in GEOM_25D:
|
||||||
FEATURE_EXCEPT = True
|
raise GeoAlgorithmExecutionException(
|
||||||
|
self.tr('Input layer has unsupported geometry type {}').format(geomType))
|
||||||
|
|
||||||
writer = self.getOutputFromName(
|
writer = self.getOutputFromName(
|
||||||
Difference.OUTPUT).getVectorWriter(layerA.pendingFields(),
|
Difference.OUTPUT).getVectorWriter(layerA.pendingFields(),
|
||||||
layerA.dataProvider().geometryType(),
|
geomType,
|
||||||
layerA.dataProvider().crs())
|
layerA.dataProvider().crs())
|
||||||
|
|
||||||
inFeatA = QgsFeature()
|
inFeatA = QgsFeature()
|
||||||
@ -89,17 +95,15 @@ class Difference(GeoAlgorithm):
|
|||||||
request = QgsFeatureRequest().setFilterFid(i)
|
request = QgsFeatureRequest().setFilterFid(i)
|
||||||
inFeatB = layerB.getFeatures(request).next()
|
inFeatB = layerB.getFeatures(request).next()
|
||||||
tmpGeom = QgsGeometry(inFeatB.geometry())
|
tmpGeom = QgsGeometry(inFeatB.geometry())
|
||||||
try:
|
if diff_geom.intersects(tmpGeom):
|
||||||
if diff_geom.intersects(tmpGeom):
|
diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
|
||||||
diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
|
if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
|
||||||
if diff_geom.isGeosEmpty():
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
GEOS_EXCEPT = False
|
self.tr('GEOS geoprocessing error: One or '
|
||||||
|
'more input features have invalid '
|
||||||
|
'geometry.'))
|
||||||
add = False
|
add = False
|
||||||
break
|
break
|
||||||
except:
|
|
||||||
GEOS_EXCEPT = False
|
|
||||||
add = False
|
|
||||||
break
|
|
||||||
|
|
||||||
if add:
|
if add:
|
||||||
try:
|
try:
|
||||||
@ -107,17 +111,11 @@ class Difference(GeoAlgorithm):
|
|||||||
outFeat.setAttributes(attrs)
|
outFeat.setAttributes(attrs)
|
||||||
writer.addFeature(outFeat)
|
writer.addFeature(outFeat)
|
||||||
except:
|
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
|
continue
|
||||||
|
|
||||||
current += 1
|
current += 1
|
||||||
progress.setPercentage(int(current * total))
|
progress.setPercentage(int(current * total))
|
||||||
|
|
||||||
del writer
|
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 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
|||||||
__revision__ = '$Format:%H$'
|
__revision__ = '$Format:%H$'
|
||||||
|
|
||||||
from qgis.core import QGis, QgsFeatureRequest, QgsFeature, QgsGeometry, QgsWKBTypes
|
from qgis.core import QGis, QgsFeatureRequest, QgsFeature, QgsGeometry, QgsWKBTypes
|
||||||
|
|
||||||
from processing.core.GeoAlgorithm import GeoAlgorithm
|
from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||||
from processing.core.ProcessingLog import ProcessingLog
|
from processing.core.ProcessingLog import ProcessingLog
|
||||||
|
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||||
from processing.core.parameters import ParameterVector
|
from processing.core.parameters import ParameterVector
|
||||||
from processing.core.outputs import OutputVector
|
from processing.core.outputs import OutputVector
|
||||||
from processing.tools import dataobjects, vector
|
from processing.tools import dataobjects, vector
|
||||||
@ -41,6 +43,10 @@ for key, value in wkbTypeGroups.items():
|
|||||||
for const in value:
|
for const in value:
|
||||||
wkbTypeGroups[const] = key
|
wkbTypeGroups[const] = key
|
||||||
|
|
||||||
|
GEOM_25D = [QGis.WKBPoint25D, QGis.WKBLineString25D, QGis.WKBPolygon25D,
|
||||||
|
QGis.WKBMultiPoint25D, QGis.WKBMultiLineString25D,
|
||||||
|
QGis.WKBMultiPolygon25D]
|
||||||
|
|
||||||
|
|
||||||
class Intersection(GeoAlgorithm):
|
class Intersection(GeoAlgorithm):
|
||||||
|
|
||||||
@ -48,6 +54,15 @@ class Intersection(GeoAlgorithm):
|
|||||||
INPUT2 = 'INPUT2'
|
INPUT2 = 'INPUT2'
|
||||||
OUTPUT = 'OUTPUT'
|
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):
|
def processAlgorithm(self, progress):
|
||||||
vlayerA = dataobjects.getObjectFromUri(
|
vlayerA = dataobjects.getObjectFromUri(
|
||||||
self.getParameterValue(self.INPUT))
|
self.getParameterValue(self.INPUT))
|
||||||
@ -55,9 +70,14 @@ class Intersection(GeoAlgorithm):
|
|||||||
self.getParameterValue(self.INPUT2))
|
self.getParameterValue(self.INPUT2))
|
||||||
vproviderA = vlayerA.dataProvider()
|
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)
|
fields = vector.combineVectorFields(vlayerA, vlayerB)
|
||||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
|
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
|
||||||
vproviderA.geometryType(), vproviderA.crs())
|
geomType, vproviderA.crs())
|
||||||
inFeatA = QgsFeature()
|
inFeatA = QgsFeature()
|
||||||
inFeatB = QgsFeature()
|
inFeatB = QgsFeature()
|
||||||
outFeat = QgsFeature()
|
outFeat = QgsFeature()
|
||||||
@ -75,36 +95,30 @@ class Intersection(GeoAlgorithm):
|
|||||||
request = QgsFeatureRequest().setFilterFid(i)
|
request = QgsFeatureRequest().setFilterFid(i)
|
||||||
inFeatB = vlayerB.getFeatures(request).next()
|
inFeatB = vlayerB.getFeatures(request).next()
|
||||||
tmpGeom = QgsGeometry(inFeatB.geometry())
|
tmpGeom = QgsGeometry(inFeatB.geometry())
|
||||||
try:
|
if geom.intersects(tmpGeom):
|
||||||
if geom.intersects(tmpGeom):
|
atMapB = inFeatB.attributes()
|
||||||
atMapB = inFeatB.attributes()
|
int_geom = QgsGeometry(geom.intersection(tmpGeom))
|
||||||
int_geom = QgsGeometry(geom.intersection(tmpGeom))
|
if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
|
||||||
if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
|
int_com = geom.combine(tmpGeom)
|
||||||
int_com = geom.combine(tmpGeom)
|
int_sym = geom.symDifference(tmpGeom)
|
||||||
int_sym = geom.symDifference(tmpGeom)
|
int_geom = QgsGeometry(int_com.difference(int_sym))
|
||||||
int_geom = QgsGeometry(int_com.difference(int_sym))
|
if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
|
||||||
try:
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
|
self.tr('GEOS geoprocessing error: One or '
|
||||||
outFeat.setGeometry(int_geom)
|
'more input features have invalid '
|
||||||
attrs = []
|
'geometry.'))
|
||||||
attrs.extend(atMapA)
|
break
|
||||||
attrs.extend(atMapB)
|
try:
|
||||||
outFeat.setAttributes(attrs)
|
if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
|
||||||
writer.addFeature(outFeat)
|
outFeat.setGeometry(int_geom)
|
||||||
except:
|
attrs = []
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
attrs.extend(atMapA)
|
||||||
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
attrs.extend(atMapB)
|
||||||
continue
|
outFeat.setAttributes(attrs)
|
||||||
except:
|
writer.addFeature(outFeat)
|
||||||
break
|
except:
|
||||||
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
|
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
||||||
|
continue
|
||||||
|
|
||||||
del writer
|
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')))
|
|
||||||
|
@ -25,13 +25,18 @@ __copyright__ = '(C) 2014, Alexander Bruy'
|
|||||||
|
|
||||||
__revision__ = '$Format:%H$'
|
__revision__ = '$Format:%H$'
|
||||||
|
|
||||||
from qgis.core import QgsFeature, QgsGeometry, QgsFeatureRequest, NULL
|
from qgis.core import QGis, QgsFeature, QgsGeometry, QgsFeatureRequest, NULL
|
||||||
from processing.core.ProcessingLog import ProcessingLog
|
from processing.core.ProcessingLog import ProcessingLog
|
||||||
from processing.core.GeoAlgorithm import GeoAlgorithm
|
from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||||
|
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||||
from processing.core.parameters import ParameterVector
|
from processing.core.parameters import ParameterVector
|
||||||
from processing.core.outputs import OutputVector
|
from processing.core.outputs import OutputVector
|
||||||
from processing.tools import dataobjects, vector
|
from processing.tools import dataobjects, vector
|
||||||
|
|
||||||
|
GEOM_25D = [QGis.WKBPoint25D, QGis.WKBLineString25D, QGis.WKBPolygon25D,
|
||||||
|
QGis.WKBMultiPoint25D, QGis.WKBMultiLineString25D,
|
||||||
|
QGis.WKBMultiPolygon25D]
|
||||||
|
|
||||||
|
|
||||||
class SymmetricalDifference(GeoAlgorithm):
|
class SymmetricalDifference(GeoAlgorithm):
|
||||||
|
|
||||||
@ -58,12 +63,14 @@ class SymmetricalDifference(GeoAlgorithm):
|
|||||||
providerA = layerA.dataProvider()
|
providerA = layerA.dataProvider()
|
||||||
providerB = layerB.dataProvider()
|
providerB = layerB.dataProvider()
|
||||||
|
|
||||||
GEOS_EXCEPT = True
|
geomType = providerA.geometryType()
|
||||||
FEATURE_EXCEPT = True
|
if geomType in GEOM_25D:
|
||||||
|
raise GeoAlgorithmExecutionException(
|
||||||
|
self.tr('Input layer has unsupported geometry type {}').format(geomType))
|
||||||
|
|
||||||
fields = vector.combineVectorFields(layerA, layerB)
|
fields = vector.combineVectorFields(layerA, layerB)
|
||||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
|
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
|
||||||
fields, providerA.geometryType(), providerA.crs())
|
fields, geomType, providerA.crs())
|
||||||
|
|
||||||
featB = QgsFeature()
|
featB = QgsFeature()
|
||||||
outFeat = QgsFeature()
|
outFeat = QgsFeature()
|
||||||
@ -86,20 +93,24 @@ class SymmetricalDifference(GeoAlgorithm):
|
|||||||
for i in intersects:
|
for i in intersects:
|
||||||
providerB.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
|
providerB.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
|
||||||
tmpGeom = QgsGeometry(featB.geometry())
|
tmpGeom = QgsGeometry(featB.geometry())
|
||||||
try:
|
if diffGeom.intersects(tmpGeom):
|
||||||
if diffGeom.intersects(tmpGeom):
|
diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
|
||||||
diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
|
if not diffGeom.isGeosValid():
|
||||||
except:
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
add = False
|
self.tr('GEOS geoprocessing error: One or '
|
||||||
GEOS_EXCEPT = False
|
'more input features have invalid '
|
||||||
break
|
'geometry.'))
|
||||||
|
add = False
|
||||||
|
break
|
||||||
|
|
||||||
if add:
|
if add:
|
||||||
try:
|
try:
|
||||||
outFeat.setGeometry(diffGeom)
|
outFeat.setGeometry(diffGeom)
|
||||||
outFeat.setAttributes(attrs)
|
outFeat.setAttributes(attrs)
|
||||||
writer.addFeature(outFeat)
|
writer.addFeature(outFeat)
|
||||||
except:
|
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
|
continue
|
||||||
|
|
||||||
count += 1
|
count += 1
|
||||||
@ -117,30 +128,27 @@ class SymmetricalDifference(GeoAlgorithm):
|
|||||||
for i in intersects:
|
for i in intersects:
|
||||||
providerA.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
|
providerA.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
|
||||||
tmpGeom = QgsGeometry(featB.geometry())
|
tmpGeom = QgsGeometry(featB.geometry())
|
||||||
try:
|
if diffGeom.intersects(tmpGeom):
|
||||||
if diffGeom.intersects(tmpGeom):
|
diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
|
||||||
diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
|
if not diffGeom.isGeosValid():
|
||||||
except:
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
add = False
|
self.tr('GEOS geoprocessing error: One or '
|
||||||
GEOS_EXCEPT = False
|
'more input features have invalid '
|
||||||
break
|
'geometry.'))
|
||||||
|
add = False
|
||||||
|
break
|
||||||
|
|
||||||
if add:
|
if add:
|
||||||
try:
|
try:
|
||||||
outFeat.setGeometry(diffGeom)
|
outFeat.setGeometry(diffGeom)
|
||||||
outFeat.setAttributes(attrs)
|
outFeat.setAttributes(attrs)
|
||||||
writer.addFeature(outFeat)
|
writer.addFeature(outFeat)
|
||||||
except:
|
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
|
continue
|
||||||
|
|
||||||
count += 1
|
count += 1
|
||||||
progress.setPercentage(int(count * total))
|
progress.setPercentage(int(count * total))
|
||||||
|
|
||||||
del writer
|
del writer
|
||||||
|
|
||||||
if not GEOS_EXCEPT:
|
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
|
|
||||||
self.tr('Geometry exception while computing symmetrical difference'))
|
|
||||||
if not FEATURE_EXCEPT:
|
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
|
|
||||||
self.tr('Feature exception while computing symmetrical difference'))
|
|
||||||
|
@ -33,6 +33,19 @@ from processing.core.parameters import ParameterVector
|
|||||||
from processing.core.outputs import OutputVector
|
from processing.core.outputs import OutputVector
|
||||||
from processing.tools import dataobjects, vector
|
from processing.tools import dataobjects, vector
|
||||||
|
|
||||||
|
wkbTypeGroups = {
|
||||||
|
'Point': (QGis.WKBPoint, QGis.WKBMultiPoint, QGis.WKBPoint25D, QGis.WKBMultiPoint25D,),
|
||||||
|
'LineString': (QGis.WKBLineString, QGis.WKBMultiLineString, QGis.WKBLineString25D, QGis.WKBMultiLineString25D,),
|
||||||
|
'Polygon': (QGis.WKBPolygon, QGis.WKBMultiPolygon, QGis.WKBPolygon25D, QGis.WKBMultiPolygon25D,),
|
||||||
|
}
|
||||||
|
for key, value in wkbTypeGroups.items():
|
||||||
|
for const in value:
|
||||||
|
wkbTypeGroups[const] = key
|
||||||
|
|
||||||
|
GEOM_25D = [QGis.WKBPoint25D, QGis.WKBLineString25D, QGis.WKBPolygon25D,
|
||||||
|
QGis.WKBMultiPoint25D, QGis.WKBMultiLineString25D,
|
||||||
|
QGis.WKBMultiPolygon25D]
|
||||||
|
|
||||||
|
|
||||||
class Union(GeoAlgorithm):
|
class Union(GeoAlgorithm):
|
||||||
|
|
||||||
@ -40,18 +53,29 @@ class Union(GeoAlgorithm):
|
|||||||
INPUT2 = 'INPUT2'
|
INPUT2 = 'INPUT2'
|
||||||
OUTPUT = 'OUTPUT'
|
OUTPUT = 'OUTPUT'
|
||||||
|
|
||||||
|
def defineCharacteristics(self):
|
||||||
|
self.name, self.i18n_name = self.trAlgorithm('Union')
|
||||||
|
self.group, self.i18n_group = self.trAlgorithm('Vector overlay tools')
|
||||||
|
self.addParameter(ParameterVector(Union.INPUT,
|
||||||
|
self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
|
||||||
|
self.addParameter(ParameterVector(Union.INPUT2,
|
||||||
|
self.tr('Input layer 2'), [ParameterVector.VECTOR_TYPE_ANY]))
|
||||||
|
self.addOutput(OutputVector(Union.OUTPUT, self.tr('Union')))
|
||||||
|
|
||||||
def processAlgorithm(self, progress):
|
def processAlgorithm(self, progress):
|
||||||
vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT))
|
vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT))
|
||||||
vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2))
|
vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2))
|
||||||
GEOS_EXCEPT = True
|
|
||||||
FEATURE_EXCEPT = True
|
|
||||||
vproviderA = vlayerA.dataProvider()
|
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)
|
fields = vector.combineVectorFields(vlayerA, vlayerB)
|
||||||
names = [field.name() for field in fields]
|
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, unicode(names))
|
|
||||||
writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields,
|
writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields,
|
||||||
vproviderA.geometryType(), vproviderA.crs())
|
geomType, vproviderA.crs())
|
||||||
inFeatA = QgsFeature()
|
inFeatA = QgsFeature()
|
||||||
inFeatB = QgsFeature()
|
inFeatB = QgsFeature()
|
||||||
outFeat = QgsFeature()
|
outFeat = QgsFeature()
|
||||||
@ -77,8 +101,8 @@ class Union(GeoAlgorithm):
|
|||||||
except:
|
except:
|
||||||
# This really shouldn't happen, as we haven't
|
# This really shouldn't happen, as we haven't
|
||||||
# edited the input geom at all
|
# edited the input geom at all
|
||||||
raise GeoAlgorithmExecutionException(
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
self.tr('Feature exception while computing union'))
|
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
||||||
else:
|
else:
|
||||||
for id in intersects:
|
for id in intersects:
|
||||||
count += 1
|
count += 1
|
||||||
@ -93,9 +117,9 @@ class Union(GeoAlgorithm):
|
|||||||
|
|
||||||
if int_geom is None:
|
if int_geom is None:
|
||||||
# There was a problem creating the intersection
|
# There was a problem creating the intersection
|
||||||
raise GeoAlgorithmExecutionException(
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
self.tr('Geometry exception while computing '
|
self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
|
||||||
'intersection'))
|
int_geom = QgsGeometry()
|
||||||
else:
|
else:
|
||||||
int_geom = QgsGeometry(int_geom)
|
int_geom = QgsGeometry(int_geom)
|
||||||
|
|
||||||
@ -105,38 +129,52 @@ class Union(GeoAlgorithm):
|
|||||||
for i in temp_list:
|
for i in temp_list:
|
||||||
if i.type() == geom.type():
|
if i.type() == geom.type():
|
||||||
int_geom = QgsGeometry(i)
|
int_geom = QgsGeometry(i)
|
||||||
try:
|
try:
|
||||||
outFeat.setGeometry(int_geom)
|
outFeat.setGeometry(int_geom)
|
||||||
attrs = []
|
outFeat.setAttributes(atMapA + atMapB)
|
||||||
attrs.extend(atMapA)
|
writer.addFeature(outFeat)
|
||||||
attrs.extend(atMapB)
|
except:
|
||||||
outFeat.setAttributes(attrs)
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
writer.addFeature(outFeat)
|
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
||||||
except Exception as err:
|
else:
|
||||||
raise GeoAlgorithmExecutionException(
|
# Geometry list: prevents writing error
|
||||||
self.tr('Feature exception while computing union'))
|
# in geometries of different types
|
||||||
|
# produced by the intersection
|
||||||
|
# fix #3549
|
||||||
|
if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
|
||||||
|
try:
|
||||||
|
outFeat.setGeometry(int_geom)
|
||||||
|
outFeat.setAttributes(atMapA + atMapB)
|
||||||
|
writer.addFeature(outFeat)
|
||||||
|
except:
|
||||||
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
|
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
||||||
|
|
||||||
|
# the remaining bit of inFeatA's geometry
|
||||||
|
# if there is nothing left, this will just silently fail and we're good
|
||||||
|
diff_geom = QgsGeometry(geom)
|
||||||
|
if len(lstIntersectingB) != 0:
|
||||||
|
intB = QgsGeometry.unaryUnion(lstIntersectingB)
|
||||||
|
diff_geom = diff_geom.difference(intB)
|
||||||
|
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.'))
|
||||||
|
|
||||||
|
if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(diff_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
|
||||||
|
temp_list = diff_geom.asGeometryCollection()
|
||||||
|
for i in temp_list:
|
||||||
|
if i.type() == geom.type():
|
||||||
|
diff_geom = QgsGeometry(i)
|
||||||
try:
|
try:
|
||||||
# the remaining bit of inFeatA's geometry
|
|
||||||
# if there is nothing left, this will just silently fail and we're good
|
|
||||||
diff_geom = QgsGeometry(geom)
|
|
||||||
if len(lstIntersectingB) != 0:
|
|
||||||
intB = QgsGeometry.unaryUnion(lstIntersectingB)
|
|
||||||
diff_geom = diff_geom.difference(intB)
|
|
||||||
|
|
||||||
if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection:
|
|
||||||
temp_list = diff_geom.asGeometryCollection()
|
|
||||||
for i in temp_list:
|
|
||||||
if i.type() == geom.type():
|
|
||||||
diff_geom = QgsGeometry(i)
|
|
||||||
outFeat.setGeometry(diff_geom)
|
outFeat.setGeometry(diff_geom)
|
||||||
outFeat.setAttributes(atMapA)
|
outFeat.setAttributes(atMapA)
|
||||||
writer.addFeature(outFeat)
|
writer.addFeature(outFeat)
|
||||||
except Exception as err:
|
except:
|
||||||
raise GeoAlgorithmExecutionException(
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
self.tr('Feature exception while computing union'))
|
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
||||||
|
|
||||||
length = len(vproviderA.fields())
|
length = len(vproviderA.fields())
|
||||||
|
atMapA = [None] * length
|
||||||
|
|
||||||
featuresA = vector.features(vlayerB)
|
featuresA = vector.features(vlayerB)
|
||||||
nFeat = len(featuresA)
|
nFeat = len(featuresA)
|
||||||
@ -154,53 +192,41 @@ class Union(GeoAlgorithm):
|
|||||||
outFeat.setGeometry(geom)
|
outFeat.setGeometry(geom)
|
||||||
outFeat.setAttributes(atMap)
|
outFeat.setAttributes(atMap)
|
||||||
writer.addFeature(outFeat)
|
writer.addFeature(outFeat)
|
||||||
except Exception as err:
|
except:
|
||||||
raise GeoAlgorithmExecutionException(
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
self.tr('Feature exception while computing union'))
|
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
||||||
else:
|
else:
|
||||||
for id in intersects:
|
for id in intersects:
|
||||||
request = QgsFeatureRequest().setFilterFid(id)
|
request = QgsFeatureRequest().setFilterFid(id)
|
||||||
inFeatB = vlayerA.getFeatures(request).next()
|
inFeatB = vlayerA.getFeatures(request).next()
|
||||||
atMapB = inFeatB.attributes()
|
atMapB = inFeatB.attributes()
|
||||||
tmpGeom = QgsGeometry(inFeatB.geometry())
|
tmpGeom = QgsGeometry(inFeatB.geometry())
|
||||||
try:
|
|
||||||
if diff_geom.intersects(tmpGeom):
|
if diff_geom.intersects(tmpGeom):
|
||||||
add = True
|
add = True
|
||||||
diff_geom = QgsGeometry(
|
diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
|
||||||
diff_geom.difference(tmpGeom))
|
if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
|
||||||
else:
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
|
self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
# Ihis only happends if the bounding box
|
# Ihis only happends if the bounding box
|
||||||
# intersects, but the geometry doesn't
|
# intersects, but the geometry doesn't
|
||||||
outFeat.setGeometry(diff_geom)
|
outFeat.setGeometry(diff_geom)
|
||||||
outFeat.setAttributes(atMap)
|
outFeat.setAttributes(atMap)
|
||||||
writer.addFeature(outFeat)
|
writer.addFeature(outFeat)
|
||||||
except Exception as err:
|
except:
|
||||||
raise GeoAlgorithmExecutionException(
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
self.tr('Geometry exception while computing intersection'))
|
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
||||||
|
|
||||||
if add:
|
if add:
|
||||||
try:
|
try:
|
||||||
outFeat.setGeometry(diff_geom)
|
outFeat.setGeometry(diff_geom)
|
||||||
outFeat.setAttributes(atMap)
|
outFeat.setAttributes(atMap)
|
||||||
writer.addFeature(outFeat)
|
writer.addFeature(outFeat)
|
||||||
except Exception as err:
|
except:
|
||||||
raise err
|
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
|
||||||
FEATURE_EXCEPT = False
|
self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
|
||||||
nElement += 1
|
nElement += 1
|
||||||
|
|
||||||
del writer
|
del writer
|
||||||
if not GEOS_EXCEPT:
|
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
|
|
||||||
self.tr('Geometry exception while computing intersection'))
|
|
||||||
if not FEATURE_EXCEPT:
|
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
|
|
||||||
self.tr('Feature exception while computing intersection'))
|
|
||||||
|
|
||||||
def defineCharacteristics(self):
|
|
||||||
self.name, self.i18n_name = self.trAlgorithm('Union')
|
|
||||||
self.group, self.i18n_group = self.trAlgorithm('Vector overlay tools')
|
|
||||||
self.addParameter(ParameterVector(Union.INPUT,
|
|
||||||
self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
|
|
||||||
self.addParameter(ParameterVector(Union.INPUT2,
|
|
||||||
self.tr('Input layer 2'), [ParameterVector.VECTOR_TYPE_ANY]))
|
|
||||||
self.addOutput(OutputVector(Union.OUTPUT, self.tr('Union')))
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user