mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
[FEATURE] Make processing dissolve algorithm accept multiple fields
This allows you to dissolve based on more than one field value
This commit is contained in:
parent
f449bf2361
commit
bb54b4f41a
@ -26,6 +26,7 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import os
|
||||
from collections import defaultdict
|
||||
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
|
||||
@ -36,7 +37,7 @@ from processing.core.GeoAlgorithm import GeoAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterBoolean
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.core.parameters import ParameterTableMultipleField
|
||||
from processing.core.outputs import OutputVector
|
||||
from processing.tools import vector, dataobjects
|
||||
|
||||
@ -60,14 +61,14 @@ class Dissolve(GeoAlgorithm):
|
||||
self.tr('Input layer'),
|
||||
[ParameterVector.VECTOR_TYPE_POLYGON, ParameterVector.VECTOR_TYPE_LINE]))
|
||||
self.addParameter(ParameterBoolean(Dissolve.DISSOLVE_ALL,
|
||||
self.tr('Dissolve all (do not use field)'), True))
|
||||
self.addParameter(ParameterTableField(Dissolve.FIELD,
|
||||
self.tr('Unique ID field'), Dissolve.INPUT, optional=True))
|
||||
self.tr('Dissolve all (do not use fields)'), True))
|
||||
self.addParameter(ParameterTableMultipleField(Dissolve.FIELD,
|
||||
self.tr('Unique ID fields'), Dissolve.INPUT, optional=True))
|
||||
self.addOutput(OutputVector(Dissolve.OUTPUT, self.tr('Dissolved')))
|
||||
|
||||
def processAlgorithm(self, progress):
|
||||
useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
|
||||
fieldname = self.getParameterValue(Dissolve.FIELD)
|
||||
field_names = self.getParameterValue(Dissolve.FIELD)
|
||||
vlayerA = dataobjects.getObjectFromUri(
|
||||
self.getParameterValue(Dissolve.INPUT))
|
||||
vproviderA = vlayerA.dataProvider()
|
||||
@ -127,20 +128,16 @@ class Dissolve(GeoAlgorithm):
|
||||
outFeat.setAttributes(attrs)
|
||||
writer.addFeature(outFeat)
|
||||
else:
|
||||
fieldIdx = vlayerA.fieldNameIndex(fieldname)
|
||||
unique = vector.getUniqueValues(vlayerA, int(fieldIdx))
|
||||
nFeat = len(unique)
|
||||
myDict = {}
|
||||
attrDict = {}
|
||||
for item in unique:
|
||||
myDict[unicode(item).strip()] = []
|
||||
attrDict[unicode(item).strip()] = None
|
||||
field_indexes = [vlayerA.fieldNameIndex(f) for f in field_names.split(';')]
|
||||
|
||||
unique = None
|
||||
attribute_dict = {}
|
||||
geometry_dict = defaultdict(lambda: [])
|
||||
|
||||
for inFeat in features:
|
||||
attrs = inFeat.attributes()
|
||||
tempItem = attrs[fieldIdx]
|
||||
|
||||
index_attrs = tuple([attrs[i] for i in field_indexes])
|
||||
|
||||
tmpInGeom = QgsGeometry(inFeat.geometry())
|
||||
if tmpInGeom.isGeosEmpty():
|
||||
continue
|
||||
@ -154,16 +151,17 @@ class Dissolve(GeoAlgorithm):
|
||||
'geometry: ')
|
||||
+ error.what())
|
||||
|
||||
if attrDict[unicode(tempItem).strip()] is None:
|
||||
if not index_attrs in attribute_dict:
|
||||
# keep attributes of first feature
|
||||
attrDict[unicode(tempItem).strip()] = attrs
|
||||
attribute_dict[index_attrs] = attrs
|
||||
|
||||
myDict[unicode(tempItem).strip()].append(tmpInGeom)
|
||||
geometry_dict[index_attrs].append(tmpInGeom)
|
||||
|
||||
features = None
|
||||
nFeat = len(attribute_dict)
|
||||
|
||||
nElement = 0
|
||||
for key, value in myDict.items():
|
||||
for key, value in geometry_dict.items():
|
||||
outFeat = QgsFeature()
|
||||
nElement += 1
|
||||
progress.setPercentage(int(nElement * 100 / nFeat))
|
||||
try:
|
||||
@ -172,7 +170,7 @@ class Dissolve(GeoAlgorithm):
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Geometry exception while dissolving'))
|
||||
outFeat.setGeometry(tmpOutGeom)
|
||||
outFeat.setAttributes(attrDict[key])
|
||||
outFeat.setAttributes(attribute_dict[key])
|
||||
writer.addFeature(outFeat)
|
||||
|
||||
del writer
|
||||
|
58
python/plugins/processing/tests/testdata/expected/dissolve_two_fields.gml
vendored
Normal file
58
python/plugins/processing/tests/testdata/expected/dissolve_two_fields.gml
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ dissolve_two_fields.xsd"
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:dissolve_two_fields fid="polys.0">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 -1,-1 -1,3 3,3 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:name>aa</ogr:name>
|
||||
<ogr:intval>1</ogr:intval>
|
||||
<ogr:floatval>44.123456</ogr:floatval>
|
||||
</ogr:dissolve_two_fields>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:dissolve_two_fields fid="polys.1">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.241458733205375,-0.054510556621882 7.241458733205375,-1.054510556621882 5.241458733205375,-1.054510556621882 6.241458733205375,-0.054510556621882</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:name>dd</ogr:name>
|
||||
<ogr:floatval>0</ogr:floatval>
|
||||
</ogr:dissolve_two_fields>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:dissolve_two_fields fid="polys.2">
|
||||
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.172552783109405,4.822648752399233 4.172552783109405,5.822648752399233 5.172552783109405,5.822648752399233 5.172552783109405,4.822648752399233 4.172552783109405,4.822648752399233</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.443378119001919,4.423608445297505 2.443378119001919,5.0 2,5 2,6 3,6 3.0,5.423608445297505 3.443378119001919,5.423608445297505 3.443378119001919,4.423608445297505 2.443378119001919,4.423608445297505</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
|
||||
<ogr:name>bb</ogr:name>
|
||||
<ogr:intval>1</ogr:intval>
|
||||
<ogr:floatval>0.123</ogr:floatval>
|
||||
</ogr:dissolve_two_fields>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:dissolve_two_fields fid="polys.3">
|
||||
<ogr:intval>120</ogr:intval>
|
||||
<ogr:floatval>-100291.43213</ogr:floatval>
|
||||
</ogr:dissolve_two_fields>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:dissolve_two_fields fid="polys.8">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.620729366602688,5.088675623800385 2.620729366602688,6.088675623800385 3.620729366602688,6.088675623800385 3.620729366602688,5.088675623800385 2.620729366602688,5.088675623800385</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:name>bb</ogr:name>
|
||||
<ogr:intval>2</ogr:intval>
|
||||
<ogr:floatval>0.123</ogr:floatval>
|
||||
</ogr:dissolve_two_fields>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:dissolve_two_fields fid="polys.7">
|
||||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8.162955854126682,2.738771593090211 8.162955854126682,3.738771593090211 9.162955854126682,3.738771593090211 9.162955854126682,2.738771593090211 8.162955854126682,2.738771593090211</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
|
||||
<ogr:name>cc</ogr:name>
|
||||
<ogr:floatval>0.123</ogr:floatval>
|
||||
</ogr:dissolve_two_fields>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
@ -304,6 +304,19 @@ tests:
|
||||
name: expected/dissolve_field.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:dissolve
|
||||
name: Dissolve using two fields
|
||||
params:
|
||||
DISSOLVE_ALL: false
|
||||
FIELD: intval;name
|
||||
INPUT:
|
||||
name: dissolve_polys.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/dissolve_two_fields.gml
|
||||
type: vector
|
||||
|
||||
- name: Dissolve with geometries reported as valid but as invalid with isGeosValid
|
||||
algorithm: qgis:dissolve
|
||||
params:
|
||||
|
Loading…
x
Reference in New Issue
Block a user