def testSimplifyIssue4189(self): """Test we can simplify a complex geometry. Note: there is a ticket related to this issue here: http://hub.qgis.org/issues/4189 Backstory: Ole Nielson pointed out an issue to me (Tim Sutton) where simplify ftools was dropping features. This test replicates that issues. Interestingly we could replicate the issue in PostGIS too: - doing straight simplify returned no feature - transforming to UTM49, then simplify with e.g. 200 threshold is ok - as above with 500 threshold drops the feature pgsql2shp -f /tmp/dissolve500.shp gis 'select *, transform(simplify(transform(geom,32649),500), 4326) as simplegeom from dissolve;' """ myWKTFile = file( os.path.join(unitTestDataPath('wkt'), 'simplify_error.wkt'), 'rt') myWKT = myWKTFile.readline() myWKTFile.close() print myWKT myGeometry = QgsGeometry().fromWkt(myWKT) assert myGeometry is not None myStartLength = len(myWKT) myTolerance = 0.00001 mySimpleGeometry = myGeometry.simplify(myTolerance) myEndLength = len(mySimpleGeometry.exportToWkt()) myMessage = 'Before simplify: %i\nAfter simplify: %i\n : Tolerance %e' % ( myStartLength, myEndLength, myTolerance) myMinimumLength = len('POLYGON(())') assert myEndLength > myMinimumLength, myMessage
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) tolerance = self.getParameterValue(self.TOLERANCE) pointsBefore = 0 pointsAfter = 0 writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.pendingFields().toList(), layer.wkbType(), layer.crs()) features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): featGeometry = QgsGeometry(f.geometry()) attrs = f.attributes() pointsBefore += self.geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(tolerance) pointsAfter += self.geomVertexCount(newGeometry) feature = QgsFeature() feature.setGeometry(newGeometry) feature.setAttributes(attrs) writer.addFeature(feature) progress.setPercentage(int(current * total)) del writer ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Simplify: Input geometries have been simplified from %s to %s points' % (pointsBefore, pointsAfter)))
def testSimplifyIssue4189(self): """Test we can simplify a complex geometry. Note: there is a ticket related to this issue here: http://hub.qgis.org/issues/4189 Backstory: Ole Nielson pointed out an issue to me (Tim Sutton) where simplify ftools was dropping features. This test replicates that issues. Interestingly we could replicate the issue in PostGIS too: - doing straight simplify returned no feature - transforming to UTM49, then simplify with e.g. 200 threshold is ok - as above with 500 threshold drops the feature pgsql2shp -f /tmp/dissolve500.shp gis 'select *, transform(simplify(transform(geom,32649),500), 4326) as simplegeom from dissolve;' """ myWKTFile = file(os.path.join(unitTestDataPath('wkt'), 'simplify_error.wkt'), 'rt') myWKT = myWKTFile.readline() myWKTFile.close() print myWKT myGeometry = QgsGeometry().fromWkt(myWKT) assert myGeometry is not None myStartLength = len(myWKT) myTolerance = 0.00001 mySimpleGeometry = myGeometry.simplify(myTolerance) myEndLength = len(mySimpleGeometry.exportToWkt()) myMessage = 'Before simplify: %i\nAfter simplify: %i\n : Tolerance %e' % ( myStartLength, myEndLength, myTolerance) myMinimumLength = len('POLYGON(())') assert myEndLength > myMinimumLength, myMessage
def processAlgorithm(self, layer, tolerance, layerName): writer = QgsVectorLayer("Polygon?crs=EPSG:2180", layerName, "memory") writer.startEditing() pointsBefore = 0 pointsAfter = 0 features = vector.features(layer) for current, f in enumerate(features): featGeometry = QgsGeometry(f.geometry()) pointsBefore += self.geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(tolerance) pointsAfter += self.geomVertexCount(newGeometry) feature = QgsFeature() feature.setGeometry(newGeometry) writer.addFeature(feature) writer.commitChanges() return writer ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Simplify: Input geometries have been simplified from %s to %s points' % (pointsBefore, pointsAfter)))
def processAlgorithm(self, layer, tolerance, layerName): writer = QgsVectorLayer("Polygon?crs=EPSG:2180", layerName, "memory") writer.startEditing() pointsBefore = 0 pointsAfter = 0 features = vector.features(layer) for current, f in enumerate(features): featGeometry = QgsGeometry(f.geometry()) pointsBefore += self.geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(tolerance) pointsAfter += self.geomVertexCount(newGeometry) feature = QgsFeature() feature.setGeometry(newGeometry) writer.addFeature(feature) writer.commitChanges() return writer ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Simplify: Input geometries have been simplified from %s to %s points' % (pointsBefore, pointsAfter)))
def runSimplify(self): self.mutex.lock() self.stopMe = 0 self.mutex.unlock() interrupted = False shapeFileWriter = None pointsBefore = 0 pointsAfter = 0 if self.writeShape: vProvider = self.inputLayer.dataProvider() shapeFields = vProvider.fields() crs = vProvider.crs() wkbType = self.inputLayer.wkbType() if not crs.isValid(): crs = None shapeFileWriter = QgsVectorFileWriter(self.outputFileName, self.outputEncoding, shapeFields, wkbType, crs) featureId = 0 if self.useSelection: selection = self.inputLayer.selectedFeatures() self.emit(SIGNAL("rangeCalculated( PyQt_PyObject )"), len(selection)) for f in selection: featGeometry = QgsGeometry(f.geometry()) attrMap = f.attributes() pointsBefore += geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(self.tolerance) pointsAfter += geomVertexCount(newGeometry) feature = QgsFeature() feature.setGeometry(newGeometry) feature.setAttributes(attrMap) shapeFileWriter.addFeature(feature) featureId += 1 self.emit(SIGNAL("featureProcessed()")) self.mutex.lock() s = self.stopMe self.mutex.unlock() if s == 1: interrupted = True break else: self.emit(SIGNAL("rangeCalculated( PyQt_PyObject )"), vProvider.featureCount()) f = QgsFeature() fit = vProvider.getFeatures() while fit.nextFeature(f): featGeometry = QgsGeometry(f.geometry()) attrMap = f.attributes() pointsBefore += geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(self.tolerance) pointsAfter += geomVertexCount(newGeometry) feature = QgsFeature() feature.setGeometry(newGeometry) feature.setAttributes(attrMap) shapeFileWriter.addFeature(feature) featureId += 1 self.emit(SIGNAL("featureProcessed()")) self.mutex.lock() s = self.stopMe self.mutex.unlock() if s == 1: interrupted = True break else: # modify existing shapefile if not self.inputLayer.isEditable(): self.inputLayer.startEditing() self.inputLayer.beginEditCommand("Simplify line(s)") if self.useSelection: selection = self.inputLayer.selectedFeatures() self.emit(SIGNAL("rangeCalculated( PyQt_PyObject )"), len(selection)) for f in selection: featureId = f.id() featGeometry = QgsGeometry(f.geometry()) pointsBefore += geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(self.tolerance) pointsAfter += geomVertexCount(newGeometry) self.inputLayer.changeGeometry(featureId, newGeometry) self.emit(SIGNAL("featureProcessed()")) self.mutex.lock() s = self.stopMe self.mutex.unlock() if s == 1: interrupted = True break else: vProvider = self.inputLayer.dataProvider() self.emit(SIGNAL("rangeCalculated( PyQt_PyObject )"), vProvider.featureCount()) f = QgsFeature() fit = vProvider.getFeatures() while fit.nextFeature(f): featureId = f.id() featGeometry = QgsGeometry(f.geometry()) pointsBefore += geomVertexCount(featGeometry) newGeometry = featGeometry.simplify(self.tolerance) pointsAfter += geomVertexCount(newGeometry) self.inputLayer.changeGeometry(featureId, newGeometry) self.emit(SIGNAL("featureProcessed()")) self.mutex.lock() s = self.stopMe self.mutex.unlock() if s == 1: interrupted = True break # cleanup if self.inputLayer.isEditable(): self.inputLayer.endEditCommand() if shapeFileWriter is not None: del shapeFileWriter if not interrupted: self.emit(SIGNAL("processingFinished( PyQt_PyObject )"), (pointsBefore, pointsAfter)) else: self.emit(SIGNAL("processingInterrupted()"))