Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #3708 from nirvn/singlepart_to_multi
[processing] optimise singlepart to multipart algorithm
  • Loading branch information
nyalldawson committed Nov 3, 2016
2 parents a44ea22 + 03e29d4 commit 962166c
Showing 1 changed file with 28 additions and 79 deletions.
107 changes: 28 additions & 79 deletions python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py
Expand Up @@ -65,94 +65,43 @@ def processAlgorithm(self, progress):
layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
fieldName = self.getParameterValue(self.FIELD)

geomType = self.singleToMultiGeom(layer.wkbType())
geomType = QgsWkbTypes.multiType(layer.wkbType())

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

inFeat = QgsFeature()
outFeat = QgsFeature()
inGeom = QgsGeometry()
outGeom = QgsGeometry()

index = layer.fields().lookupField(fieldName)
unique = vector.getUniqueValues(layer, index)

collection_geom = {}
collection_attrs = {}

features = vector.features(layer)
current = 0
total = 100.0 / (len(features))

features = vector.features(layer)
total = 100.0 / (len(features) * len(unique))
if not len(unique) == layer.featureCount():
for i in unique:
multi_feature = []
first = True
features = vector.features(layer)
for inFeat in features:
atMap = inFeat.attributes()
idVar = atMap[index]
if str(idVar).strip() == str(i).strip():
if first:
attrs = atMap
first = False
inGeom = inFeat.geometry()
vType = inGeom.type()
feature_list = self.extractAsMulti(inGeom)
multi_feature.extend(feature_list)

current += 1
progress.setPercentage(int(current * total))

outFeat.setAttributes(attrs)
outGeom = QgsGeometry(self.convertGeometry(multi_feature,
vType))
outFeat.setGeometry(outGeom)
writer.addFeature(outFeat)

del writer
else:
raise GeoAlgorithmExecutionException(
self.tr('At least two features must have same attribute '
'value! Please choose another field...'))

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

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

return QgsWkbTypes.MultiPolygon
else:
return QgsWkbTypes.Unknown
except Exception:
pass

def extractAsMulti(self, geom):
if geom.type() == QgsWkbTypes.PointGeometry:
if geom.isMultipart():
return geom.asMultiPoint()
else:
return [geom.asPoint()]
elif geom.type() == QgsWkbTypes.LineGeometry:
if geom.isMultipart():
return geom.asMultiPolyline()
else:
return [geom.asPolyline()]
else:
if geom.isMultipart():
return geom.asMultiPolygon()
else:
return [geom.asPolygon()]

def convertGeometry(self, geom_list, vType):
if vType == QgsWkbTypes.PointGeometry:
return QgsGeometry().fromMultiPoint(geom_list)
elif vType == QgsWkbTypes.LineGeometry:
return QgsGeometry().fromMultiPolyline(geom_list)
else:
return QgsGeometry().fromMultiPolygon(geom_list)
for inFeat in features:
atMap = inFeat.attributes()
idVar = atMap[index]
key = str(idVar).strip()
if not key in collection_geom:
collection_geom[key] = []
collection_attrs[key] = atMap

inGeom = inFeat.geometry()
vType = inGeom.type()
collection_geom[key].append(inGeom)

current += 1
progress.setPercentage(int(current * total))

for key, geoms in collection_geom.items():
outFeat.setAttributes(collection_attrs[key])
outFeat.setGeometry(QgsGeometry.collectGeometry(geoms))
writer.addFeature(outFeat)

del writer

0 comments on commit 962166c

Please sign in to comment.