Skip to content

Commit becf690

Browse files
committed
Port extract specific nodes algorithm to new API
Improvements: - keep Z/M values if present in geometries
1 parent ecaee1a commit becf690

File tree

3 files changed

+64
-57
lines changed

3 files changed

+64
-57
lines changed

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

+33-26
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,23 @@
2727

2828
import math
2929
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
30-
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
31-
from processing.core.parameters import ParameterVector, ParameterString
32-
from processing.core.outputs import OutputVector
33-
from processing.tools import dataobjects
3430

3531
from qgis.core import (QgsWkbTypes,
3632
QgsFeature,
3733
QgsFeatureSink,
3834
QgsGeometry,
3935
QgsField,
40-
QgsApplication,
41-
QgsProcessingUtils)
36+
QgsProcessing,
37+
QgsProcessingParameterFeatureSource,
38+
QgsProcessingParameterString,
39+
QgsProcessingParameterFeatureSink,
40+
QgsProcessingException)
4241
from qgis.PyQt.QtCore import QVariant
4342

4443

4544
class ExtractSpecificNodes(QgisAlgorithm):
46-
47-
INPUT_LAYER = 'INPUT_LAYER'
48-
OUTPUT_LAYER = 'OUTPUT_LAYER'
45+
INPUT = 'INPUT'
46+
OUTPUT = 'OUTPUT'
4947
NODES = 'NODES'
5048

5149
def group(self):
@@ -55,11 +53,12 @@ def __init__(self):
5553
super().__init__()
5654

5755
def initAlgorithm(self, config=None):
58-
self.addParameter(ParameterVector(self.INPUT_LAYER,
59-
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_ANY]))
60-
self.addParameter(ParameterString(self.NODES,
61-
self.tr('Node indices'), default='0'))
62-
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Nodes'), datatype=[dataobjects.TYPE_VECTOR_POINT]))
56+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
57+
self.tr('Input layer'), [QgsProcessing.TypeVectorAny]))
58+
self.addParameter(QgsProcessingParameterString(self.NODES,
59+
self.tr('Node indices'), defaultValue='0'))
60+
61+
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Nodes'), QgsProcessing.TypeVectorPoint))
6362

6463
def name(self):
6564
return 'extractspecificnodes'
@@ -68,34 +67,42 @@ def displayName(self):
6867
return self.tr('Extract specific nodes')
6968

7069
def processAlgorithm(self, parameters, context, feedback):
71-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
72-
73-
fields = layer.fields()
70+
source = self.parameterAsSource(parameters, self.INPUT, context)
71+
fields = source.fields()
7472
fields.append(QgsField('node_pos', QVariant.Int))
7573
fields.append(QgsField('node_index', QVariant.Int))
7674
fields.append(QgsField('distance', QVariant.Double))
7775
fields.append(QgsField('angle', QVariant.Double))
76+
fields.append(QgsField('NUM_FIELD', QVariant.Int))
77+
78+
wkb_type = QgsWkbTypes.Point
79+
if QgsWkbTypes.hasM(source.wkbType()):
80+
wkb_type = QgsWkbTypes.addM(wkb_type)
81+
if QgsWkbTypes.hasZ(source.wkbType()):
82+
wkb_type = QgsWkbTypes.addZ(wkb_type)
7883

79-
writer = self.getOutputFromName(
80-
self.OUTPUT_LAYER).getVectorWriter(fields, QgsWkbTypes.Point, layer.crs(), context)
84+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
85+
fields, wkb_type, source.sourceCrs())
8186

82-
node_indices_string = self.getParameterValue(self.NODES)
87+
node_indices_string = self.parameterAsString(parameters, self.NODES, context)
8388
indices = []
8489
for node in node_indices_string.split(','):
8590
try:
8691
indices.append(int(node))
8792
except:
88-
raise GeoAlgorithmExecutionException(
93+
raise QgsProcessingException(
8994
self.tr('\'{}\' is not a valid node index').format(node))
9095

91-
features = QgsProcessingUtils.getFeatures(layer, context)
92-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
96+
features = source.getFeatures()
97+
total = 100.0 / source.featureCount() if source.featureCount() else 0
9398

9499
for current, f in enumerate(features):
100+
if feedback.isCanceled():
101+
break
95102

96103
input_geometry = f.geometry()
97104
if not input_geometry:
98-
writer.addFeature(f, QgsFeatureSink.FastInsert)
105+
sink.addFeature(f, QgsFeatureSink.FastInsert)
99106
else:
100107
total_nodes = input_geometry.geometry().nCoordinates()
101108

@@ -122,8 +129,8 @@ def processAlgorithm(self, parameters, context, feedback):
122129
point = input_geometry.vertexAt(node_index)
123130
output_feature.setGeometry(QgsGeometry(point))
124131

125-
writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
132+
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
126133

127134
feedback.setProgress(int(current * total))
128135

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

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
from .ExtendLines import ExtendLines
6666
from .ExtentFromLayer import ExtentFromLayer
6767
from .ExtractNodes import ExtractNodes
68+
from .ExtractSpecificNodes import ExtractSpecificNodes
6869
from .FixGeometry import FixGeometry
6970
from .GeometryByExpression import GeometryByExpression
7071
from .GridPolygon import GridPolygon
@@ -165,7 +166,6 @@
165166
# from .Relief import Relief
166167
# from .IdwInterpolation import IdwInterpolation
167168
# from .TinInterpolation import TinInterpolation
168-
# from .ExtractSpecificNodes import ExtractSpecificNodes
169169
# from .RasterCalculator import RasterCalculator
170170
# from .ExecuteSQL import ExecuteSQL
171171
# from .FindProjection import FindProjection
@@ -211,7 +211,6 @@ def getAlgs(self):
211211
# PointsAlongGeometry(),
212212
# Relief(),
213213
# IdwInterpolation(), TinInterpolation(),
214-
# ExtractSpecificNodes(),
215214
# RasterCalculator(),
216215
# ExecuteSQL(), FindProjection(),
217216
# TopoColor(), EliminateSelection()
@@ -241,6 +240,7 @@ def getAlgs(self):
241240
ExtendLines(),
242241
ExtentFromLayer(),
243242
ExtractNodes(),
243+
ExtractSpecificNodes(),
244244
FixGeometry(),
245245
GeometryByExpression(),
246246
GridPolygon(),

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

+29-29
Original file line numberDiff line numberDiff line change
@@ -1412,35 +1412,35 @@ tests:
14121412
name: expected/extend_multilines.gml
14131413
type: vector
14141414

1415-
# - algorithm: qgis:extractspecificnodes
1416-
# name: Extract specific nodes lines
1417-
# params:
1418-
# INPUT_LAYER:
1419-
# name: lines.gml
1420-
# type: vector
1421-
# NODES: 0,-1,2,-2
1422-
# results:
1423-
# OUTPUT_LAYER:
1424-
# name: expected/extract_specific_nodes_lines.gml
1425-
# type: vector
1426-
# compare:
1427-
# fields:
1428-
# fid: skip
1429-
#
1430-
# - algorithm: qgis:extractspecificnodes
1431-
# name: Extract specific nodes polygons
1432-
# params:
1433-
# INPUT_LAYER:
1434-
# name: polys.gml
1435-
# type: vector
1436-
# NODES: 0,-1,5,-5
1437-
# results:
1438-
# OUTPUT_LAYER:
1439-
# name: expected/extract_specific_nodes_polys.gml
1440-
# type: vector
1441-
# compare:
1442-
# fields:
1443-
# fid: skip
1415+
- algorithm: qgis:extractspecificnodes
1416+
name: Extract specific nodes lines
1417+
params:
1418+
INPUT:
1419+
name: lines.gml
1420+
type: vector
1421+
NODES: 0,-1,2,-2
1422+
results:
1423+
OUTPUT:
1424+
name: expected/extract_specific_nodes_lines.gml
1425+
type: vector
1426+
compare:
1427+
fields:
1428+
fid: skip
1429+
1430+
- algorithm: qgis:extractspecificnodes
1431+
name: Extract specific nodes polygons
1432+
params:
1433+
INPUT:
1434+
name: polys.gml
1435+
type: vector
1436+
NODES: 0,-1,5,-5
1437+
results:
1438+
OUTPUT:
1439+
name: expected/extract_specific_nodes_polys.gml
1440+
type: vector
1441+
compare:
1442+
fields:
1443+
fid: skip
14441444

14451445
- algorithm: qgis:geometrybyexpression
14461446
name: Geometry by expression (point)

0 commit comments

Comments
 (0)