QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgswcsgetcoverage.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgswcsgetcoverage.cpp
3 -------------------------
4 begin : January 16 , 2017
5 copyright : (C) 2013 by René-Luc D'Hont ( parts from qgswcsserver )
6 (C) 2017 by David Marteau
7 email : rldhont at 3liz dot com
8 david dot marteau at 3liz dot com
9 ***************************************************************************/
10
11/***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20#include <QTemporaryFile>
21
22#include "qgswcsutils.h"
24#include "qgswcsgetcoverage.h"
25
26#include "qgsproject.h"
27#include "qgsrasterlayer.h"
29#include "qgsrasterpipe.h"
30#include "qgsrasterprojector.h"
31#include "qgsrasterfilewriter.h"
32
33
34namespace QgsWcs
35{
36
40 void writeGetCoverage( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
41 const QgsServerRequest &request, QgsServerResponse &response )
42 {
43 Q_UNUSED( version )
44
45 response.write( getCoverageData( serverIface, project, request ) );
46 response.setHeader( "Content-Type", "image/tiff" );
47 }
48
49 QByteArray getCoverageData( QgsServerInterface *serverIface, const QgsProject *project, const QgsServerRequest &request )
50 {
51 const QgsServerRequest::Parameters parameters = request.parameters();
52
53#ifdef HAVE_SERVER_PYTHON_PLUGINS
54 QgsAccessControl *accessControl = serverIface->accessControls();
55#else
56 ( void )serverIface;
57#endif
58 //defining coverage name
59 QString coveName;
60 //read COVERAGE
61 const QMap<QString, QString>::const_iterator cove_name_it = parameters.constFind( QStringLiteral( "COVERAGE" ) );
62 if ( cove_name_it != parameters.constEnd() )
63 {
64 coveName = cove_name_it.value();
65 }
66 if ( coveName.isEmpty() )
67 {
68 const QMap<QString, QString>::const_iterator cove_name_it = parameters.constFind( QStringLiteral( "IDENTIFIER" ) );
69 if ( cove_name_it != parameters.constEnd() )
70 {
71 coveName = cove_name_it.value();
72 }
73 }
74
75 if ( coveName.isEmpty() )
76 {
77 throw QgsRequestNotWellFormedException( QStringLiteral( "COVERAGE is mandatory" ) );
78 }
79
80 //get the raster layer
81 const QStringList wcsLayersId = QgsServerProjectUtils::wcsLayerIds( *project );
82
83 QgsRasterLayer *rLayer = nullptr;
84 for ( int i = 0; i < wcsLayersId.size(); ++i )
85 {
86 QgsMapLayer *layer = project->mapLayer( wcsLayersId.at( i ) );
87 if ( !layer )
88 {
89 continue;
90 }
91 if ( layer->type() != QgsMapLayerType::RasterLayer )
92 {
93 continue;
94 }
95#ifdef HAVE_SERVER_PYTHON_PLUGINS
96 if ( !accessControl->layerReadPermission( layer ) )
97 {
98 continue;
99 }
100#endif
101 QString name = layer->name();
102 if ( !layer->shortName().isEmpty() )
103 name = layer->shortName();
104 name = name.replace( QLatin1String( " " ), QLatin1String( "_" ) );
105
106 if ( name == coveName )
107 {
108 rLayer = qobject_cast<QgsRasterLayer *>( layer );
109 break;
110 }
111 }
112 if ( !rLayer )
113 {
114 throw QgsRequestNotWellFormedException( QStringLiteral( "The layer for the COVERAGE '%1' is not found" ).arg( coveName ) );
115 }
116
117 double minx = 0.0, miny = 0.0, maxx = 0.0, maxy = 0.0;
118 // WIDTh and HEIGHT
119 int width = 0, height = 0;
120 // CRS
121 QString crs;
122
123 // read BBOX
124 const QgsRectangle bbox = parseBbox( parameters.value( QStringLiteral( "BBOX" ) ) );
125 if ( !bbox.isEmpty() )
126 {
127 minx = bbox.xMinimum();
128 miny = bbox.yMinimum();
129 maxx = bbox.xMaximum();
130 maxy = bbox.yMaximum();
131 }
132 else
133 {
134 throw QgsRequestNotWellFormedException( QStringLiteral( "The BBOX is mandatory and has to be xx.xxx,yy.yyy,xx.xxx,yy.yyy" ) );
135 }
136
137 // read WIDTH
138 bool conversionSuccess = false;
139 width = parameters.value( QStringLiteral( "WIDTH" ), QStringLiteral( "0" ) ).toInt( &conversionSuccess );
140 if ( !conversionSuccess )
141 {
142 width = 0;
143 }
144 // read HEIGHT
145 height = parameters.value( QStringLiteral( "HEIGHT" ), QStringLiteral( "0" ) ).toInt( &conversionSuccess );
146 if ( !conversionSuccess )
147 {
148 height = 0;
149 }
150
151 if ( width < 0 || height < 0 )
152 {
153 throw QgsRequestNotWellFormedException( QStringLiteral( "The WIDTH and HEIGHT are mandatory and have to be integer" ) );
154 }
155
156 crs = parameters.value( QStringLiteral( "CRS" ) );
157 if ( crs.isEmpty() )
158 {
159 throw QgsRequestNotWellFormedException( QStringLiteral( "The CRS is mandatory" ) );
160 }
161
163 if ( !requestCRS.isValid() )
164 {
165 throw QgsRequestNotWellFormedException( QStringLiteral( "Invalid CRS" ) );
166 }
167
168 QgsRectangle rect( minx, miny, maxx, maxy );
169
170 // transform rect
171 if ( requestCRS != rLayer->crs() )
172 {
173 const QgsCoordinateTransform t( requestCRS, rLayer->crs(), project );
174 rect = t.transformBoundingBox( rect );
175 }
176
177 // RESPONSE_CRS
178 QgsCoordinateReferenceSystem responseCRS = rLayer->crs();
179 crs = parameters.value( QStringLiteral( "RESPONSE_CRS" ) );
180 if ( !crs.isEmpty() )
181 {
183 if ( !responseCRS.isValid() )
184 {
185 responseCRS = rLayer->crs();
186 }
187 }
188
189 QTemporaryFile tempFile;
190 tempFile.open();
191 QgsRasterFileWriter fileWriter( tempFile.fileName() );
192
193 // clone pipe/provider
194 QgsRasterPipe pipe;
195 if ( !pipe.set( rLayer->dataProvider()->clone() ) )
196 {
197 throw QgsRequestNotWellFormedException( QStringLiteral( "Cannot set pipe provider" ) );
198 }
199
200 // add projector if necessary
201 if ( responseCRS != rLayer->crs() )
202 {
203 QgsRasterProjector *projector = new QgsRasterProjector;
204 projector->setCrs( rLayer->crs(), responseCRS, rLayer->transformContext() );
205 if ( !pipe.insert( 2, projector ) )
206 {
207 throw QgsRequestNotWellFormedException( QStringLiteral( "Cannot set pipe projector" ) );
208 }
209 }
210
211 const QgsRasterFileWriter::WriterError err = fileWriter.writeRaster( &pipe, width, height, rect, responseCRS, rLayer->transformContext() );
212 if ( err != QgsRasterFileWriter::NoError )
213 {
214 throw QgsRequestNotWellFormedException( QStringLiteral( "Cannot write raster error code: %1" ).arg( err ) );
215 }
216 return tempFile.readAll();
217 }
218
219} // namespace QgsWcs
220
221
222
A helper class that centralizes restrictions given by all the access control filter plugins.
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Class for doing transforms between two map coordinate systems.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
QgsMapLayerType type
Definition: qgsmaplayer.h:80
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:104
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
The raster file writer which allows you to save a raster to a new file.
Q_DECL_DEPRECATED WriterError writeRaster(const QgsRasterPipe *pipe, int nCols, int nRows, const QgsRectangle &outputExtent, const QgsCoordinateReferenceSystem &crs, QgsRasterBlockFeedback *feedback=nullptr)
Write raster file.
Represents a raster layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
Contains a pipeline of raster interfaces for sequential raster processing.
Definition: qgsrasterpipe.h:50
bool set(QgsRasterInterface *interface)
Inserts a new known interface in default place or replace interface of the same role if it already ex...
bool insert(int idx, QgsRasterInterface *interface)
Attempts to insert interface at specified index and connect if connection would fail,...
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
Q_DECL_DEPRECATED void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
Sets the source and destination CRS.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
QMap< QString, QString > Parameters
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
virtual void setHeader(const QString &key, const QString &value)=0
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
Exception thrown in case of malformed request.
@ RasterLayer
Raster layer.
SERVER_EXPORT QStringList wcsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WCS.
WCS implementation.
Definition: qgswcs.cpp:30
QgsRectangle parseBbox(const QString &bboxStr)
Parse bounding box.
void writeGetCoverage(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output WCS DescribeCoverage response.
QByteArray getCoverageData(QgsServerInterface *serverIface, const QgsProject *project, const QgsServerRequest &request)
Compute coverage data.
const QgsCoordinateReferenceSystem & crs