Skip to content

Commit

Permalink
Port clip algorithm to new API
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 6, 2017
1 parent 9038872 commit f1511a2
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 106 deletions.
47 changes: 28 additions & 19 deletions python/plugins/processing/algs/qgis/Clip.py
Expand Up @@ -34,11 +34,14 @@
QgsFeatureRequest,
QgsWkbTypes,
QgsMessageLog,
QgsProcessingUtils)
QgsProcessingUtils,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink,
QgsProcessingOutputVectorLayer,
QgsProcessingParameterDefinition
)

from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
from processing.tools import dataobjects

pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
Expand All @@ -58,11 +61,12 @@ def group(self):

def __init__(self):
super().__init__()
self.addParameter(ParameterVector(Clip.INPUT,
self.tr('Input layer')))
self.addParameter(ParameterVector(Clip.OVERLAY,
self.tr('Clip layer'), [dataobjects.TYPE_VECTOR_POLYGON]))
self.addOutput(OutputVector(Clip.OUTPUT, self.tr('Clipped')))

self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer')))
self.addParameter(QgsProcessingParameterFeatureSource(self.OVERLAY, self.tr('Clip layer'), [QgsProcessingParameterDefinition.TypeVectorPolygon]))

self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Clipped')))
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Clipped")))

def name(self):
return 'clip'
Expand All @@ -71,17 +75,17 @@ def displayName(self):
return self.tr('Clip')

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(),
QgsWkbTypes.multiType(source_layer.wkbType()),
source_layer.crs(), context)
feature_source = self.parameterAsSource(parameters, self.INPUT, context)
mask_source = self.parameterAsSource(parameters, self.OVERLAY, 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
clip_geoms = []
for maskFeat in QgsProcessingUtils.getFeatures(mask_layer, context, QgsFeatureRequest().setSubsetOfAttributes([])):
clip_geoms.append(maskFeat.geometry())
for mask_feature in mask_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([])):
clip_geoms.append(mask_feature.geometry())

# are we clipping against a single feature? if so, we can show finer progress reports
if len(clip_geoms) > 1:
Expand All @@ -98,8 +102,10 @@ def processAlgorithm(self, parameters, context, feedback):
tested_feature_ids = set()

for i, clip_geom in enumerate(clip_geoms):
input_features = [f for f in QgsProcessingUtils.getFeatures(source_layer, context,
QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))]
if feedback.isCanceled():
break

input_features = [f for f in feature_source.getFeatures(QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))]

if not input_features:
continue
Expand All @@ -110,6 +116,9 @@ def processAlgorithm(self, parameters, context, feedback):
total = 0

for current, in_feat in enumerate(input_features):
if feedback.isCanceled():
break

if not in_feat.geometry():
continue

Expand Down Expand Up @@ -137,7 +146,7 @@ def processAlgorithm(self, parameters, context, feedback):
out_feat = QgsFeature()
out_feat.setGeometry(new_geom)
out_feat.setAttributes(in_feat.attributes())
writer.addFeature(out_feat)
sink.addFeature(out_feat)
except:
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more '
'output features ignored due to '
Expand All @@ -151,4 +160,4 @@ def processAlgorithm(self, parameters, context, feedback):
# coarse progress report for multiple clip geometries
feedback.setProgress(100.0 * i / len(clip_geoms))

del writer
return {self.OUTPUT: dest_id}
7 changes: 4 additions & 3 deletions python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
Expand Up @@ -75,7 +75,7 @@
# from .ConvexHull import ConvexHull
# from .FixedDistanceBuffer import FixedDistanceBuffer
# from .VariableDistanceBuffer import VariableDistanceBuffer
# from .Clip import Clip
from .Clip import Clip
# from .Difference import Difference
# from .Dissolve import Dissolve
# from .Intersection import Intersection
Expand Down Expand Up @@ -210,7 +210,7 @@ def getAlgs(self):
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
# ConvexHull(), FixedDistanceBuffer(),
# VariableDistanceBuffer(), Dissolve(), Difference(),
# Intersection(), Union(), Clip(), ExtentFromLayer(),
# Intersection(), Union(), ExtentFromLayer(),
# RandomSelection(), RandomSelectionWithinSubsets(),
# SelectByLocation(), RandomExtract(), DeleteHoles(),
# RandomExtractWithinSubsets(), ExtractByLocation(),
Expand Down Expand Up @@ -263,7 +263,8 @@ def getAlgs(self):
Aspect(),
AutoincrementalField(),
Boundary(),
BoundingBox()]
BoundingBox(),
Clip()]

if hasPlotly:
# from .VectorLayerHistogram import VectorLayerHistogram
Expand Down
168 changes: 84 additions & 84 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -25,90 +25,90 @@ tests:
# name: expected/polys_deleteholes.gml
# type: vector
#
# - algorithm: qgis:clip
# name: Clip lines by polygons
# params:
# INPUT:
# name: custom/lines2.gml
# type: vector
# OVERLAY:
# name: polys.gml
# type: vector
# results:
# OUTPUT:
# name: expected/clip_lines_by_polygon.gml
# type: vector
#
# - algorithm: qgis:clip
# name: Clip lines by multipolygon
# params:
# INPUT:
# name: lines.gml
# type: vector
# OVERLAY:
# name: multipolys.gml
# type: vector
# results:
# OUTPUT:
# name: expected/clip_lines_by_multipolygon.gml
# type: vector
#
# - algorithm: qgis:clip
# name: Clip polygons by multipolygons
# params:
# INPUT:
# name: polys.gml
# type: vector
# OVERLAY:
# name: multipolys.gml
# type: vector
# results:
# OUTPUT:
# name: expected/clip_polys_by_multipolygon.gml
# type: vector
#
# - algorithm: qgis:clip
# name: Clip multipolygons by polygons
# params:
# INPUT:
# name: multipolys.gml
# type: vector
# OVERLAY:
# name: polys.gml
# type: vector
# results:
# OUTPUT:
# name: expected/clip_multipolygons_by_polygons.gml
# type: vector
#
# - algorithm: qgis:clip
# name: Clip points by polygons
# params:
# INPUT:
# name: points.gml
# type: vector
# OVERLAY:
# name: polys.gml
# type: vector
# results:
# OUTPUT:
# name: expected/clip_points_by_polygons.gml
# type: vector
#
# - algorithm: qgis:clip
# name: Clip points by multipolygons
# params:
# INPUT:
# name: points.gml
# type: vector
# OVERLAY:
# name: multipolys.gml
# type: vector
# results:
# OUTPUT:
# name: expected/clip_points_by_multipolygons.gml
# type: vector
#
- algorithm: qgis:clip
name: Clip lines by polygons
params:
INPUT:
name: custom/lines2.gml
type: vector
OVERLAY:
name: polys.gml
type: vector
results:
OUTPUT:
name: expected/clip_lines_by_polygon.gml
type: vector

- algorithm: qgis:clip
name: Clip lines by multipolygon
params:
INPUT:
name: lines.gml
type: vector
OVERLAY:
name: multipolys.gml
type: vector
results:
OUTPUT:
name: expected/clip_lines_by_multipolygon.gml
type: vector

- algorithm: qgis:clip
name: Clip polygons by multipolygons
params:
INPUT:
name: polys.gml
type: vector
OVERLAY:
name: multipolys.gml
type: vector
results:
OUTPUT:
name: expected/clip_polys_by_multipolygon.gml
type: vector

- algorithm: qgis:clip
name: Clip multipolygons by polygons
params:
INPUT:
name: multipolys.gml
type: vector
OVERLAY:
name: polys.gml
type: vector
results:
OUTPUT:
name: expected/clip_multipolygons_by_polygons.gml
type: vector

- algorithm: qgis:clip
name: Clip points by polygons
params:
INPUT:
name: points.gml
type: vector
OVERLAY:
name: polys.gml
type: vector
results:
OUTPUT:
name: expected/clip_points_by_polygons.gml
type: vector

- algorithm: qgis:clip
name: Clip points by multipolygons
params:
INPUT:
name: points.gml
type: vector
OVERLAY:
name: multipolys.gml
type: vector
results:
OUTPUT:
name: expected/clip_points_by_multipolygons.gml
type: vector

# # 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
# # check this behavior.
Expand Down

0 comments on commit f1511a2

Please sign in to comment.