Port single sided buffer to new API

This commit is contained in:
Nyall Dawson 2017-07-20 14:53:02 +10:00
parent 4a935c1090
commit 1cac3bb635
3 changed files with 111 additions and 120 deletions

View File

@ -96,6 +96,7 @@ from .ShortestPathLayerToPoint import ShortestPathLayerToPoint
from .ShortestPathPointToLayer import ShortestPathPointToLayer from .ShortestPathPointToLayer import ShortestPathPointToLayer
from .ShortestPathPointToPoint import ShortestPathPointToPoint from .ShortestPathPointToPoint import ShortestPathPointToPoint
from .SimplifyGeometries import SimplifyGeometries from .SimplifyGeometries import SimplifyGeometries
from .SingleSidedBuffer import SingleSidedBuffer
from .Slope import Slope from .Slope import Slope
from .Smooth import Smooth from .Smooth import Smooth
from .SnapGeometries import SnapGeometriesToLayer from .SnapGeometries import SnapGeometriesToLayer
@ -157,7 +158,6 @@ from .ZonalStatistics import ZonalStatistics
# from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable # from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable
# from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed # from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
# from .MergeLines import MergeLines # from .MergeLines import MergeLines
# from .SingleSidedBuffer import SingleSidedBuffer
# from .PointsAlongGeometry import PointsAlongGeometry # from .PointsAlongGeometry import PointsAlongGeometry
# from .Relief import Relief # from .Relief import Relief
# from .IdwInterpolation import IdwInterpolation # from .IdwInterpolation import IdwInterpolation
@ -218,7 +218,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
# RectanglesOvalsDiamondsVariable(), # RectanglesOvalsDiamondsVariable(),
# RectanglesOvalsDiamondsFixed(), MergeLines(), # RectanglesOvalsDiamondsFixed(), MergeLines(),
# #
# SingleSidedBuffer(), PointsAlongGeometry(), # PointsAlongGeometry(),
# Relief(), # Relief(),
# IdwInterpolation(), TinInterpolation(), # IdwInterpolation(), TinInterpolation(),
# ExtendLines(), ExtractSpecificNodes(), # ExtendLines(), ExtractSpecificNodes(),
@ -286,6 +286,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
ShortestPathPointToLayer(), ShortestPathPointToLayer(),
ShortestPathPointToPoint(), ShortestPathPointToPoint(),
SimplifyGeometries(), SimplifyGeometries(),
SingleSidedBuffer(),
Slope(), Slope(),
Smooth(), Smooth(),
SnapGeometriesToLayer(), SnapGeometriesToLayer(),

View File

@ -25,27 +25,17 @@ __copyright__ = '(C) 2016, Nyall Dawson'
__revision__ = '$Format:%H$' __revision__ = '$Format:%H$'
import os from qgis.core import (QgsGeometry,
from qgis.core import (QgsApplication,
QgsGeometry,
QgsFeatureSink,
QgsWkbTypes, QgsWkbTypes,
QgsProcessingUtils) QgsProcessing,
QgsProcessingParameterNumber,
QgsProcessingParameterEnum,
QgsProcessingException)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector, ParameterSelection, ParameterNumber
from processing.core.outputs import OutputVector
from processing.tools import dataobjects
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
class SingleSidedBuffer(QgisAlgorithm): class SingleSidedBuffer(QgisFeatureBasedAlgorithm):
INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'
DISTANCE = 'DISTANCE' DISTANCE = 'DISTANCE'
SIDE = 'SIDE' SIDE = 'SIDE'
SEGMENTS = 'SEGMENTS' SEGMENTS = 'SEGMENTS'
@ -57,33 +47,35 @@ class SingleSidedBuffer(QgisAlgorithm):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.distance = None
def initAlgorithm(self, config=None): self.segments = None
self.addParameter(ParameterVector(self.INPUT_LAYER, self.join_style = None
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_LINE])) self.side = None
self.addParameter(ParameterNumber(self.DISTANCE, self.miter_limit = None
self.tr('Distance'), default=10.0))
self.sides = [self.tr('Left'), self.sides = [self.tr('Left'),
'Right'] 'Right']
self.addParameter(ParameterSelection(
self.SIDE,
self.tr('Side'),
self.sides))
self.addParameter(ParameterNumber(self.SEGMENTS,
self.tr('Segments'), 1, default=8))
self.join_styles = [self.tr('Round'), self.join_styles = [self.tr('Round'),
'Mitre', 'Mitre',
'Bevel'] 'Bevel']
self.addParameter(ParameterSelection(
def initParameters(self, config=None):
self.addParameter(QgsProcessingParameterNumber(self.DISTANCE,
self.tr('Distance'), defaultValue=10.0))
self.addParameter(QgsProcessingParameterEnum(
self.SIDE,
self.tr('Side'),
options=self.sides))
self.addParameter(QgsProcessingParameterNumber(self.SEGMENTS,
self.tr('Segments'), QgsProcessingParameterNumber.Integer,
minValue=1, defaultValue=8))
self.addParameter(QgsProcessingParameterEnum(
self.JOIN_STYLE, self.JOIN_STYLE,
self.tr('Join style'), self.tr('Join style'),
self.join_styles)) options=self.join_styles))
self.addParameter(ParameterNumber(self.MITRE_LIMIT, self.addParameter(QgsProcessingParameterNumber(self.MITRE_LIMIT,
self.tr('Mitre limit'), 1, default=2)) self.tr('Mitre limit'), minValue=1, defaultValue=2))
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Single sided buffers')))
def name(self): def name(self):
return 'singlesidedbuffer' return 'singlesidedbuffer'
@ -91,37 +83,35 @@ class SingleSidedBuffer(QgisAlgorithm):
def displayName(self): def displayName(self):
return self.tr('Single sided buffer') return self.tr('Single sided buffer')
def processAlgorithm(self, parameters, context, feedback): def outputName(self):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context) return self.tr('Buffers')
writer = self.getOutputFromName( def outputType(self):
self.OUTPUT_LAYER).getVectorWriter(layer.fields(), QgsWkbTypes.Polygon, layer.crs(), context) return QgsProcessing.TypeVectorPolygon
distance = self.getParameterValue(self.DISTANCE) def outputWkbType(self, input_wkb_type):
segments = int(self.getParameterValue(self.SEGMENTS)) return QgsWkbTypes.Polygon
join_style = self.getParameterValue(self.JOIN_STYLE) + 1
if self.getParameterValue(self.SIDE) == 0: def prepareAlgorithm(self, parameters, context, feedback):
side = QgsGeometry.SideLeft self.distance = self.parameterAsDouble(parameters, self.DISTANCE, context)
self.segments = self.parameterAsInt(parameters, self.SEGMENTS, context)
self.join_style = self.parameterAsEnum(parameters, self.JOIN_STYLE, context) + 1
if self.parameterAsEnum(parameters, self.SIDE, context) == 0:
self.side = QgsGeometry.SideLeft
else: else:
side = QgsGeometry.SideRight self.side = QgsGeometry.SideRight
miter_limit = self.getParameterValue(self.MITRE_LIMIT) self.miter_limit = self.parameterAsDouble(parameters, self.MITRE_LIMIT, context)
return True
features = QgsProcessingUtils.getFeatures(layer, context) def processFeature(self, feature, feedback):
total = 100.0 / layer.featureCount() if layer.featureCount() else 0 input_geometry = feature.geometry()
if input_geometry:
output_geometry = input_geometry.singleSidedBuffer(self.distance, self.segments,
self.side, self.join_style, self.miter_limit)
if not output_geometry:
raise QgsProcessingException(
self.tr('Error calculating single sided buffer'))
for current, input_feature in enumerate(features): feature.setGeometry(output_geometry)
output_feature = input_feature
input_geometry = input_feature.geometry()
if input_geometry:
output_geometry = input_geometry.singleSidedBuffer(distance, segments,
side, join_style, miter_limit)
if not output_geometry:
raise GeoAlgorithmExecutionException(
self.tr('Error calculating single sided buffer'))
output_feature.setGeometry(output_geometry) return feature
writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))
del writer

View File

@ -913,59 +913,59 @@ tests:
name: expected/lines_translated.gml name: expected/lines_translated.gml
type: vector type: vector
# - algorithm: qgis:singlesidedbuffer - algorithm: qgis:singlesidedbuffer
# name: Single sided buffer lines (left, round) name: Single sided buffer lines (left, round)
# params: params:
# DISTANCE: 1.0 DISTANCE: 1.0
# INPUT_LAYER: INPUT:
# name: lines.gml name: lines.gml
# type: vector type: vector
# JOIN_STYLE: '0' JOIN_STYLE: '0'
# MITRE_LIMIT: 2 MITRE_LIMIT: 2
# SEGMENTS: 8 SEGMENTS: 8
# SIDE: '0' SIDE: '0'
# results: results:
# OUTPUT_LAYER: OUTPUT:
# name: expected/single_sided_buffer_line.gml name: expected/single_sided_buffer_line.gml
# type: vector type: vector
# compare: compare:
# geometry: geometry:
# precision: 7 precision: 7
#
# - algorithm: qgis:singlesidedbuffer - algorithm: qgis:singlesidedbuffer
# name: Single sided buffer lines (Right, mitre) name: Single sided buffer lines (Right, mitre)
# params: params:
# DISTANCE: 1.0 DISTANCE: 1.0
# INPUT_LAYER: INPUT:
# name: lines.gml name: lines.gml
# type: vector type: vector
# JOIN_STYLE: '1' JOIN_STYLE: '1'
# MITRE_LIMIT: 2 MITRE_LIMIT: 2
# SEGMENTS: 8 SEGMENTS: 8
# SIDE: '1' SIDE: '1'
# results: results:
# OUTPUT_LAYER: OUTPUT:
# name: expected/single_sided_buffer_line_mitre.gml name: expected/single_sided_buffer_line_mitre.gml
# type: vector type: vector
# compare: compare:
# geometry: geometry:
# precision: 7 precision: 7
#
# - algorithm: qgis:singlesidedbuffer - algorithm: qgis:singlesidedbuffer
# name: Single sided buffer multiline (bevel) name: Single sided buffer multiline (bevel)
# params: params:
# DISTANCE: 1.0 DISTANCE: 1.0
# INPUT_LAYER: INPUT:
# name: multilines.gml name: multilines.gml
# type: vector type: vector
# JOIN_STYLE: '2' JOIN_STYLE: '2'
# MITRE_LIMIT: 2 MITRE_LIMIT: 2
# SEGMENTS: 8 SEGMENTS: 8
# SIDE: '0' SIDE: '0'
# results: results:
# OUTPUT_LAYER: OUTPUT:
# name: expected/single_sided_buffer_multiline_bevel.gml name: expected/single_sided_buffer_multiline_bevel.gml
# type: vector type: vector
- algorithm: qgis:extractnodes - algorithm: qgis:extractnodes
name: Test (qgis:extractnodes) name: Test (qgis:extractnodes)