diff --git a/python/plugins/processing/algs/gdal/ClipRasterByExtent.py b/python/plugins/processing/algs/gdal/ClipRasterByExtent.py index 00079e52565..a31f6a82a75 100644 --- a/python/plugins/processing/algs/gdal/ClipRasterByExtent.py +++ b/python/plugins/processing/algs/gdal/ClipRasterByExtent.py @@ -24,7 +24,6 @@ import os from qgis.PyQt.QtGui import QIcon from qgis.core import ( - QgsDistanceArea, QgsRasterFileWriter, QgsProcessingException, QgsProcessingParameterDefinition, @@ -36,11 +35,9 @@ from qgis.core import ( QgsProcessingParameterBoolean, QgsProcessingParameterRasterDestination, QgsProcessingRasterLayerDefinition, - QgsProcessingUtils, - QgsWmsUtils, ) from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm -from processing.algs.gdal.GdalUtils import GdalConnectionDetails, GdalUtils +from processing.algs.gdal.GdalUtils import GdalUtils pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0] @@ -193,48 +190,20 @@ class ClipRasterByExtent(GdalAlgorithm): ) ) + input_details = GdalUtils.gdal_connection_details_from_layer( + inLayer, + self.INPUT, + parameters, + context, + bbox, + ) + arguments = [] - # If it's a WMS layer and scale/DPI were given, craft a XML description file - if inLayer.providerType() == "wms" and isinstance( + # If not a WMS or scale/DPI were not given, add -projwin + if inLayer.providerType() != "wms" or not isinstance( parameters[self.INPUT], QgsProcessingRasterLayerDefinition ): - # If the scale is greater than 0, we'll have a QgsProcessingRasterLayerDefinition - param_def = parameters[self.INPUT] - scale = param_def.referenceScale - dpi = param_def.dpi - - distanceArea = None - if inLayer.crs().isGeographic(): - distanceArea = QgsDistanceArea() - distanceArea.setSourceCrs(inLayer.crs(), context.transformContext()) - distanceArea.setEllipsoid(inLayer.crs().ellipsoidAcronym()) - - width, height = GdalUtils._wms_dimensions_for_scale( - bbox, inLayer.crs(), scale, dpi, distanceArea - ) - wms_description_file_path = QgsProcessingUtils.generateTempFilename( - "wms_description_file.xml", context - ) - res_xml_wms, xml_wms_error = GdalUtils.gdal_wms_xml_description_file( - inLayer, - QgsWmsUtils.wmsVersion(inLayer), - bbox, - width, - height, - wms_description_file_path, - ) - if not res_xml_wms: - raise QgsProcessingException( - "Cannot create XML description file for WMS layer. Details: {}".format( - xml_wms_error - ) - ) - input_details = GdalConnectionDetails( - connection_string=wms_description_file_path - ) - else: - input_details = GdalUtils.gdal_connection_details_from_layer(inLayer) arguments.extend( [ "-projwin", diff --git a/python/plugins/processing/algs/gdal/ClipRasterByMask.py b/python/plugins/processing/algs/gdal/ClipRasterByMask.py index 43467ea5933..83bd8d2b581 100644 --- a/python/plugins/processing/algs/gdal/ClipRasterByMask.py +++ b/python/plugins/processing/algs/gdal/ClipRasterByMask.py @@ -24,7 +24,6 @@ import os from qgis.PyQt.QtGui import QIcon from qgis.core import ( - QgsDistanceArea, QgsRasterFileWriter, QgsProcessing, QgsProcessingException, @@ -39,11 +38,9 @@ from qgis.core import ( QgsProcessingParameterBoolean, QgsProcessingParameterRasterDestination, QgsProcessingRasterLayerDefinition, - QgsProcessingUtils, - QgsWmsUtils, ) from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm -from processing.algs.gdal.GdalUtils import GdalConnectionDetails, GdalUtils +from processing.algs.gdal.GdalUtils import GdalUtils pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0] @@ -284,18 +281,14 @@ class ClipRasterByMask(GdalAlgorithm): out = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) self.setOutputValue(self.OUTPUT, out) - # If it's a WMS layer and scale/DPI were given, craft a XML description file + _bbox = None + # If it's a WMS layer and scale/DPI were given, + # choose a BBOX depending on alg parameters if inLayer.providerType() == "wms" and isinstance( parameters[self.INPUT], QgsProcessingRasterLayerDefinition ): - # If the scale is greater than 0, we'll have a QgsProcessingRasterLayerDefinition - param_def = parameters[self.INPUT] - scale = param_def.referenceScale - dpi = param_def.dpi - # For the input WMS's BBOX, if -te is given, then use -te, projected to input's # crs. Otherwise, use mask layer's extent, projected to input's crs. - _bbox = None if not bbox.isNull() and not bbox.isEmpty(): if bboxCrs != inLayer.crs(): _bbox = self.parameterAsExtent( @@ -320,37 +313,13 @@ class ClipRasterByMask(GdalAlgorithm): ) ) - distanceArea = None - if inLayer.crs().isGeographic(): - distanceArea = QgsDistanceArea() - distanceArea.setSourceCrs(inLayer.crs(), context.transformContext()) - distanceArea.setEllipsoid(inLayer.crs().ellipsoidAcronym()) - - width, height = GdalUtils._wms_dimensions_for_scale( - _bbox, inLayer.crs(), scale, dpi, distanceArea - ) - wms_description_file_path = QgsProcessingUtils.generateTempFilename( - "wms_description_file.xml", context - ) - res_xml_wms, xml_wms_error = GdalUtils.gdal_wms_xml_description_file( - inLayer, - QgsWmsUtils.wmsVersion(inLayer), - _bbox, - width, - height, - wms_description_file_path, - ) - if not res_xml_wms: - raise QgsProcessingException( - "Cannot create XML description file for WMS layer. Details: {}".format( - xml_wms_error - ) - ) - input_details = GdalConnectionDetails( - connection_string=wms_description_file_path - ) - else: - input_details = GdalUtils.gdal_connection_details_from_layer(inLayer) + input_details = GdalUtils.gdal_connection_details_from_layer( + inLayer, + self.INPUT, + parameters, + context, + _bbox, # Chosen BBOX for WMS + ) arguments = ["-overwrite"] diff --git a/python/plugins/processing/algs/gdal/GdalUtils.py b/python/plugins/processing/algs/gdal/GdalUtils.py index df0ec171e1c..7ac1cb4c59c 100644 --- a/python/plugins/processing/algs/gdal/GdalUtils.py +++ b/python/plugins/processing/algs/gdal/GdalUtils.py @@ -49,6 +49,8 @@ from qgis.core import ( QgsPointXY, QgsDistanceArea, QgsRasterLayer, + QgsWmsUtils, + QgsProcessingRasterLayerDefinition, ) from qgis.PyQt.QtCore import ( @@ -369,9 +371,16 @@ class GdalUtils: return GdalUtils.gdal_connection_details_from_layer(layer) @staticmethod - def gdal_connection_details_from_layer(layer: QgsMapLayer) -> GdalConnectionDetails: + def gdal_connection_details_from_layer( + layer: QgsMapLayer, + parameter_name: Optional[str] = "", + parameters: Optional[dict] = {}, + context: Optional[QgsProcessingContext] = None, + extent: Optional[QgsRectangle] = None, + ) -> GdalConnectionDetails: """ Builds GDAL connection details from a QGIS map layer + and related settings """ provider = layer.providerType() if provider == "spatialite": @@ -520,6 +529,53 @@ class GdalUtils: return GdalConnectionDetails( connection_string=gdal_source, format='"PostGISRaster"' ) + elif provider.lower() == "wms": + if parameter_name and parameters and context and extent: + # Create an XML description file for the WMS + parameter_value = parameters[parameter_name] + scale, dpi = 0, 0 + if layer.providerType() == "wms" and isinstance( + parameter_value, QgsProcessingRasterLayerDefinition + ): + scale = parameter_value.referenceScale + dpi = parameter_value.dpi + + if scale > 0: + distanceArea = None + if layer.crs().isGeographic(): + distanceArea = QgsDistanceArea() + distanceArea.setSourceCrs( + layer.crs(), context.transformContext() + ) + distanceArea.setEllipsoid(layer.crs().ellipsoidAcronym()) + + width, height = GdalUtils._wms_dimensions_for_scale( + extent, layer.crs(), scale, dpi, distanceArea + ) + wms_description_file_path = QgsProcessingUtils.generateTempFilename( + "wms_description_file.xml", context + ) + res_xml_wms, xml_wms_error = ( + GdalUtils.gdal_wms_xml_description_file( + layer, + QgsWmsUtils.wmsVersion(layer), + extent, + width, + height, + wms_description_file_path, + ) + ) + if res_xml_wms: + return GdalConnectionDetails( + connection_string=wms_description_file_path + ) + else: + message = "Cannot create XML description file for WMS layer. Details: {}".format( + xml_wms_error + ) + QgsMessageLog.logMessage( + message, "Processing", Qgis.MessageLevel.Warning + ) ogrstr = str(layer.source()).split("|")[0] path, ext = os.path.splitext(ogrstr) @@ -715,7 +771,7 @@ class GdalUtils: crs: QgsCoordinateReferenceSystem, scale: int, dpi: float = 96.0, - distanceArea=Optional[QgsDistanceArea], + distanceArea: Optional[QgsDistanceArea] = None, ) -> tuple[int, int]: """ Returns a tuple with WIDTH and HEIGHT in pixels that would match