Skip to content

Commit

Permalink
Make concave hull alg more efficient
Browse files Browse the repository at this point in the history
- remove temporary layers from context, delete them as soon as they
are finished with
- directly remove features via data provider, instead of selecting
and using edit buffer
- use native geometry methods for splitting to single features
and removing rings
  • Loading branch information
nyalldawson committed Jul 6, 2017
1 parent 70cc196 commit a2af3a9
Showing 1 changed file with 13 additions and 16 deletions.
29 changes: 13 additions & 16 deletions python/plugins/processing/algs/qgis/ConcaveHull.py
Expand Up @@ -88,7 +88,7 @@ def processAlgorithm(self, parameters, context, feedback):
# Delaunay triangulation from input point layer
feedback.setProgressText(self.tr('Creating Delaunay triangles...'))
delone_triangles = processing.run("qgis:delaunaytriangulation", {'INPUT': parameters[ConcaveHull.INPUT], 'OUTPUT': 'memory:'}, feedback=feedback, context=context)['OUTPUT']
delaunay_layer = QgsProcessingUtils.mapLayerFromString(delone_triangles, context)
delaunay_layer = context.takeResultLayer(delone_triangles)

# Get max edge length from Delaunay triangles
feedback.setProgressText(self.tr('Computing edges max length...'))
Expand Down Expand Up @@ -127,48 +127,45 @@ def processAlgorithm(self, parameters, context, feedback):
i += 1

# Remove features
delaunay_layer.selectByIds(ids)
delaunay_layer.startEditing()
delaunay_layer.deleteSelectedFeatures()
delaunay_layer.commitChanges()
delaunay_layer.dataProvider().deleteFeatures(ids)

# Dissolve all Delaunay triangles
feedback.setProgressText(self.tr('Dissolving Delaunay triangles...'))
dissolved = processing.run("native:dissolve", {'INPUT': delaunay_layer.id(), 'OUTPUT': 'memory:'}, feedback=feedback, context=context)['OUTPUT']
dissolved_layer = QgsProcessingUtils.mapLayerFromString(dissolved, context)
dissolved = processing.run("native:dissolve", {'INPUT': delaunay_layer, 'OUTPUT': 'memory:'}, feedback=feedback, context=context)['OUTPUT']
dissolved_layer = context.takeResultLayer(dissolved)

# Save result
feedback.setProgressText(self.tr('Saving data...'))
feat = QgsFeature()
dissolved_layer.getFeatures().nextFeature(feat)

# Not needed anymore, free up some resources
del delaunay_layer
del dissolved_layer

(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
layer.fields(), QgsWkbTypes.Polygon, layer.sourceCrs())

geom = feat.geometry()
if no_multigeom and geom.isMultipart():
# Only singlepart geometries are allowed
geom_list = geom.asMultiPolygon()
for single_geom_list in geom_list:
geom_list = geom.asGeometryCollection()
for single_geom in geom_list:
if feedback.isCanceled():
break

single_feature = QgsFeature()
single_geom = QgsGeometry.fromPolygon(single_geom_list)
if not holes:
# Delete holes
deleted = True
while deleted:
deleted = single_geom.deleteRing(1)
single_geom = single_geom.removeInteriorRings()
single_feature.setGeometry(single_geom)
sink.addFeature(single_feature, QgsFeatureSink.FastInsert)
else:
# Multipart geometries are allowed
if not holes:
# Delete holes
deleted = True
while deleted:
deleted = geom.deleteRing(1)
geom = geom.removeInteriorRings()
feat.setGeometry(geom)
sink.addFeature(feat, QgsFeatureSink.FastInsert)

return {self.OUTPUT: dest_id}

0 comments on commit a2af3a9

Please sign in to comment.