Skip to content
Permalink
Browse files

Port extract specific nodes algorithm to new API

Improvements:
- keep Z/M values if present in geometries
  • Loading branch information
nyalldawson committed Jul 28, 2017
1 parent ecaee1a commit becf6904b17ce292863235b4ccd86fdeca237ade
@@ -27,25 +27,23 @@

import math
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector, ParameterString
from processing.core.outputs import OutputVector
from processing.tools import dataobjects

from qgis.core import (QgsWkbTypes,
QgsFeature,
QgsFeatureSink,
QgsGeometry,
QgsField,
QgsApplication,
QgsProcessingUtils)
QgsProcessing,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterString,
QgsProcessingParameterFeatureSink,
QgsProcessingException)
from qgis.PyQt.QtCore import QVariant


class ExtractSpecificNodes(QgisAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'
INPUT = 'INPUT'
OUTPUT = 'OUTPUT'
NODES = 'NODES'

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

def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_ANY]))
self.addParameter(ParameterString(self.NODES,
self.tr('Node indices'), default='0'))
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Nodes'), datatype=[dataobjects.TYPE_VECTOR_POINT]))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer'), [QgsProcessing.TypeVectorAny]))
self.addParameter(QgsProcessingParameterString(self.NODES,
self.tr('Node indices'), defaultValue='0'))

self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Nodes'), QgsProcessing.TypeVectorPoint))

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

def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)

fields = layer.fields()
source = self.parameterAsSource(parameters, self.INPUT, context)
fields = source.fields()
fields.append(QgsField('node_pos', QVariant.Int))
fields.append(QgsField('node_index', QVariant.Int))
fields.append(QgsField('distance', QVariant.Double))
fields.append(QgsField('angle', QVariant.Double))
fields.append(QgsField('NUM_FIELD', QVariant.Int))

wkb_type = QgsWkbTypes.Point
if QgsWkbTypes.hasM(source.wkbType()):
wkb_type = QgsWkbTypes.addM(wkb_type)
if QgsWkbTypes.hasZ(source.wkbType()):
wkb_type = QgsWkbTypes.addZ(wkb_type)

writer = self.getOutputFromName(
self.OUTPUT_LAYER).getVectorWriter(fields, QgsWkbTypes.Point, layer.crs(), context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, wkb_type, source.sourceCrs())

node_indices_string = self.getParameterValue(self.NODES)
node_indices_string = self.parameterAsString(parameters, self.NODES, context)
indices = []
for node in node_indices_string.split(','):
try:
indices.append(int(node))
except:
raise GeoAlgorithmExecutionException(
raise QgsProcessingException(
self.tr('\'{}\' is not a valid node index').format(node))

features = QgsProcessingUtils.getFeatures(layer, context)
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
features = source.getFeatures()
total = 100.0 / source.featureCount() if source.featureCount() else 0

for current, f in enumerate(features):
if feedback.isCanceled():
break

input_geometry = f.geometry()
if not input_geometry:
writer.addFeature(f, QgsFeatureSink.FastInsert)
sink.addFeature(f, QgsFeatureSink.FastInsert)
else:
total_nodes = input_geometry.geometry().nCoordinates()

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

writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)

feedback.setProgress(int(current * total))

del writer
return {self.OUTPUT: dest_id}
@@ -65,6 +65,7 @@
from .ExtendLines import ExtendLines
from .ExtentFromLayer import ExtentFromLayer
from .ExtractNodes import ExtractNodes
from .ExtractSpecificNodes import ExtractSpecificNodes
from .FixGeometry import FixGeometry
from .GeometryByExpression import GeometryByExpression
from .GridPolygon import GridPolygon
@@ -165,7 +166,6 @@
# from .Relief import Relief
# from .IdwInterpolation import IdwInterpolation
# from .TinInterpolation import TinInterpolation
# from .ExtractSpecificNodes import ExtractSpecificNodes
# from .RasterCalculator import RasterCalculator
# from .ExecuteSQL import ExecuteSQL
# from .FindProjection import FindProjection
@@ -211,7 +211,6 @@ def getAlgs(self):
# PointsAlongGeometry(),
# Relief(),
# IdwInterpolation(), TinInterpolation(),
# ExtractSpecificNodes(),
# RasterCalculator(),
# ExecuteSQL(), FindProjection(),
# TopoColor(), EliminateSelection()
@@ -241,6 +240,7 @@ def getAlgs(self):
ExtendLines(),
ExtentFromLayer(),
ExtractNodes(),
ExtractSpecificNodes(),
FixGeometry(),
GeometryByExpression(),
GridPolygon(),
@@ -1412,35 +1412,35 @@ tests:
name: expected/extend_multilines.gml
type: vector

# - algorithm: qgis:extractspecificnodes
# name: Extract specific nodes lines
# params:
# INPUT_LAYER:
# name: lines.gml
# type: vector
# NODES: 0,-1,2,-2
# results:
# OUTPUT_LAYER:
# name: expected/extract_specific_nodes_lines.gml
# type: vector
# compare:
# fields:
# fid: skip
#
# - algorithm: qgis:extractspecificnodes
# name: Extract specific nodes polygons
# params:
# INPUT_LAYER:
# name: polys.gml
# type: vector
# NODES: 0,-1,5,-5
# results:
# OUTPUT_LAYER:
# name: expected/extract_specific_nodes_polys.gml
# type: vector
# compare:
# fields:
# fid: skip
- algorithm: qgis:extractspecificnodes
name: Extract specific nodes lines
params:
INPUT:
name: lines.gml
type: vector
NODES: 0,-1,2,-2
results:
OUTPUT:
name: expected/extract_specific_nodes_lines.gml
type: vector
compare:
fields:
fid: skip

- algorithm: qgis:extractspecificnodes
name: Extract specific nodes polygons
params:
INPUT:
name: polys.gml
type: vector
NODES: 0,-1,5,-5
results:
OUTPUT:
name: expected/extract_specific_nodes_polys.gml
type: vector
compare:
fields:
fid: skip

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

0 comments on commit becf690

Please sign in to comment.
You can’t perform that action at this time.