32
32
from qgis .core import (QgsProcessing ,
33
33
QgsProcessingException ,
34
34
QgsProcessingUtils ,
35
+ QgsProcessingParameterCrs ,
35
36
QgsProcessingParameterMultipleLayers ,
36
37
QgsProcessingParameterNumber ,
37
38
QgsProcessingParameterExtent ,
38
39
QgsProcessingParameterRasterDestination ,
39
40
QgsProcessingParameterRasterLayer ,
40
41
QgsProcessingOutputRasterLayer ,
41
- QgsProcessingParameterString )
42
+ QgsProcessingParameterString ,
43
+ QgsCoordinateTransform )
42
44
from qgis .analysis import QgsRasterCalculator , QgsRasterCalculatorEntry
43
45
44
46
@@ -48,6 +50,7 @@ class RasterCalculator(QgisAlgorithm):
48
50
EXTENT = 'EXTENT'
49
51
CELLSIZE = 'CELLSIZE'
50
52
EXPRESSION = 'EXPRESSION'
53
+ CRS = 'CRS'
51
54
OUTPUT = 'OUTPUT'
52
55
53
56
def group (self ):
@@ -60,13 +63,6 @@ def __init__(self):
60
63
super ().__init__ ()
61
64
62
65
def initAlgorithm (self , config = None ):
63
- layer_param = QgsProcessingParameterMultipleLayers (self .LAYERS ,
64
- self .tr ('Input layers' ),
65
- layerType = QgsProcessing .TypeRaster ,
66
- optional = True )
67
- layer_param .setMetadata ({'widget_wrapper' : 'processing.algs.qgis.ui.RasterCalculatorWidgets.LayersListWidgetWrapper' })
68
- self .addParameter (layer_param )
69
-
70
66
class ParameterRasterCalculatorExpression (QgsProcessingParameterString ):
71
67
72
68
def __init__ (self , name = '' , description = '' , multiLine = False ):
@@ -100,13 +96,18 @@ def evaluateForModeler(self, value, model):
100
96
101
97
self .addParameter (ParameterRasterCalculatorExpression (self .EXPRESSION , self .tr ('Expression' ),
102
98
multiLine = True ))
99
+ self .addParameter (QgsProcessingParameterMultipleLayers (self .LAYERS ,
100
+ self .tr ('Reference layer(s) (used for automated determination extent and cellsize)' ),
101
+ layerType = QgsProcessing .TypeRaster ,
102
+ optional = True ))
103
103
self .addParameter (QgsProcessingParameterNumber (self .CELLSIZE ,
104
104
self .tr ('Cell size (use 0 or empty to set it automatically)' ),
105
105
type = QgsProcessingParameterNumber .Double ,
106
106
minValue = 0.0 , defaultValue = 0.0 , optional = True ))
107
107
self .addParameter (QgsProcessingParameterExtent (self .EXTENT ,
108
108
self .tr ('Output extent' ),
109
109
optional = True ))
110
+ self .addParameter (QgsProcessingParameterCrs (self .CRS , 'Output CRS' , 'ProjectCrs' ))
110
111
self .addParameter (QgsProcessingParameterRasterDestination (self .OUTPUT , self .tr ('Output' )))
111
112
112
113
def name (self ):
@@ -118,10 +119,32 @@ def displayName(self):
118
119
def processAlgorithm (self , parameters , context , feedback ):
119
120
expression = self .parameterAsString (parameters , self .EXPRESSION , context )
120
121
layers = self .parameterAsLayerList (parameters , self .LAYERS , context )
122
+ crs = self .parameterAsCrs (parameters , self .CRS , context )
123
+
121
124
layersDict = {}
122
125
if layers :
123
126
layersDict = {os .path .basename (lyr .source ().split ("." )[0 ]): lyr for lyr in layers }
124
127
128
+ bbox = self .parameterAsExtent (parameters , self .EXTENT , context )
129
+ if not layers and bbox .isNull ():
130
+ raise QgsProcessingException (self .tr ("No reference layer selected to automate extent box" ))
131
+
132
+ if bbox .isNull () and layers :
133
+ bbox = QgsProcessingUtils .combineLayerExtents (layers , crs )
134
+
135
+ cellsize = self .parameterAsDouble (parameters , self .CELLSIZE , context )
136
+ if not layers and cellsize == 0 :
137
+ raise QgsProcessingException (self .tr ("No reference layer selected to automate cellsize value" ))
138
+
139
+ def _cellsize (layer ):
140
+ ext = layer .extent ()
141
+ if layer .crs () != crs :
142
+ transform = QgsCoordinateTransform (layer .crs (), crs , context .project ())
143
+ ext = transform .transformBoundingBox (ext )
144
+ return (ext .xMaximum () - ext .xMinimum ()) / layer .width ()
145
+ if cellsize == 0 :
146
+ cellsize = min ([_cellsize (lyr ) for lyr in layersDict .values ()])
147
+
125
148
for lyr in QgsProcessingUtils .compatibleRasterLayers (context .project ()):
126
149
name = lyr .name ()
127
150
if (name + "@" ) in expression :
@@ -137,28 +160,15 @@ def processAlgorithm(self, parameters, context, feedback):
137
160
entries .append (entry )
138
161
139
162
output = self .parameterAsOutputLayer (parameters , self .OUTPUT , context )
140
- bbox = self .parameterAsExtent (parameters , self .EXTENT , context )
141
- if bbox .isNull ():
142
- bbox = QgsProcessingUtils .combineLayerExtents (layers )
143
163
144
- if bbox .isNull ():
145
- if layersDict :
146
- bbox = list (layersDict .values ())[0 ].extent ()
147
- for lyr in layersDict .values ():
148
- bbox .combineExtentWith (lyr .extent ())
149
- else :
150
- raise QgsProcessingException (self .tr ("No layers selected" ))
151
-
152
- def _cellsize (layer ):
153
- return (layer .extent ().xMaximum () - layer .extent ().xMinimum ()) / layer .width ()
154
- cellsize = self .parameterAsDouble (parameters , self .CELLSIZE , context ) or min ([_cellsize (lyr ) for lyr in layersDict .values ()])
155
164
width = math .floor ((bbox .xMaximum () - bbox .xMinimum ()) / cellsize )
156
165
height = math .floor ((bbox .yMaximum () - bbox .yMinimum ()) / cellsize )
157
166
driverName = GdalUtils .getFormatShortNameFromFilename (output )
158
167
calc = QgsRasterCalculator (expression ,
159
168
output ,
160
169
driverName ,
161
170
bbox ,
171
+ crs ,
162
172
width ,
163
173
height ,
164
174
entries )
0 commit comments