Skip to content

Commit

Permalink
[processing] optimise multipart to singlepart algorithm
Browse files Browse the repository at this point in the history
- simplify code
- keep z/m/curved geometries intact
- might be a bit faster
  • Loading branch information
nyalldawson committed Nov 2, 2016
1 parent 5e3bef7 commit 18fc0c6
Showing 1 changed file with 12 additions and 59 deletions.
71 changes: 12 additions & 59 deletions python/plugins/processing/algs/qgis/MultipartToSingleparts.py
Expand Up @@ -33,7 +33,6 @@
from qgis.core import QgsFeature, QgsGeometry, QgsWkbTypes

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
Expand All @@ -58,74 +57,28 @@ def defineCharacteristics(self):

def processAlgorithm(self, progress):
layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
geomType = self.multiToSingleGeom(layer.wkbType())
geomType = QgsWkbTypes.singleType(layer.wkbType())

writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
layer.fields().toList(), geomType, layer.crs())

features = vector.features(layer)
total = 100.0 / len(features)
for current, f in enumerate(features):
outFeat = QgsFeature()
attrs = f.attributes()
outFeat.setAttributes(attrs)

inGeom = f.geometry()
if inGeom:
geometries = self.extractAsSingle(inGeom)

for g in geometries:
outFeat.setGeometry(g)
writer.addFeature(outFeat)
input_geometry = f.geometry()
if input_geometry:
if input_geometry.isMultipart():
for i in range(input_geometry.geometry().numGeometries()):
singlepart_geometry = QgsGeometry(input_geometry.geometry().geometryN(i).clone())
output_feature = f
output_feature.setGeometry( singlepart_geometry )
writer.addFeature(output_feature)
else:
writer.addFeature(f)
else:
#input feature with null geometry
writer.addFeature(outFeat)
writer.addFeature(f)

progress.setPercentage(int(current * total))

del writer

def multiToSingleGeom(self, wkbType):
try:
if wkbType in (QgsWkbTypes.Point, QgsWkbTypes.MultiPoint,
QgsWkbTypes.Point25D, QgsWkbTypes.MultiPoint25D):
return QgsWkbTypes.Point
elif wkbType in (QgsWkbTypes.LineString, QgsWkbTypes.MultiLineString,
QgsWkbTypes.MultiLineString25D,
QgsWkbTypes.LineString25D):

return QgsWkbTypes.LineString
elif wkbType in (QgsWkbTypes.Polygon, QgsWkbTypes.MultiPolygon,
QgsWkbTypes.MultiPolygon25D, QgsWkbTypes.Polygon25D):

return QgsWkbTypes.Polygon
else:
return QgsWkbTypes.Unknown
except Exception as err:
raise GeoAlgorithmExecutionException(str(err))

def extractAsSingle(self, geom):
multiGeom = QgsGeometry()
geometries = []
if geom.type() == QgsWkbTypes.PointGeometry:
if geom.isMultipart():
multiGeom = geom.asMultiPoint()
for i in multiGeom:
geometries.append(QgsGeometry().fromPoint(i))
else:
geometries.append(geom)
elif geom.type() == QgsWkbTypes. LineGeometry:
if geom.isMultipart():
multiGeom = geom.asMultiPolyline()
for i in multiGeom:
geometries.append(QgsGeometry().fromPolyline(i))
else:
geometries.append(geom)
elif geom.type() == QgsWkbTypes.PolygonGeometry:
if geom.isMultipart():
multiGeom = geom.asMultiPolygon()
for i in multiGeom:
geometries.append(QgsGeometry().fromPolygon(i))
else:
geometries.append(geom)
return geometries

0 comments on commit 18fc0c6

Please sign in to comment.