Skip to content

Commit 7132faa

Browse files
committed
Port Topocolor algorithm to new API
1 parent ec4df6c commit 7132faa

File tree

4 files changed

+76
-59
lines changed

4 files changed

+76
-59
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
from .SumLines import SumLines
134134
from .SymmetricalDifference import SymmetricalDifference
135135
from .TextToFloat import TextToFloat
136+
from .TopoColors import TopoColor
136137
from .Translate import Translate
137138
from .TruncateTable import TruncateTable
138139
from .Union import Union
@@ -169,7 +170,6 @@
169170
# from .RasterCalculator import RasterCalculator
170171
# from .ExecuteSQL import ExecuteSQL
171172
# from .FindProjection import FindProjection
172-
# from .TopoColors import TopoColor
173173
# from .EliminateSelection import EliminateSelection
174174

175175
pluginPath = os.path.normpath(os.path.join(
@@ -206,7 +206,7 @@ def getAlgs(self):
206206
# IdwInterpolation(), TinInterpolation(),
207207
# RasterCalculator(),
208208
# ExecuteSQL(), FindProjection(),
209-
# TopoColor(), EliminateSelection()
209+
# EliminateSelection()
210210
# ]
211211
algs = [AddTableField(),
212212
Aspect(),
@@ -301,6 +301,7 @@ def getAlgs(self):
301301
SumLines(),
302302
SymmetricalDifference(),
303303
TextToFloat(),
304+
TopoColor(),
304305
Translate(),
305306
TruncateTable(),
306307
Union(),

python/plugins/processing/algs/qgis/TopoColors.py

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,33 +31,31 @@
3131

3232
from collections import defaultdict
3333

34-
from qgis.core import (QgsApplication,
35-
QgsField,
34+
from qgis.core import (QgsField,
3635
QgsFeatureSink,
3736
QgsGeometry,
3837
QgsSpatialIndex,
3938
QgsPointXY,
4039
NULL,
41-
QgsProcessingUtils)
40+
QgsProcessing,
41+
QgsProcessingParameterFeatureSource,
42+
QgsProcessingParameterNumber,
43+
QgsProcessingParameterEnum,
44+
QgsProcessingParameterFeatureSink)
4245

4346
from qgis.PyQt.QtCore import (QVariant)
4447

4548
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
46-
from processing.core.parameters import (ParameterVector,
47-
ParameterSelection,
48-
ParameterNumber)
49-
from processing.core.outputs import OutputVector
50-
from processing.tools import dataobjects
5149

5250
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
5351

5452

5553
class TopoColor(QgisAlgorithm):
56-
INPUT_LAYER = 'INPUT_LAYER'
54+
INPUT = 'INPUT'
5755
MIN_COLORS = 'MIN_COLORS'
5856
MIN_DISTANCE = 'MIN_DISTANCE'
5957
BALANCE = 'BALANCE'
60-
OUTPUT_LAYER = 'OUTPUT_LAYER'
58+
OUTPUT = 'OUTPUT'
6159

6260
def tags(self):
6361
return self.tr('topocolor,colors,graph,adjacent,assign').split(',')
@@ -69,21 +67,23 @@ def __init__(self):
6967
super().__init__()
7068

7169
def initAlgorithm(self, config=None):
72-
self.addParameter(ParameterVector(self.INPUT_LAYER,
73-
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_POLYGON]))
74-
self.addParameter(ParameterNumber(self.MIN_COLORS,
75-
self.tr('Minimum number of colors'), 1, 1000, 4))
76-
self.addParameter(ParameterNumber(self.MIN_DISTANCE,
77-
self.tr('Minimum distance between features'), 0.0, 999999999.0, 0.0))
70+
71+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
72+
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon]))
73+
self.addParameter(QgsProcessingParameterNumber(self.MIN_COLORS,
74+
self.tr('Minimum number of colors'), minValue=1, maxValue=1000, defaultValue=4))
75+
self.addParameter(QgsProcessingParameterNumber(self.MIN_DISTANCE,
76+
self.tr('Minimum distance between features'), type=QgsProcessingParameterNumber.Double,
77+
minValue=0.0, maxValue=999999999.0, defaultValue=0.0))
7878
balance_by = [self.tr('By feature count'),
7979
self.tr('By assigned area'),
8080
self.tr('By distance between colors')]
81-
self.addParameter(ParameterSelection(
81+
self.addParameter(QgsProcessingParameterEnum(
8282
self.BALANCE,
8383
self.tr('Balance color assignment'),
84-
balance_by, default=0))
84+
options=balance_by, defaultValue=0))
8585

86-
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Colored'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))
86+
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Colored'), QgsProcessing.TypeVectorPolygon))
8787

8888
def name(self):
8989
return 'topologicalcoloring'
@@ -92,18 +92,18 @@ def displayName(self):
9292
return self.tr('Topological coloring')
9393

9494
def processAlgorithm(self, parameters, context, feedback):
95-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
96-
min_colors = self.getParameterValue(self.MIN_COLORS)
97-
balance_by = self.getParameterValue(self.BALANCE)
98-
min_distance = self.getParameterValue(self.MIN_DISTANCE)
95+
source = self.parameterAsSource(parameters, self.INPUT, context)
96+
min_colors = self.parameterAsInt(parameters, self.MIN_COLORS, context)
97+
balance_by = self.parameterAsEnum(parameters, self.BALANCE, context)
98+
min_distance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context)
9999

100-
fields = layer.fields()
100+
fields = source.fields()
101101
fields.append(QgsField('color_id', QVariant.Int))
102102

103-
writer = self.getOutputFromName(
104-
self.OUTPUT_LAYER).getVectorWriter(fields, layer.wkbType(), layer.crs(), context)
103+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
104+
fields, source.wkbType(), source.sourceCrs())
105105

106-
features = {f.id(): f for f in QgsProcessingUtils.getFeatures(layer, context)}
106+
features = {f.id(): f for f in source.getFeatures()}
107107

108108
topology, id_graph = self.compute_graph(features, feedback, min_distance=min_distance)
109109
feature_colors = ColoringAlgorithm.balanced(features,
@@ -118,6 +118,9 @@ def processAlgorithm(self, parameters, context, feedback):
118118
total = 20.0 / len(features)
119119
current = 0
120120
for feature_id, input_feature in features.items():
121+
if feedback.isCanceled():
122+
break
123+
121124
output_feature = input_feature
122125
attributes = input_feature.attributes()
123126
if feature_id in feature_colors:
@@ -126,11 +129,11 @@ def processAlgorithm(self, parameters, context, feedback):
126129
attributes.append(NULL)
127130
output_feature.setAttributes(attributes)
128131

129-
writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
132+
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
130133
current += 1
131134
feedback.setProgress(80 + int(current * total))
132135

133-
del writer
136+
return {self.OUTPUT: dest_id}
134137

135138
@staticmethod
136139
def compute_graph(features, feedback, create_id_graph=False, min_distance=0):
@@ -148,6 +151,9 @@ def compute_graph(features, feedback, create_id_graph=False, min_distance=0):
148151

149152
i = 0
150153
for feature_id, f in features_with_geometry.items():
154+
if feedback.isCanceled():
155+
break
156+
151157
g = f.geometry()
152158
if min_distance > 0:
153159
g = g.buffer(min_distance, 5)
@@ -172,6 +178,9 @@ def compute_graph(features, feedback, create_id_graph=False, min_distance=0):
172178
feedback.setProgress(int(i * total))
173179

174180
for feature_id, f in features_with_geometry.items():
181+
if feedback.isCanceled():
182+
break
183+
175184
if feature_id not in s.node_edge:
176185
s.add_edge(feature_id, None)
177186

@@ -206,6 +215,9 @@ def balanced(features, graph, feedback, balance=0, min_colors=4):
206215
i = 0
207216

208217
for (feature_id, n) in sorted_by_count:
218+
if feedback.isCanceled():
219+
break
220+
209221
# first work out which already assigned colors are adjacent to this feature
210222
adjacent_colors = set()
211223
for neighbour in graph.node_edge[feature_id]:
@@ -240,6 +252,9 @@ def balanced(features, graph, feedback, balance=0, min_colors=4):
240252
# loop through these, and calculate the minimum distance from this feature to the nearest
241253
# feature with each assigned color
242254
for other_feature_id, c in other_features.items():
255+
if feedback.isCanceled():
256+
break
257+
243258
other_geometry = features[other_feature_id].geometry()
244259
other_centroid = QgsPointXY(other_geometry.centroid().geometry())
245260

python/plugins/processing/tests/testdata/expected/topocolor_polys.gml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<ogr:right>8.23935</ogr:right>
4242
<ogr:bottom>-3.11331</ogr:bottom>
4343
<ogr:id>11</ogr:id>
44-
<ogr:color_id>4</ogr:color_id>
44+
<ogr:color_id>5</ogr:color_id>
4545
</ogr:topocolor_polys>
4646
</gml:featureMember>
4747
<gml:featureMember>
@@ -52,7 +52,7 @@
5252
<ogr:right>8.23935</ogr:right>
5353
<ogr:bottom>-6.11331</ogr:bottom>
5454
<ogr:id>12</ogr:id>
55-
<ogr:color_id>5</ogr:color_id>
55+
<ogr:color_id>4</ogr:color_id>
5656
</ogr:topocolor_polys>
5757
</gml:featureMember>
5858
<gml:featureMember>

python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,32 +2598,33 @@ tests:
25982598
name: expected/polygon_from_extent.gml
25992599
type: vector
26002600

2601-
# - algorithm: qgis:topologicalcoloring
2602-
# name: Topological coloring
2603-
# params:
2604-
# INPUT_LAYER:
2605-
# name: custom/adjacent_polys.gml
2606-
# type: vector
2607-
# MIN_COLORS: 4
2608-
# results:
2609-
# OUTPUT_LAYER:
2610-
# name: expected/topocolor_polys.gml
2611-
# type: vector
2612-
#
2613-
# - algorithm: qgis:topologicalcoloring
2614-
# name: Topological coloring w/ min distance
2615-
# params:
2616-
# BALANCE: '0'
2617-
# INPUT_LAYER:
2618-
# name: custom/adjacent_polys.gml
2619-
# type: vector
2620-
# MIN_COLORS: 4
2621-
# MIN_DISTANCE: 4.0
2622-
# results:
2623-
# OUTPUT_LAYER:
2624-
# name: expected/topocolor_polys_min_dist.gml
2625-
# type: vector
2626-
#
2601+
- algorithm: qgis:topologicalcoloring
2602+
name: Topological coloring
2603+
params:
2604+
BALANCE: 0
2605+
INPUT:
2606+
name: custom/adjacent_polys.gml
2607+
type: vector
2608+
MIN_COLORS: 4
2609+
results:
2610+
OUTPUT:
2611+
name: expected/topocolor_polys.gml
2612+
type: vector
2613+
2614+
- algorithm: qgis:topologicalcoloring
2615+
name: Topological coloring w/ min distance
2616+
params:
2617+
BALANCE: 0
2618+
INPUT:
2619+
name: custom/adjacent_polys.gml
2620+
type: vector
2621+
MIN_COLORS: 4
2622+
MIN_DISTANCE: 4.0
2623+
results:
2624+
OUTPUT:
2625+
name: expected/topocolor_polys_min_dist.gml
2626+
type: vector
2627+
26272628
- algorithm: qgis:regularpoints
26282629
name: Regular point with standard extent
26292630
params:

0 commit comments

Comments
 (0)