Port clip algorithm to new API

This commit is contained in:
Nyall Dawson 2017-06-06 15:54:10 +10:00
parent 9038872200
commit f1511a290c
3 changed files with 116 additions and 106 deletions

View File

@ -34,11 +34,14 @@ from qgis.core import (QgsFeature,
QgsFeatureRequest, QgsFeatureRequest,
QgsWkbTypes, QgsWkbTypes,
QgsMessageLog, QgsMessageLog,
QgsProcessingUtils) QgsProcessingUtils,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink,
QgsProcessingOutputVectorLayer,
QgsProcessingParameterDefinition
)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
from processing.tools import dataobjects from processing.tools import dataobjects
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0] pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
@ -58,11 +61,12 @@ class Clip(QgisAlgorithm):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.addParameter(ParameterVector(Clip.INPUT,
self.tr('Input layer'))) self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer')))
self.addParameter(ParameterVector(Clip.OVERLAY, self.addParameter(QgsProcessingParameterFeatureSource(self.OVERLAY, self.tr('Clip layer'), [QgsProcessingParameterDefinition.TypeVectorPolygon]))
self.tr('Clip layer'), [dataobjects.TYPE_VECTOR_POLYGON]))
self.addOutput(OutputVector(Clip.OUTPUT, self.tr('Clipped'))) self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Clipped')))
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Clipped")))
def name(self): def name(self):
return 'clip' return 'clip'
@ -71,17 +75,17 @@ class Clip(QgisAlgorithm):
return self.tr('Clip') return self.tr('Clip')
def processAlgorithm(self, parameters, context, feedback): def processAlgorithm(self, parameters, context, feedback):
source_layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Clip.INPUT), context)
mask_layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Clip.OVERLAY), context)
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(source_layer.fields(), feature_source = self.parameterAsSource(parameters, self.INPUT, context)
QgsWkbTypes.multiType(source_layer.wkbType()), mask_source = self.parameterAsSource(parameters, self.OVERLAY, context)
source_layer.crs(), context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
feature_source.fields(), QgsWkbTypes.multiType(feature_source.wkbType()), feature_source.sourceCrs())
# first build up a list of clip geometries # first build up a list of clip geometries
clip_geoms = [] clip_geoms = []
for maskFeat in QgsProcessingUtils.getFeatures(mask_layer, context, QgsFeatureRequest().setSubsetOfAttributes([])): for mask_feature in mask_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([])):
clip_geoms.append(maskFeat.geometry()) clip_geoms.append(mask_feature.geometry())
# are we clipping against a single feature? if so, we can show finer progress reports # are we clipping against a single feature? if so, we can show finer progress reports
if len(clip_geoms) > 1: if len(clip_geoms) > 1:
@ -98,8 +102,10 @@ class Clip(QgisAlgorithm):
tested_feature_ids = set() tested_feature_ids = set()
for i, clip_geom in enumerate(clip_geoms): for i, clip_geom in enumerate(clip_geoms):
input_features = [f for f in QgsProcessingUtils.getFeatures(source_layer, context, if feedback.isCanceled():
QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))] break
input_features = [f for f in feature_source.getFeatures(QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))]
if not input_features: if not input_features:
continue continue
@ -110,6 +116,9 @@ class Clip(QgisAlgorithm):
total = 0 total = 0
for current, in_feat in enumerate(input_features): for current, in_feat in enumerate(input_features):
if feedback.isCanceled():
break
if not in_feat.geometry(): if not in_feat.geometry():
continue continue
@ -137,7 +146,7 @@ class Clip(QgisAlgorithm):
out_feat = QgsFeature() out_feat = QgsFeature()
out_feat.setGeometry(new_geom) out_feat.setGeometry(new_geom)
out_feat.setAttributes(in_feat.attributes()) out_feat.setAttributes(in_feat.attributes())
writer.addFeature(out_feat) sink.addFeature(out_feat)
except: except:
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more ' QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more '
'output features ignored due to ' 'output features ignored due to '
@ -151,4 +160,4 @@ class Clip(QgisAlgorithm):
# coarse progress report for multiple clip geometries # coarse progress report for multiple clip geometries
feedback.setProgress(100.0 * i / len(clip_geoms)) feedback.setProgress(100.0 * i / len(clip_geoms))
del writer return {self.OUTPUT: dest_id}

View File

@ -75,7 +75,7 @@ from .QgisAlgorithm import QgisAlgorithm
# from .ConvexHull import ConvexHull # from .ConvexHull import ConvexHull
# from .FixedDistanceBuffer import FixedDistanceBuffer # from .FixedDistanceBuffer import FixedDistanceBuffer
# from .VariableDistanceBuffer import VariableDistanceBuffer # from .VariableDistanceBuffer import VariableDistanceBuffer
# from .Clip import Clip from .Clip import Clip
# from .Difference import Difference # from .Difference import Difference
# from .Dissolve import Dissolve # from .Dissolve import Dissolve
# from .Intersection import Intersection # from .Intersection import Intersection
@ -210,7 +210,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(), # PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
# ConvexHull(), FixedDistanceBuffer(), # ConvexHull(), FixedDistanceBuffer(),
# VariableDistanceBuffer(), Dissolve(), Difference(), # VariableDistanceBuffer(), Dissolve(), Difference(),
# Intersection(), Union(), Clip(), ExtentFromLayer(), # Intersection(), Union(), ExtentFromLayer(),
# RandomSelection(), RandomSelectionWithinSubsets(), # RandomSelection(), RandomSelectionWithinSubsets(),
# SelectByLocation(), RandomExtract(), DeleteHoles(), # SelectByLocation(), RandomExtract(), DeleteHoles(),
# RandomExtractWithinSubsets(), ExtractByLocation(), # RandomExtractWithinSubsets(), ExtractByLocation(),
@ -263,7 +263,8 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
Aspect(), Aspect(),
AutoincrementalField(), AutoincrementalField(),
Boundary(), Boundary(),
BoundingBox()] BoundingBox(),
Clip()]
if hasPlotly: if hasPlotly:
# from .VectorLayerHistogram import VectorLayerHistogram # from .VectorLayerHistogram import VectorLayerHistogram

View File

@ -25,90 +25,90 @@ tests:
# name: expected/polys_deleteholes.gml # name: expected/polys_deleteholes.gml
# type: vector # type: vector
# #
# - algorithm: qgis:clip - algorithm: qgis:clip
# name: Clip lines by polygons name: Clip lines by polygons
# params: params:
# INPUT: INPUT:
# name: custom/lines2.gml name: custom/lines2.gml
# type: vector type: vector
# OVERLAY: OVERLAY:
# name: polys.gml name: polys.gml
# type: vector type: vector
# results: results:
# OUTPUT: OUTPUT:
# name: expected/clip_lines_by_polygon.gml name: expected/clip_lines_by_polygon.gml
# type: vector type: vector
#
# - algorithm: qgis:clip - algorithm: qgis:clip
# name: Clip lines by multipolygon name: Clip lines by multipolygon
# params: params:
# INPUT: INPUT:
# name: lines.gml name: lines.gml
# type: vector type: vector
# OVERLAY: OVERLAY:
# name: multipolys.gml name: multipolys.gml
# type: vector type: vector
# results: results:
# OUTPUT: OUTPUT:
# name: expected/clip_lines_by_multipolygon.gml name: expected/clip_lines_by_multipolygon.gml
# type: vector type: vector
#
# - algorithm: qgis:clip - algorithm: qgis:clip
# name: Clip polygons by multipolygons name: Clip polygons by multipolygons
# params: params:
# INPUT: INPUT:
# name: polys.gml name: polys.gml
# type: vector type: vector
# OVERLAY: OVERLAY:
# name: multipolys.gml name: multipolys.gml
# type: vector type: vector
# results: results:
# OUTPUT: OUTPUT:
# name: expected/clip_polys_by_multipolygon.gml name: expected/clip_polys_by_multipolygon.gml
# type: vector type: vector
#
# - algorithm: qgis:clip - algorithm: qgis:clip
# name: Clip multipolygons by polygons name: Clip multipolygons by polygons
# params: params:
# INPUT: INPUT:
# name: multipolys.gml name: multipolys.gml
# type: vector type: vector
# OVERLAY: OVERLAY:
# name: polys.gml name: polys.gml
# type: vector type: vector
# results: results:
# OUTPUT: OUTPUT:
# name: expected/clip_multipolygons_by_polygons.gml name: expected/clip_multipolygons_by_polygons.gml
# type: vector type: vector
#
# - algorithm: qgis:clip - algorithm: qgis:clip
# name: Clip points by polygons name: Clip points by polygons
# params: params:
# INPUT: INPUT:
# name: points.gml name: points.gml
# type: vector type: vector
# OVERLAY: OVERLAY:
# name: polys.gml name: polys.gml
# type: vector type: vector
# results: results:
# OUTPUT: OUTPUT:
# name: expected/clip_points_by_polygons.gml name: expected/clip_points_by_polygons.gml
# type: vector type: vector
#
# - algorithm: qgis:clip - algorithm: qgis:clip
# name: Clip points by multipolygons name: Clip points by multipolygons
# params: params:
# INPUT: INPUT:
# name: points.gml name: points.gml
# type: vector type: vector
# OVERLAY: OVERLAY:
# name: multipolys.gml name: multipolys.gml
# type: vector type: vector
# results: results:
# OUTPUT: OUTPUT:
# name: expected/clip_points_by_multipolygons.gml name: expected/clip_points_by_multipolygons.gml
# type: vector type: vector
#
# # These datasets should produce a geometry collection and not a polygon only # # These datasets should produce a geometry collection and not a polygon only
# # dataset. If the algorithm is fixed, a new test should be introduced to # # dataset. If the algorithm is fixed, a new test should be introduced to
# # check this behavior. # # check this behavior.