From 8f1cf6edaca0352a891b5d8e4cca2f70b677ffc7 Mon Sep 17 00:00:00 2001 From: cfarmer Date: Sun, 8 Feb 2009 17:57:14 +0000 Subject: [PATCH] 1) geoprocessing tools better handle geos exceptions 2) fix osx bug regarding about dialog 3) update version information git-svn-id: http://svn.osgeo.org/qgis/trunk@10127 c8812cc2-4d05-0410-92ff-de0c093fc19c --- python/plugins/fTools/__init__.py | 4 +- python/plugins/fTools/doAbout.py | 4 +- python/plugins/fTools/fTools.py | 6 +- .../plugins/fTools/tools/doGeoprocessing.py | 342 +++++++++++------- 4 files changed, 215 insertions(+), 141 deletions(-) diff --git a/python/plugins/fTools/__init__.py b/python/plugins/fTools/__init__.py index 124c99d5cfe..f13b5e149bd 100755 --- a/python/plugins/fTools/__init__.py +++ b/python/plugins/fTools/__init__.py @@ -21,13 +21,13 @@ def description(): return "Tools for vector data analysis and management" def version(): - return "0.5.5" + return "0.5.6" def qgisMinimumVersion(): return "1.0.0" def authorName(): - return "Carson Farmer" + return "Carson J. Q. Farmer" def classFactory( iface ): from fTools import fToolsPlugin diff --git a/python/plugins/fTools/doAbout.py b/python/plugins/fTools/doAbout.py index 7216935fe49..8b38943b104 100755 --- a/python/plugins/fTools/doAbout.py +++ b/python/plugins/fTools/doAbout.py @@ -32,7 +32,7 @@ class Dialog(QDialog, Ui_Dialog): QObject.connect(self.btnWeb, SIGNAL("clicked()"), self.openWeb) QObject.connect(self.btnHelp, SIGNAL("clicked()"), self.openHelp) self.fToolsLogo.setPixmap(QPixmap(":/icons/default/ftools_logo.png")) - self.label_3.setText("fTools 0.5.2") + self.label_3.setText("fTools 0.5.6") self.textEdit.setText(self.getText()) def getText(self): @@ -71,6 +71,8 @@ class Dialog(QDialog, Ui_Dialog): aknowledgeString.append("Paolo Cavallini\n") aknowledgeString.append("Aaron Racicot\n") aknowledgeString.append("Colin Robertson\n") + aknowledgeString.append("Agustin Lobo\n") + aknowledgeString.append("Jurgen E. Fischer\n") aknowledgeString.append("QGis developer and user communities\n") aknowledgeString.append("Folks on #qgis at freenode.net\n") aknowledgeString.append("All those who have reported bugs/fixes/suggestions/comments/etc.") diff --git a/python/plugins/fTools/fTools.py b/python/plugins/fTools/fTools.py index b9b15984f86..98ff24498e5 100755 --- a/python/plugins/fTools/fTools.py +++ b/python/plugins/fTools/fTools.py @@ -170,7 +170,7 @@ class fToolsPlugin: QCoreApplication.translate( "fTools", "Split vector layer" ), self.iface.mainWindow() ) self.dataManageMenu.addActions( [ self.project, self.define, self.joinAttr, self.spatJoin, self.splitVect ] ) - self.about_ftools = QAction( QIcon( self.getThemeIcon( "ftools_logo.png" ) ), + self.ftools_about = QAction( QIcon( self.getThemeIcon( "ftools_logo.png" ) ), QCoreApplication.translate( "fTools", "About fTools" ), self.iface.mainWindow() ) self.menu.addMenu( self.analysisMenu ) @@ -179,7 +179,7 @@ class fToolsPlugin: self.menu.addMenu( self.conversionMenu ) self.menu.addMenu( self.dataManageMenu ) self.menu.addSeparator() - self.menu.addAction( self.about_ftools ) + self.menu.addAction( self.ftools_about ) menuBar = self.iface.mainWindow().menuBar() actions = menuBar.actions() @@ -226,7 +226,7 @@ class fToolsPlugin: QObject.connect( self.spatJoin, SIGNAL("triggered()"), self.dospatJoin ) QObject.connect( self.splitVect, SIGNAL("triggered()"), self.dosplitVect ) - QObject.connect( self.about_ftools, SIGNAL("triggered()"), self.doabout ) + QObject.connect( self.ftools_about, SIGNAL("triggered()"), self.doabout ) def unload( self ): pass diff --git a/python/plugins/fTools/tools/doGeoprocessing.py b/python/plugins/fTools/tools/doGeoprocessing.py index e209aa8be5f..a8a5fd1f6fe 100755 --- a/python/plugins/fTools/tools/doGeoprocessing.py +++ b/python/plugins/fTools/tools/doGeoprocessing.py @@ -4,6 +4,7 @@ from qgis.core import * from qgis.gui import * from frmGeoprocessing import Ui_Dialog import ftools_utils +import sys class GeoprocessingDialog( QDialog, Ui_Dialog ): def __init__( self, iface, function ): @@ -161,19 +162,24 @@ class GeoprocessingDialog( QDialog, Ui_Dialog ): self.testThread.stop() self.cancel_close.setText( "Close" ) QObject.disconnect( self.cancel_close, SIGNAL( "clicked()" ), self.cancelThread ) - if results[0]: - if not results[1]: - out_text = self.tr( "\n\nWarning: Different input coordinate reference systems detected, results may not be as expected.") - else: - out_text = "" - addToTOC = QMessageBox.question( self, "Geoprocessing", self.tr( "Created output shapefile:" ) + "\n" + - unicode( self.shapefileName ) + "\n\n" + self.tr( "Would you like to add the new layer to the TOC?" ) - + out_text, QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton ) - if addToTOC == QMessageBox.Yes: - ftools_utils.addShapeToCanvas( unicode( self.shapefileName ) ) + if not results[2] or not results[1] or not results [0]: + out_text = self.tr( "\nWarnings:" ) + end_text = self.tr( "\nSome output geometries may be missing or invalid.\n\nWould you like to add the new layer anyway?" ) else: - QMessageBox.warning( self, "Geoprocessing", self.tr( "GEOS geoprocessing error, please check that all features have a valid geometry" ) ) - QObject.disconnect( self.cancel_close, SIGNAL( "clicked()" ), self.cancelThread ) + out_text = "\n" + end_text = self.tr( "\n\nWould you like to add the new layer to the TOC?" ) + if not results[2]: + out_text = out_text + self.tr( "\nInput CRS error: Different input coordinate reference systems detected, results may not be as expected.") + if not results[1]: + out_text = out_text + self.tr( "\nFeature geometry error: One or more output features ignored due to invalid geometry.") + if not results[0]: + out_text = out_text + self.tr( "\nGEOS geoprocessing error: One or more input features have invalid geometry.") + else: + out_text = "" + addToTOC = QMessageBox.question( self, "Geoprocessing", self.tr( "Created output shapefile:" ) + "\n" + + unicode( self.shapefileName ) + out_text + end_text, QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton ) + if addToTOC == QMessageBox.Yes: + ftools_utils.addShapeToCanvas( unicode( self.shapefileName ) ) def runStatusFromThread( self, status ): self.progressBar.setValue( status ) @@ -202,24 +208,24 @@ class geoprocessingThread( QThread ): ( self.myParam, useField ) = self.checkParameter( self.vlayerA, self.myParam ) if not self.myParam is None: if self.myFunction == 1: - success, match = self.buffering( useField ) + geos, feature, match = self.buffering( useField ) elif self.myFunction == 2: - success, match = self.convex_hull( useField ) + geos, feature, match = self.convex_hull( useField ) elif self.myFunction == 4: - success, match = self.dissolve( useField ) + geos, feature, match = self.dissolve( useField ) else: self.vlayerB = ftools_utils.getVectorLayerByName( self.myLayerB ) if self.myFunction == 3: - success, match = self.difference() + geos, feature, match = self.difference() elif self.myFunction == 5: - success, match = self.intersect() + geos, feature, match = self.intersect() elif self.myFunction == 6: - success, match = self.union() + geos, feature, match = self.union() elif self.myFunction == 7: - success, match = self.symetrical_difference() + geos, feature, match = self.symetrical_difference() elif self.myFunction == 8: - success, match = self.clip() - self.emit( SIGNAL( "runFinished(PyQt_PyObject)" ), (success, match) ) + geos, feature, match = self.clip() + self.emit( SIGNAL( "runFinished(PyQt_PyObject)" ), (geos, feature, match) ) self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), 0 ) def stop(self): @@ -227,6 +233,7 @@ class geoprocessingThread( QThread ): def buffering( self, useField ): GEOS_EXCEPT = True + FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() allAttrs = vproviderA.attributeIndexes() vproviderA.select( allAttrs ) @@ -244,9 +251,8 @@ class geoprocessingThread( QThread ): if self.myMerge: first = True vproviderA.rewind() + add = True while vproviderA.nextFeature( inFeat ): - nElement += 1 - self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) atMap = inFeat.attributeMap() if useField: value = atMap[ self.myParam ].toDouble()[ 0 ] @@ -255,27 +261,28 @@ class geoprocessingThread( QThread ): inGeom = QgsGeometry( inFeat.geometry() ) try: outGeom = inGeom.buffer( float( value ), 5 ) + if first: + tempGeom = QgsGeometry( outGeom ) + first = False + else: + try: + tempGeom = tempGeom.combine( outGeom ) + except: + GEOS_EXCEPT = False + continue except: - outGeom = QgsGeometry() GEOS_EXCEPT = False - break - if first: - tempGeom = QgsGeometry( outGeom ) - first = False - else: - try: - tempGeom = tempGeom.combine( outGeom ) - except: - tempGeom = QgsGeometry() - GEOS_EXCEPT = False - break - outFeat.setGeometry( tempGeom ) - writer.addFeature( outFeat ) + continue + nElement += 1 + self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) + try: + outFeat.setGeometry( tempGeom ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False else: vproviderA.rewind() while vproviderA.nextFeature( inFeat ): - nElement += 1 - self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) atMap = inFeat.attributeMap() if useField: value = atMap[ self.myParam ].toDouble()[ 0 ] @@ -284,18 +291,24 @@ class geoprocessingThread( QThread ): inGeom = QgsGeometry( inFeat.geometry() ) try: outGeom = inGeom.buffer( float( value ), 5 ) + try: + outFeat.setGeometry( outGeom ) + outFeat.setAttributeMap( atMap ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False + continue except: - outGeom = QgsGeometry() GEOS_EXCEPT = False continue - outFeat.setGeometry( outGeom ) - outFeat.setAttributeMap( atMap ) - writer.addFeature( outFeat ) + nElement += 1 + self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) del writer - return GEOS_EXCEPT, True + return GEOS_EXCEPT, FEATURE_EXCEPT, True def convex_hull(self, useField ): GEOS_EXCEPT = True + FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() allAttrsA = vproviderA.attributeIndexes() fields = vproviderA.fields() @@ -318,8 +331,6 @@ class geoprocessingThread( QThread ): vproviderA.select( allAttrsA ) vproviderA.rewind() while vproviderA.nextFeature( inFeat ): - nElement += 1 - self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) atMap = inFeat.attributeMap() idVar = atMap[ self.myParam ] if idVar.toString().trimmed() == i.toString().trimmed(): @@ -329,19 +340,21 @@ class geoprocessingThread( QThread ): inGeom = QgsGeometry( inFeat.geometry() ) points = ftools_utils.extractPoints( inGeom ) hull.extend( points ) + nElement += 1 + self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) if len( hull ) >= 3: tmpGeom = QgsGeometry( outGeom.fromMultiPoint( hull ) ) try: outGeom = tmpGeom.convexHull() + outFeat.setGeometry( outGeom ) + (area, perim) = self.simpleMeasure( outGeom ) + outFeat.addAttribute( 0, QVariant( outID ) ) + outFeat.addAttribute( 1, QVariant( area ) ) + outFeat.addAttribute( 2, QVariant( perim ) ) + writer.addFeature( outFeat ) except: - outGeom = QgsGeometry() GEOS_EXCEPT = False - outFeat.setGeometry( outGeom ) - (area, perim) = self.simpleMeasure( outGeom ) - outFeat.addAttribute( 0, QVariant( outID ) ) - outFeat.addAttribute( 1, QVariant( area ) ) - outFeat.addAttribute( 2, QVariant( perim ) ) - writer.addFeature( outFeat ) + continue else: hull = [] vproviderA.rewind() @@ -350,24 +363,24 @@ class geoprocessingThread( QThread ): self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), 0) self.emit( SIGNAL( "runRange(PyQt_PyObject)" ), ( 0, nFeat ) ) while vproviderA.nextFeature( inFeat ): - nElement += 1 - self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) inGeom = QgsGeometry( inFeat.geometry() ) points = ftools_utils.extractPoints( inGeom ) hull.extend( points ) + nElement += 1 + self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) tmpGeom = QgsGeometry( outGeom.fromMultiPoint( hull ) ) try: outGeom = tmpGeom.convexHull() + outFeat.setGeometry( outGeom ) + writer.addFeature( outFeat ) except: - outGeom = QgsGeometry() GEOS_EXCEPT = False - outFeat.setGeometry( outGeom ) - writer.addFeature( outFeat ) del writer - return GEOS_EXCEPT, True + return GEOS_EXCEPT, FEATURE_EXCEPT, True def dissolve( self, useField ): GEOS_EXCEPT = True + FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() allAttrsA = vproviderA.attributeIndexes() fields = vproviderA.fields() @@ -382,6 +395,7 @@ class geoprocessingThread( QThread ): self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), 0) self.emit( SIGNAL( "runRange(PyQt_PyObject)" ), ( 0, nFeat ) ) first = True + add = True while vproviderA.nextFeature( inFeat ): nElement += 1 self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) @@ -394,11 +408,11 @@ class geoprocessingThread( QThread ): tmpInGeom = QgsGeometry( inFeat.geometry() ) tmpOutGeom = QgsGeometry( outFeat.geometry() ) try: - tmpOutGeom = tmpOutGeom.combine( tmpInGeom ) + tmpOutGeom = QgsGeometry( tmpOutGeom.combine( tmpInGeom ) ) + outFeat.setGeometry( tmpOutGeom ) except: - tmpOutGeom = QgsGeometry() GEOS_EXCEPT = False - outFeat.setGeometry( tmpOutGeom ) + continue outFeat.setAttributeMap( attrs ) writer.addFeature( outFeat ) else: @@ -408,6 +422,7 @@ class geoprocessingThread( QThread ): self.emit( SIGNAL( "runRange(PyQt_PyObject)" ), ( 0, nFeat ) ) for item in unique: first = True + add = True vproviderA.select( allAttrsA ) vproviderA.rewind() while vproviderA.nextFeature( inFeat ): @@ -426,18 +441,20 @@ class geoprocessingThread( QThread ): tmpInGeom = QgsGeometry( inFeat.geometry() ) tmpOutGeom = QgsGeometry( outFeat.geometry() ) try: - tmpOutGeom = tmpOutGeom.combine( tmpInGeom ) + tmpOutGeom = QgsGeometry( tmpOutGeom.combine( tmpInGeom ) ) + outFeat.setGeometry( tmpOutGeom ) except: - tmpOutGeom = QgsGeometry() GEOS_EXCEPT = False - outFeat.setGeometry( tmpOutGeom ) - outFeat.setAttributeMap( attrs ) - writer.addFeature( outFeat ) + add = False + if add: + outFeat.setAttributeMap( attrs ) + writer.addFeature( outFeat ) del writer - return GEOS_EXCEPT, True + return GEOS_EXCEPT, FEATURE_EXCEPT, True def difference( self ): GEOS_EXCEPT = True + FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() allAttrsA = vproviderA.attributeIndexes() vproviderA.select( allAttrsA ) @@ -460,28 +477,36 @@ class geoprocessingThread( QThread ): vproviderA.rewind() while vproviderA.nextFeature( inFeatA ): nElement += 1 + add = True self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) geom = QgsGeometry( inFeatA.geometry() ) + diff_geom = QgsGeometry( geom ) atMap = inFeatA.attributeMap() intersects = index.intersects( geom.boundingBox() ) for id in intersects: vproviderB.featureAtId( int( id ), inFeatB , True, allAttrsB ) tmpGeom = QgsGeometry( inFeatB.geometry() ) try: - if geom.intersects( tmpGeom ): - geom = geom.difference( tmpGeom ) + if diff_geom.intersects( tmpGeom ): + diff_geom = QgsGeometry( diff_geom.difference( tmpGeom ) ) except: - geom = QgsGeometry() GEOS_EXCEPT = False + add = False break - outFeat.setGeometry( geom ) - outFeat.setAttributeMap( atMap ) - writer.addFeature( outFeat ) + if add: + try: + outFeat.setGeometry( diff_geom ) + outFeat.setAttributeMap( atMap ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False + continue del writer - return GEOS_EXCEPT, crs_match + return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match def intersect( self ): GEOS_EXCEPT = True + FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() allAttrsA = vproviderA.attributeIndexes() vproviderA.select( allAttrsA ) @@ -514,22 +539,27 @@ class geoprocessingThread( QThread ): try: if geom.intersects( tmpGeom ): atMapB = inFeatB.attributeMap() - int_geom = geom.intersection( tmpGeom ) + int_geom = QgsGeometry( geom.intersection( tmpGeom ) ) if int_geom.wkbType() == 7: int_com = geom.combine( tmpGeom ) int_sym = geom.symDifference( tmpGeom ) - int_geom = int_com.difference( int_sym ) - outFeat.setGeometry( int_geom ) - outFeat.setAttributeMap( ftools_utils.combineVectorAttributes( atMapA, atMapB ) ) - writer.addFeature( outFeat ) + int_geom = QgsGeometry( int_com.difference( int_sym ) ) + try: + outFeat.setGeometry( int_geom ) + outFeat.setAttributeMap( ftools_utils.combineVectorAttributes( atMapA, atMapB ) ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False + continue except: GEOS_EXCEPT = False - continue + break del writer - return True, crs_match + return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match def union( self ): GEOS_EXCEPT = True + FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() allAttrsA = vproviderA.attributeIndexes() vproviderA.select( allAttrsA ) @@ -552,76 +582,99 @@ class geoprocessingThread( QThread ): self.emit( SIGNAL( "runRange(PyQt_PyObject)" ), ( 0, nFeat ) ) vproviderA.rewind() while vproviderA.nextFeature( inFeatA ): - nElement += 1 self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) + nElement += 1 found = False geom = QgsGeometry( inFeatA.geometry() ) diffGeom = QgsGeometry( inFeatA.geometry() ) atMapA = inFeatA.attributeMap() intersects = indexA.intersects( geom.boundingBox() ) if len( intersects ) <= 0: - outFeat.setGeometry( geom ) - outFeat.setAttributeMap( atMapA ) - writer.addFeature( outFeat ) + try: + outFeat.setGeometry( geom ) + outFeat.setAttributeMap( atMapA ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False + continue else: for id in intersects: vproviderB.featureAtId( int( id ), inFeatB , True, allAttrsB ) atMapB = inFeatB.attributeMap() tmpGeom = QgsGeometry( inFeatB.geometry() ) - if geom.intersects( tmpGeom ): - found = True - try: - diff_geom = diff_geom.difference( tmpGeom ) - int_geom = geom.intersection( tmpGeom ) + try: + if geom.intersects( tmpGeom ): + found = True + diff_geom = QgsGeometry( diff_geom.difference( tmpGeom ) ) + int_geom = QgsGeometry( geom.intersection( tmpGeom ) ) if int_geom.wkbType() == 7: int_com = geom.combine( tmpGeom ) int_sym = geom.symDifference( tmpGeom ) - int_geom = int_com.difference( int_sym ) - except: - int_geom = QgsGeometry() - GEOS_EXCEPT = False - found = False - break - outFeat.setGeometry( int_geom ) - outFeat.setAttributeMap( ftools_utils.combineVectorAttributes( atMapA, atMapB ) ) - writer.addFeature( outFeat ) + int_geom = QgsGeometry( int_com.difference( int_sym ) ) + try: + outFeat.setGeometry( int_geom ) + outFeat.setAttributeMap( ftools_utils.combineVectorAttributes( atMapA, atMapB ) ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False + continue + except: + GEOS_EXCEPT = False + found = False + continue if found: - outFeat.setGeometry( diff_geom ) - outFeat.setAttributeMap( atMapA ) - writer.addFeature( outFeat ) + try: + outFeat.setGeometry( diff_geom ) + outFeat.setAttributeMap( atMapA ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False + continue length = len( vproviderA.fields().values() ) vproviderB.rewind() while vproviderB.nextFeature( inFeatA ): - nElement += 1 - self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) + add = True geom = QgsGeometry( inFeatA.geometry() ) + diff_geom = QgsGeometry( geom ) atMap = inFeatA.attributeMap().values() atMap = dict( zip( range( length, length + len( atMap ) ), atMap ) ) intersects = indexB.intersects( geom.boundingBox() ) if len(intersects) <= 0: - outFeat.setGeometry( geom ) - outFeat.setAttributeMap( atMapA ) - writer.addFeature( outFeat ) + try: + outFeat.setGeometry( diff_geom ) + outFeat.setAttributeMap( atMapA ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False + continue else: for id in intersects: vproviderA.featureAtId( int( id ), inFeatB , True, allAttrsA ) atMapB = inFeatB.attributeMap() tmpGeom = QgsGeometry( inFeatB.geometry() ) try: - if geom.intersects( tmpGeom ): - geom = geom.difference( tmpGeom ) + if diff_geom.intersects( tmpGeom ): + diff_geom = QgsGeometry( diff_geom.difference( tmpGeom ) ) except: - geom = QgsGeometry() + add = False GEOS_EXCEPT = False + break + if add: + try: + outFeat.setGeometry( diff_geom ) + outFeat.setAttributeMap( atMap ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False continue - outFeat.setGeometry( geom ) - outFeat.setAttributeMap( atMap ) - writer.addFeature( outFeat ) + self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) + nElement += 1 del writer - return True, crs_match + return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match def symetrical_difference( self ): GEOS_EXCEPT = True + FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() allAttrsA = vproviderA.attributeIndexes() vproviderA.select( allAttrsA ) @@ -646,28 +699,37 @@ class geoprocessingThread( QThread ): while vproviderA.nextFeature( inFeatA ): nElement += 1 self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) + add = True geom = QgsGeometry( inFeatA.geometry() ) + diff_geom = QgsGeometry( geom ) atMapA = inFeatA.attributeMap() intersects = indexA.intersects( geom.boundingBox() ) for id in intersects: vproviderB.featureAtId( int( id ), inFeatB , True, allAttrsB ) tmpGeom = QgsGeometry( inFeatB.geometry() ) try: - if geom.intersects( tmpGeom ): - geom = geom.difference( tmpGeom ) + if diff_geom.intersects( tmpGeom ): + diff_geom = QgsGeometry( diff_geom.difference( tmpGeom ) ) except: - geom = QgsGeometry() + add = False GEOS_EXCEPT = False + break + if add: + try: + outFeat.setGeometry( diff_geom ) + outFeat.setAttributeMap( atMapA ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False continue - outFeat.setGeometry( geom ) - outFeat.setAttributeMap( atMapA ) - writer.addFeature( outFeat ) length = len( vproviderA.fields().values() ) vproviderB.rewind() while vproviderB.nextFeature( inFeatA ): nElement += 1 self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) + add = True geom = QgsGeometry( inFeatA.geometry() ) + diff_geom = QgsGeometry( geom ) atMap = inFeatA.attributeMap().values() atMap = dict( zip( range( length, length + len( atMap ) ), atMap ) ) intersects = indexB.intersects( geom.boundingBox() ) @@ -675,20 +737,26 @@ class geoprocessingThread( QThread ): vproviderA.featureAtId( int( id ), inFeatB , True, allAttrsA ) tmpGeom = QgsGeometry( inFeatB.geometry() ) try: - if geom.intersects( tmpGeom ): - geom = geom.difference( tmpGeom ) + if diff_geom.intersects( tmpGeom ): + diff_geom = QgsGeometry( diff_geom.difference( tmpGeom ) ) except: - geom = QgsGeometry() + add = False GEOS_EXCEPT = False + break + if add: + try: + outFeat.setGeometry( diff_geom ) + outFeat.setAttributeMap( atMap ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False continue - outFeat.setGeometry( geom ) - outFeat.setAttributeMap( atMap ) - writer.addFeature( outFeat ) del writer - return GEOS_EXCEPT, crs_match + return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match def clip( self ): GEOS_EXCEPT = True + FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() allAttrsA = vproviderA.attributeIndexes() vproviderA.select( allAttrsA ) @@ -720,19 +788,23 @@ class geoprocessingThread( QThread ): tmpGeom = QgsGeometry( inFeatB.geometry() ) try: if geom.intersects( tmpGeom ): - int_geom = geom.intersection( tmpGeom ) + int_geom = QgsGeometry( geom.intersection( tmpGeom ) ) if int_geom.wkbType() == 7: int_com = geom.combine( tmpGeom ) int_sym = geom.symDifference( tmpGeom ) - int_geom = int_com.difference( int_sym ) - outFeat.setGeometry( int_geom ) - outFeat.setAttributeMap( atMap ) - writer.addFeature( outFeat ) + int_geom = QgsGeometry( int_com.difference( int_sym ) ) + try: + outFeat.setGeometry( int_geom ) + outFeat.setAttributeMap( atMap ) + writer.addFeature( outFeat ) + except: + FEATURE_EXCEPT = False + continue except: GEOS_EXCEPT = False - continue + break del writer - return GEOS_EXCEPT, crs_match + return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match def checkParameter( self, layer, param ): if self.myFunction == 1: