[processing] restore clip raster by mask algorithm

This commit is contained in:
Alexander Bruy 2017-09-06 11:18:13 +03:00
parent 1744ad7114
commit 587907e003
4 changed files with 230 additions and 302 deletions

View File

@ -61,6 +61,8 @@ class ClipByExtent(GdalAlgorithm):
def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterRasterLayer(self.INPUT,
self.tr('Input layer')))
self.addParameter(QgsProcessingParameterExtent(self.EXTENT,
self.tr('Clipping extent')))
self.addParameter(QgsProcessingParameterNumber(self.NODATA,
self.tr('Assign a specified nodata value to output bands'),
type=QgsProcessingParameterNumber.Double,
@ -68,8 +70,6 @@ class ClipByExtent(GdalAlgorithm):
maxValue=99999999.999999,
defaultValue=0.0,
optional=True))
self.addParameter(QgsProcessingParameterExtent(self.EXTENT,
self.tr('Clipping extent')))
options_param = QgsProcessingParameterString(self.OPTIONS,
self.tr('Additional creation parameters'),

View File

@ -16,7 +16,6 @@
* *
***************************************************************************
"""
from builtins import str
__author__ = 'Alexander Bruy'
__date__ = 'September 2013'
@ -30,66 +29,80 @@ import os
from qgis.PyQt.QtGui import QIcon
from qgis.core import QgsProcessingUtils
from osgeo import gdal
from processing.core.parameters import (ParameterRaster,
ParameterVector,
ParameterBoolean,
ParameterString,
ParameterSelection)
from processing.core.outputs import OutputRaster
from qgis.core import (QgsRasterFileWriter,
QgsProcessing,
QgsProcessingParameterDefinition,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterRasterLayer,
QgsProcessingParameterEnum,
QgsProcessingParameterString,
QgsProcessingParameterNumber,
QgsProcessingParameterBoolean,
QgsProcessingParameterRasterDestination)
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
from processing.algs.gdal.GdalUtils import GdalUtils
from processing.tools import dataobjects
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
class ClipByMask(GdalAlgorithm):
INPUT = 'INPUT'
OUTPUT = 'OUTPUT'
NO_DATA = 'NO_DATA'
MASK = 'MASK'
NODATA = 'NODATA'
ALPHA_BAND = 'ALPHA_BAND'
CROP_TO_CUTLINE = 'CROP_TO_CUTLINE'
KEEP_RESOLUTION = 'KEEP_RESOLUTION'
OPTIONS = 'OPTIONS'
RTYPE = 'RTYPE'
TYPE = ['Byte', 'Int16', 'UInt16', 'UInt32', 'Int32', 'Float32', 'Float64']
DATA_TYPE = 'DATA_TYPE'
OUTPUT = 'OUTPUT'
TYPES = ['Byte', 'Int16', 'UInt16', 'UInt32', 'Int32', 'Float32', 'Float64', 'CInt16', 'CInt32', 'CFloat32', 'CFloat64']
def __init__(self):
super().__init__()
def initAlgorithm(self, config=None):
self.addParameter(ParameterRaster(self.INPUT, self.tr('Input layer'), False))
self.addParameter(ParameterVector(self.MASK, self.tr('Mask layer'),
[dataobjects.TYPE_VECTOR_POLYGON]))
self.addParameter(ParameterString(self.NO_DATA,
self.tr("Nodata value, leave blank to take the nodata value from input"),
'', optional=True))
self.addParameter(ParameterBoolean(self.ALPHA_BAND,
self.addParameter(QgsProcessingParameterRasterLayer(self.INPUT,
self.tr('Input layer')))
self.addParameter(QgsProcessingParameterVectorLayer(self.MASK,
self.tr('Mask layer'),
[QgsProcessing.TypeVectorPolygon]))
self.addParameter(QgsProcessingParameterNumber(self.NODATA,
self.tr('Assign a specified nodata value to output bands'),
type=QgsProcessingParameterNumber.Double,
minValue=-99999999.999999,
maxValue=99999999.999999,
defaultValue=0.0,
optional=True))
self.addParameter(QgsProcessingParameterBoolean(self.ALPHA_BAND,
self.tr('Create and output alpha band'),
False))
self.addParameter(ParameterBoolean(self.CROP_TO_CUTLINE,
defaultValue=False))
self.addParameter(QgsProcessingParameterBoolean(self.CROP_TO_CUTLINE,
self.tr('Crop the extent of the target dataset to the extent of the cutline'),
True))
self.addParameter(ParameterBoolean(self.KEEP_RESOLUTION,
defaultValue=True))
self.addParameter(QgsProcessingParameterBoolean(self.KEEP_RESOLUTION,
self.tr('Keep resolution of output raster'),
False))
self.addParameter(ParameterString(self.OPTIONS,
self.tr('Additional creation options'),
optional=True,
metadata={'widget_wrapper': 'processing.algs.gdal.ui.RasterOptionsWidget.RasterOptionsWidgetWrapper'}))
self.addParameter(ParameterSelection(self.RTYPE,
self.tr('Output raster type'),
self.TYPE, 5))
defaultValue=False))
self.addOutput(OutputRaster(self.OUTPUT, self.tr('Clipped (mask)')))
options_param = QgsProcessingParameterString(self.OPTIONS,
self.tr('Additional creation parameters'),
defaultValue='',
optional=True)
options_param.setFlags(options_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
options_param.setMetadata({
'widget_wrapper': {
'class': 'processing.algs.gdal.ui.RasterOptionsWidget.RasterOptionsWidgetWrapper'}})
self.addParameter(options_param)
self.addParameter(QgsProcessingParameterEnum(self.DATA_TYPE,
self.tr('Output data type'),
self.TYPES,
allowMultiple=False,
defaultValue=5))
self.addParameter(QgsProcessingParameterRasterDestination(self.OUTPUT,
self.tr('Clipped (mask)')))
def name(self):
return 'cliprasterbymasklayer'
@ -104,60 +117,48 @@ class ClipByMask(GdalAlgorithm):
return self.tr('Raster extraction')
def getConsoleCommands(self, parameters, context, feedback):
out = self.getOutputValue(self.OUTPUT)
mask = self.getParameterValue(self.MASK)
context = dataobjects.createContext()
maskLayer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.MASK), context)
ogrMask = GdalUtils.ogrConnectionString(mask, context)[1:-1]
noData = self.getParameterValue(self.NO_DATA)
opts = self.getParameterValue(self.OPTIONS)
inLayer = self.parameterAsRasterLayer(parameters, self.INPUT, context)
if noData is not None:
noData = str(noData)
maskLayer = self.parameterAsVectorLayer(parameters, self.MASK, context)
connectionString = GdalUtils.ogrConnectionString(maskLayer.source(), context)
addAlphaBand = self.getParameterValue(self.ALPHA_BAND)
cropToCutline = self.getParameterValue(self.CROP_TO_CUTLINE)
keepResolution = self.getParameterValue(self.KEEP_RESOLUTION)
nodata = self.parameterAsDouble(parameters, self.NODATA, context)
options = self.parameterAsString(parameters, self.OPTIONS, context)
out = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
arguments = []
arguments.append('-ot')
arguments.append(self.TYPE[self.getParameterValue(self.RTYPE)])
arguments.append('-q')
arguments.append('-of')
arguments.append(GdalUtils.getFormatShortNameFromFilename(out))
if noData and len(noData) > 0:
arguments.append('-dstnodata')
arguments.append(noData)
arguments.append(self.TYPES[self.parameterAsEnum(parameters, self.DATA_TYPE, context)])
if keepResolution:
r = gdal.Open(self.getParameterValue(self.INPUT))
geoTransform = r.GetGeoTransform()
r = None
arguments.append('-of')
arguments.append(QgsRasterFileWriter.driverForExtension(os.path.splitext(out)[1]))
if self.parameterAsBool(self.KEEP_RESOLUTION):
arguments.append('-tr')
arguments.append(str(geoTransform[1]))
arguments.append(str(geoTransform[5]))
arguments.append(str(inLayer.rasterUnitsPerPixelX()))
arguments.append(str(-inLayer.rasterUnitsPerPixelY()))
arguments.append('-tap')
arguments.append('-cutline')
arguments.append(ogrMask)
if maskLayer and maskLayer.subsetString() != '':
arguments.append(connectionString)
if maskLayer.subsetString():
arguments.append('-cwhere')
arguments.append(maskLayer.subsetString())
if cropToCutline:
if self.parameterAsBool(self.CROP_TO_CUTLINE):
arguments.append('-crop_to_cutline')
if addAlphaBand:
if self.parameterAsBool(self.ALPHA_BAND):
arguments.append('-dstalpha')
if opts:
if nodata:
arguments.append('-dstnodata {}'.format(nodata))
if options:
arguments.append('-co')
arguments.append(opts)
arguments.append(options)
if GdalUtils.version() in [2010000, 2010100]:
arguments.append("--config GDALWARP_IGNORE_BAD_CUTLINE YES")
arguments.append(self.getParameterValue(self.INPUT))
arguments.append(inLayer.source())
arguments.append(out)
return ['gdalwarp', GdalUtils.escapeAndJoin(arguments)]

View File

@ -37,6 +37,7 @@ from .AssignProjection import AssignProjection
from .aspect import aspect
from .buildvrt import buildvrt
from .ClipByExtent import ClipByExtent
from .ClipByMask import ClipByMask
from .ColorRelief import ColorRelief
from .contour import contour
from .fillnodata import fillnodata
@ -63,7 +64,6 @@ from .warp import warp
# from .merge import merge
# from .gdaladdo import gdaladdo
# from .ClipByMask import ClipByMask
# from .rasterize import rasterize
# from .proximity import proximity
# from .extractprojection import ExtractProjection
@ -140,6 +140,7 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
aspect(),
buildvrt(),
ClipByExtent(),
ClipByMask(),
ColorRelief(),
contour(),
fillnodata(),
@ -165,7 +166,6 @@ class GdalAlgorithmProvider(QgsProcessingProvider):
warp(),
# merge(),
# gdaladdo(),
# ClipByMask(),
# rasterize(),
# proximity(),
# ExtractProjection(),

View File

@ -16,228 +16,6 @@ tests:
- 'Band 1 Block=16x14 Type=Float32, ColorInterp=Gray'
- ' NoData Value=-32768'
# - algorithm: gdal:ogrinfo
# name: ogrinfo
# params:
# INPUT:
# name: lines.gml
# type: vector
# SUMMARY_ONLY: 'True'
# results:
# OUTPUT:
# name: expected/gdal/vector_info.html
# type: regex
# rules:
# - 'Extent: \(-1.000000, -3.000000\) - \(11.000000, 5.000000\)'
# - 'Geometry: Line String'
# - 'Feature Count: [6|7]' # On some platforms returns 6 instead of 7...
#
# - algorithm: gdal:buffervectors
# name: Buffer lines
# params:
# DISSOLVEALL: false
# DISTANCE: 1.0
# GEOMETRY: geometry
# INPUT_LAYER:
# name: lines.gml
# type: vector
# MULTI: false
# results:
# OUTPUT_LAYER:
# name: expected/gdal/buffer_lines.gml
# type: vector
# compare:
# geometry:
# precision: 7
# expectedFailure:
# - int(1)
#
# - algorithm: gdal:buffervectors
# name: Basic polygon buffer
# params:
# DISSOLVEALL: false
# DISTANCE: 0.5
# GEOMETRY: geometry
# INPUT_LAYER:
# name: polys.gml
# type: vector
# MULTI: false
# results:
# OUTPUT_LAYER:
# name: expected/gdal/buffer_polys.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: gdal:buffervectors
# name: Polygon buffer with dissolve
# params:
# DISSOLVEALL: true
# DISTANCE: 0.5
# GEOMETRY: geometry
# INPUT_LAYER:
# name: polys.gml
# type: vector
# MULTI: false
# results:
# OUTPUT_LAYER:
# name: expected/gdal/buffer_polys_dissolve.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
- algorithm: gdal:createpointsalonglines
name: Points along lines
params:
DISTANCE: 0.25
GEOMETRY: geometry
INPUT:
name: lines.gml
type: vector
results:
OUTPUT:
name: expected/gdal/points_along_lines.gml
type: vector
pk: fid
compare:
ignore_crs_check: true
# - algorithm: gdal:offsetlinesforlines
# name: Offset lines for lines (right-handed)
# params:
# GEOMETRY: geometry
# INPUT_LAYER:
# name: lines.gml
# type: vector
# RADIUS: -0.5
# results:
# OUTPUT_LAYER:
# name: expected/gdal/offset_lines.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: gdal:singlesidedbufferforlines
# name: One-side buffer for lines (left-handed)
# params:
# DISSOLVEALL: false
# GEOMETRY: geometry
# INPUT_LAYER:
# name: lines.gml
# type: vector
# LEFTRIGHT: '1'
# MULTI: false
# RADIUS: 0.5
# results:
# OUTPUT_LAYER:
# name: expected/gdal/one_side_buffer.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: gdal:cliprasterbyextent
# name: Clip raster by extent and change no data values
# params:
# BIGTIFF: '0'
# COMPRESS: '4'
# INPUT:
# name: dem.tif
# type: raster
# JPEGCOMPRESSION: 75
# NO_DATA: '-9999'
# PREDICTOR: 1
# PROJWIN: 18.67460436727692,18.698371162148714,45.78995019401027,45.804344168369234
# RTYPE: '5'
# TFW: false
# TILED: false
# ZLEVEL: 6
# results:
# OUTPUT:
# hash: df5de501bcec0c10f738d77f3b48d5545b48f0a22e0e028a8b1ccbe7
# type: rasterhash
#
# - algorithm: gdal:cliprasterbymasklayer
# name: Clip raster by mask layer
# params:
# ALPHA_BAND: false
# BIGTIFF: '0'
# COMPRESS: '4'
# CROP_TO_CUTLINE: true
# INPUT:
# name: dem.tif
# type: raster
# JPEGCOMPRESSION: 75
# KEEP_RESOLUTION: false
# MASK:
# name: custom/polygon_mask.gml
# type: vector
# NO_DATA: ''
# PREDICTOR: 1
# RTYPE: '5'
# TFW: false
# TILED: false
# ZLEVEL: 6
# results:
# OUTPUT:
# hash: 4f4720e4efe59a7f238f622659917bbeb5262369d15d5e2917dbcf8b
# type: rasterhash
#
# - algorithm: gdal:cliprasterbymasklayer
# name: Clip raster by mask layer and change no data value
# params:
# ALPHA_BAND: false
# BIGTIFF: '0'
# COMPRESS: '4'
# CROP_TO_CUTLINE: true
# INPUT:
# name: dem.tif
# type: raster
# JPEGCOMPRESSION: 75
# KEEP_RESOLUTION: false
# MASK:
# name: custom/polygon_mask.gml
# type: vector
# NO_DATA: '-9999'
# PREDICTOR: 1
# RTYPE: '5'
# TFW: false
# TILED: false
# ZLEVEL: 6
# results:
# OUTPUT:
# hash: 1e0252e63c65dcf4ed1f2b17d2490d3e0331aeb59d8f59b59554f442
# type: rasterhash
#
# - algorithm: gdal:cliprasterbymasklayer
# name: Clip raster by mask layer and add alpha band
# params:
# ALPHA_BAND: true
# BIGTIFF: '0'
# COMPRESS: '4'
# CROP_TO_CUTLINE: true
# INPUT:
# name: dem.tif
# type: raster
# JPEGCOMPRESSION: 75
# KEEP_RESOLUTION: false
# MASK:
# name: custom/polygon_mask.gml
# type: vector
# NO_DATA: ''
# PREDICTOR: 1
# RTYPE: '5'
# TFW: false
# TILED: false
# ZLEVEL: 6
# results:
# OUTPUT:
# hash: 8f69431c6ff7db5174c1ca8e879ae39582fd4ce86f9b53edae0f38ce
# type: rasterhash
- algorithm: gdal:aspect
name: Aspect
params:
@ -452,6 +230,155 @@ tests:
hash: 9913a7c0e1ced2c2ce1cd8f0e8103475bc2b0dd4d1d0adafe4920f93
type: rasterhash
- algorithm: gdal:cliprasterbymasklayer
name: Clip raster by mask layer
params:
ALPHA_BAND: false
BIGTIFF: '0'
COMPRESS: '4'
CROP_TO_CUTLINE: true
INPUT:
name: dem.tif
type: raster
JPEGCOMPRESSION: 75
KEEP_RESOLUTION: false
MASK:
name: custom/polygon_mask.gml
type: vector
NO_DATA: ''
PREDICTOR: 1
RTYPE: '5'
TFW: false
TILED: false
ZLEVEL: 6
results:
OUTPUT:
hash: 4f4720e4efe59a7f238f622659917bbeb5262369d15d5e2917dbcf8b
type: rasterhash
# - algorithm: gdal:ogrinfo
# name: ogrinfo
# params:
# INPUT:
# name: lines.gml
# type: vector
# SUMMARY_ONLY: 'True'
# results:
# OUTPUT:
# name: expected/gdal/vector_info.html
# type: regex
# rules:
# - 'Extent: \(-1.000000, -3.000000\) - \(11.000000, 5.000000\)'
# - 'Geometry: Line String'
# - 'Feature Count: [6|7]' # On some platforms returns 6 instead of 7...
#
# - algorithm: gdal:buffervectors
# name: Buffer lines
# params:
# DISSOLVEALL: false
# DISTANCE: 1.0
# GEOMETRY: geometry
# INPUT_LAYER:
# name: lines.gml
# type: vector
# MULTI: false
# results:
# OUTPUT_LAYER:
# name: expected/gdal/buffer_lines.gml
# type: vector
# compare:
# geometry:
# precision: 7
# expectedFailure:
# - int(1)
#
# - algorithm: gdal:buffervectors
# name: Basic polygon buffer
# params:
# DISSOLVEALL: false
# DISTANCE: 0.5
# GEOMETRY: geometry
# INPUT_LAYER:
# name: polys.gml
# type: vector
# MULTI: false
# results:
# OUTPUT_LAYER:
# name: expected/gdal/buffer_polys.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: gdal:buffervectors
# name: Polygon buffer with dissolve
# params:
# DISSOLVEALL: true
# DISTANCE: 0.5
# GEOMETRY: geometry
# INPUT_LAYER:
# name: polys.gml
# type: vector
# MULTI: false
# results:
# OUTPUT_LAYER:
# name: expected/gdal/buffer_polys_dissolve.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
- algorithm: gdal:createpointsalonglines
name: Points along lines
params:
DISTANCE: 0.25
GEOMETRY: geometry
INPUT:
name: lines.gml
type: vector
results:
OUTPUT:
name: expected/gdal/points_along_lines.gml
type: vector
pk: fid
compare:
ignore_crs_check: true
# - algorithm: gdal:offsetlinesforlines
# name: Offset lines for lines (right-handed)
# params:
# GEOMETRY: geometry
# INPUT_LAYER:
# name: lines.gml
# type: vector
# RADIUS: -0.5
# results:
# OUTPUT_LAYER:
# name: expected/gdal/offset_lines.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: gdal:singlesidedbufferforlines
# name: One-side buffer for lines (left-handed)
# params:
# DISSOLVEALL: false
# GEOMETRY: geometry
# INPUT_LAYER:
# name: lines.gml
# type: vector
# LEFTRIGHT: '1'
# MULTI: false
# RADIUS: 0.5
# results:
# OUTPUT_LAYER:
# name: expected/gdal/one_side_buffer.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: gdal:merge
# name: Merge 2 raster layers
# params: