Skip to content

Commit f9fabb8

Browse files
authoredAug 2, 2016
Merge pull request #3346 from nyalldawson/processing
Some processing features + fixes
2 parents e259e62 + 4bfdcf0 commit f9fabb8

21 files changed

+678
-40
lines changed
 

‎.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ tests/testdata/raster/band1_float32_noct_epsg4326.tif.aux.xml
6161
tests/testdata/raster/band1_int16_noct_epsg4326.tif.aux.xml
6262
tests/testdata/raster/band3_float32_noct_epsg4326.tif.aux.xml
6363
tests/testdata/raster/band3_int16_noct_epsg4326.tif.aux.xml
64+
python/plugins/processing/tests/testdata/custom/grass7/float_raster.tif.aux.xml
65+
python/plugins/processing/tests/testdata/custom/grass7/raster_1class.tif.aux.xml
6466
Thumb.db

‎python/plugins/processing/algs/help/qgis.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ qgis:meancoordinates: >
225225

226226
If an attribute is selected in the <Unique ID field> parameters, features will be grouped according to values in this field. Instead of a single point with the center of mass of the whole layer, the output layer will contain a center of mass for the features in each category.
227227

228+
qgis:mergelines: >
229+
This algorithm joins all connected parts of MultiLineString geometries into single LineString geometries.
230+
231+
If any parts of the input MultiLineString geometries are not connected, the resultant geometry will be a MultiLineString containing any lines which could be merged and any non-connected line parts.
232+
228233
qgis:mergevectorlayers: >
229234
This algorithm combines two vector layer of the same geometry type into a single one.
230235

‎python/plugins/processing/algs/qgis/Dissolve.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
__revision__ = '$Format:%H$'
2727

2828
import os
29+
from collections import defaultdict
2930

3031
from qgis.PyQt.QtGui import QIcon
3132

@@ -36,7 +37,7 @@
3637
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
3738
from processing.core.parameters import ParameterVector
3839
from processing.core.parameters import ParameterBoolean
39-
from processing.core.parameters import ParameterTableField
40+
from processing.core.parameters import ParameterTableMultipleField
4041
from processing.core.outputs import OutputVector
4142
from processing.tools import vector, dataobjects
4243

@@ -60,22 +61,24 @@ def defineCharacteristics(self):
6061
self.tr('Input layer'),
6162
[ParameterVector.VECTOR_TYPE_POLYGON, ParameterVector.VECTOR_TYPE_LINE]))
6263
self.addParameter(ParameterBoolean(Dissolve.DISSOLVE_ALL,
63-
self.tr('Dissolve all (do not use field)'), True))
64-
self.addParameter(ParameterTableField(Dissolve.FIELD,
65-
self.tr('Unique ID field'), Dissolve.INPUT, optional=True))
64+
self.tr('Dissolve all (do not use fields)'), True))
65+
self.addParameter(ParameterTableMultipleField(Dissolve.FIELD,
66+
self.tr('Unique ID fields'), Dissolve.INPUT, optional=True))
6667
self.addOutput(OutputVector(Dissolve.OUTPUT, self.tr('Dissolved')))
6768

6869
def processAlgorithm(self, progress):
6970
useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
70-
fieldname = self.getParameterValue(Dissolve.FIELD)
71+
field_names = self.getParameterValue(Dissolve.FIELD)
7172
vlayerA = dataobjects.getObjectFromUri(
7273
self.getParameterValue(Dissolve.INPUT))
7374
vproviderA = vlayerA.dataProvider()
74-
fields = vlayerA.fields()
75+
7576
writer = self.getOutputFromName(
76-
Dissolve.OUTPUT).getVectorWriter(fields,
77-
vproviderA.geometryType(),
78-
vproviderA.crs())
77+
Dissolve.OUTPUT).getVectorWriter(
78+
vlayerA.fields().toList(),
79+
vproviderA.geometryType(),
80+
vlayerA.crs())
81+
7982
outFeat = QgsFeature()
8083
features = vector.features(vlayerA)
8184
total = 100.0 / len(features)
@@ -125,20 +128,16 @@ def processAlgorithm(self, progress):
125128
outFeat.setAttributes(attrs)
126129
writer.addFeature(outFeat)
127130
else:
128-
fieldIdx = vlayerA.fieldNameIndex(fieldname)
129-
unique = vector.getUniqueValues(vlayerA, int(fieldIdx))
130-
nFeat = len(unique)
131-
myDict = {}
132-
attrDict = {}
133-
for item in unique:
134-
myDict[unicode(item).strip()] = []
135-
attrDict[unicode(item).strip()] = None
131+
field_indexes = [vlayerA.fieldNameIndex(f) for f in field_names.split(';')]
136132

137-
unique = None
133+
attribute_dict = {}
134+
geometry_dict = defaultdict(lambda: [])
138135

139136
for inFeat in features:
140137
attrs = inFeat.attributes()
141-
tempItem = attrs[fieldIdx]
138+
139+
index_attrs = tuple([attrs[i] for i in field_indexes])
140+
142141
tmpInGeom = QgsGeometry(inFeat.geometry())
143142
if tmpInGeom.isGeosEmpty():
144143
continue
@@ -152,16 +151,17 @@ def processAlgorithm(self, progress):
152151
'geometry: ')
153152
+ error.what())
154153

155-
if attrDict[unicode(tempItem).strip()] is None:
154+
if not index_attrs in attribute_dict:
156155
# keep attributes of first feature
157-
attrDict[unicode(tempItem).strip()] = attrs
156+
attribute_dict[index_attrs] = attrs
158157

159-
myDict[unicode(tempItem).strip()].append(tmpInGeom)
158+
geometry_dict[index_attrs].append(tmpInGeom)
160159

161-
features = None
160+
nFeat = len(attribute_dict)
162161

163162
nElement = 0
164-
for key, value in myDict.items():
163+
for key, value in geometry_dict.items():
164+
outFeat = QgsFeature()
165165
nElement += 1
166166
progress.setPercentage(int(nElement * 100 / nFeat))
167167
try:
@@ -170,7 +170,7 @@ def processAlgorithm(self, progress):
170170
raise GeoAlgorithmExecutionException(
171171
self.tr('Geometry exception while dissolving'))
172172
outFeat.setGeometry(tmpOutGeom)
173-
outFeat.setAttributes(attrDict[key])
173+
outFeat.setAttributes(attribute_dict[key])
174174
writer.addFeature(outFeat)
175175

176176
del writer
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
Smooth.py
6+
---------
7+
Date : July 2016
8+
Copyright : (C) 2016 by Nyall Dawson
9+
Email : nyall dot dawson at gmail dot com
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
__author__ = 'Nyall Dawson'
21+
__date__ = 'July 2016'
22+
__copyright__ = '(C) 2016, Nyall Dawson'
23+
24+
# This will get replaced with a git SHA1 when you do a git archive323
25+
26+
__revision__ = '$Format:%H$'
27+
28+
import os
29+
30+
from qgis.core import QgsFeature
31+
32+
from qgis.PyQt.QtGui import QIcon
33+
34+
from processing.core.GeoAlgorithm import GeoAlgorithm
35+
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
36+
from processing.core.parameters import ParameterVector
37+
from processing.core.outputs import OutputVector
38+
from processing.tools import dataobjects, vector
39+
40+
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
41+
42+
43+
class MergeLines(GeoAlgorithm):
44+
45+
INPUT_LAYER = 'INPUT_LAYER'
46+
OUTPUT_LAYER = 'OUTPUT_LAYER'
47+
48+
def getIcon(self):
49+
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'to_lines.png'))
50+
51+
def defineCharacteristics(self):
52+
self.name, self.i18n_name = self.trAlgorithm('Merge lines')
53+
self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')
54+
55+
self.addParameter(ParameterVector(self.INPUT_LAYER,
56+
self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_LINE]))
57+
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Merged')))
58+
59+
def processAlgorithm(self, progress):
60+
layer = dataobjects.getObjectFromUri(
61+
self.getParameterValue(self.INPUT_LAYER))
62+
provider = layer.dataProvider()
63+
64+
writer = self.getOutputFromName(
65+
self.OUTPUT_LAYER).getVectorWriter(
66+
layer.fields().toList(),
67+
provider.geometryType(),
68+
layer.crs())
69+
70+
features = vector.features(layer)
71+
total = 100.0 / len(features)
72+
73+
for current, inFeat in enumerate(features):
74+
outFeat = QgsFeature()
75+
attrs = inFeat.attributes()
76+
outFeat.setAttributes(attrs)
77+
78+
inGeom = inFeat.geometry()
79+
if inGeom:
80+
outGeom = inGeom.mergeLines()
81+
if outGeom is None:
82+
raise GeoAlgorithmExecutionException(
83+
self.tr('Error merging lines'))
84+
85+
outFeat.setGeometry(outGeom)
86+
87+
writer.addFeature(outFeat)
88+
progress.setPercentage(int(current * total))
89+
90+
del writer

‎python/plugins/processing/algs/qgis/MultipartToSingleparts.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,22 @@ def processAlgorithm(self, progress):
6363
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
6464
layer.pendingFields().toList(), geomType, layer.crs())
6565

66-
outFeat = QgsFeature()
67-
inGeom = QgsGeometry()
68-
6966
features = vector.features(layer)
7067
total = 100.0 / len(features)
7168
for current, f in enumerate(features):
72-
inGeom = f.geometry()
69+
outFeat = QgsFeature()
7370
attrs = f.attributes()
74-
75-
geometries = self.extractAsSingle(inGeom)
7671
outFeat.setAttributes(attrs)
7772

78-
for g in geometries:
79-
outFeat.setGeometry(g)
73+
inGeom = f.geometry()
74+
if inGeom:
75+
geometries = self.extractAsSingle(inGeom)
76+
77+
for g in geometries:
78+
outFeat.setGeometry(g)
79+
writer.addFeature(outFeat)
80+
else:
81+
#input feature with null geometry
8082
writer.addFeature(outFeat)
8183

8284
progress.setPercentage(int(current * total))

‎python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
from .DefineProjection import DefineProjection
147147
from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable
148148
from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
149+
from .MergeLines import MergeLines
149150

150151
pluginPath = os.path.normpath(os.path.join(
151152
os.path.split(os.path.dirname(__file__))[0], os.pardir))
@@ -197,7 +198,7 @@ def __init__(self):
197198
CheckValidity(), OrientedMinimumBoundingBox(), Smooth(),
198199
ReverseLineDirection(), SpatialIndex(), DefineProjection(),
199200
RectanglesOvalsDiamondsVariable(),
200-
RectanglesOvalsDiamondsFixed()
201+
RectanglesOvalsDiamondsFixed(), MergeLines()
201202
]
202203

203204
if hasMatplotlib:

‎python/plugins/processing/gui/ListMultiselectWidget.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
QListWidget,
2424
QAbstractItemView)
2525
from qgis.PyQt.QtGui import QFont
26-
from qgis.PyQt.QtCore import pyqtSignal
26+
from qgis.PyQt.QtCore import Qt, QSize, pyqtSignal
2727

2828

2929
class ListMultiSelectWidget(QGroupBox):
@@ -163,7 +163,7 @@ def _setupUI(self):
163163
self._set_list_widget_defaults(self.unselected_widget)
164164
unselected_label = QLabel()
165165
unselected_label.setText('Unselected')
166-
unselected_label.setAlignment(Qt.Qt.AlignCenter)
166+
unselected_label.setAlignment(Qt.AlignCenter)
167167
unselected_label.setFont(italic_font)
168168
unselected_v_layout = QVBoxLayout()
169169
unselected_v_layout.addWidget(unselected_label)
@@ -174,7 +174,7 @@ def _setupUI(self):
174174
self._set_list_widget_defaults(self.selected_widget)
175175
selected_label = QLabel()
176176
selected_label.setText('Selected')
177-
selected_label.setAlignment(Qt.Qt.AlignCenter)
177+
selected_label.setAlignment(Qt.AlignCenter)
178178
selected_label.setFont(italic_font)
179179
selected_v_layout = QVBoxLayout()
180180
selected_v_layout.addWidget(selected_label)
@@ -215,7 +215,7 @@ def _set_list_widget_defaults(self, widget):
215215
widget.setDragEnabled(True)
216216
widget.setDragDropMode(QAbstractItemView.DragDrop)
217217
widget.setDragDropOverwriteMode(False)
218-
widget.setDefaultDropAction(QtCore.Qt.MoveAction)
218+
widget.setDefaultDropAction(Qt.MoveAction)
219219
widget.setSelectionMode(QAbstractItemView.MultiSelection)
220220

221221

@@ -227,4 +227,4 @@ def __init__(self, text):
227227
buttons_size_policy = QSizePolicy(
228228
QSizePolicy.Fixed, QSizePolicy.Fixed)
229229
self.setSizePolicy(buttons_size_policy)
230-
self.setMaximumSize(QtCore.QSize(30, 30))
230+
self.setMaximumSize(QSize(30, 30))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>dissolve_polys</Name>
4+
<ElementPath>dissolve_polys</ElementPath>
5+
<GeometryType>3</GeometryType>
6+
<SRSName>EPSG:4326</SRSName>
7+
<DatasetSpecificInfo>
8+
<FeatureCount>10</FeatureCount>
9+
<ExtentXMin>-1.00000</ExtentXMin>
10+
<ExtentXMax>9.16296</ExtentXMax>
11+
<ExtentYMin>-3.00000</ExtentYMin>
12+
<ExtentYMax>6.08868</ExtentYMax>
13+
</DatasetSpecificInfo>
14+
<PropertyDefn>
15+
<Name>name</Name>
16+
<ElementPath>name</ElementPath>
17+
<Type>String</Type>
18+
<Width>2</Width>
19+
</PropertyDefn>
20+
<PropertyDefn>
21+
<Name>intval</Name>
22+
<ElementPath>intval</ElementPath>
23+
<Type>Integer</Type>
24+
</PropertyDefn>
25+
<PropertyDefn>
26+
<Name>floatval</Name>
27+
<ElementPath>floatval</ElementPath>
28+
<Type>Real</Type>
29+
</PropertyDefn>
30+
</GMLFeatureClass>
31+
</GMLFeatureClassList>

0 commit comments

Comments
 (0)
Please sign in to comment.