QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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"
23 #include "qgsserverprojectutils.h"
24 #include "qgswcsgetcoverage.h"
25 
26 #include "qgsproject.h"
27 #include "qgsrasterlayer.h"
28 #include "qgsrasterdataprovider.h"
29 #include "qgsrasterpipe.h"
30 #include "qgsrasterprojector.h"
31 #include "qgsrasterfilewriter.h"
32 
33 
34 namespace 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  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  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  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  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  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  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  {
182  responseCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crs );
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  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 
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...
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Base class for all map layer types.
Definition: qgsmaplayer.h:78
Base class for processing modules.
Definition: qgsrasterpipe.h:46
QgsRectangle parseBbox(const QString &bboxStr)
Parse bounding box.
QgsMapLayerType type() const
Returns the type of the layer.
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:263
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
QgsRasterInterface * clone() const override=0
Clone itself, create deep copy.
const QgsCoordinateReferenceSystem & crs
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device...
Exception thrown in case of malformed request.
QgsRasterDataProvider * dataProvider() override
Returns the layer&#39;s data provider, it may be nullptr.
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:426
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
SERVER_EXPORT QStringList wcsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WCS.
Reads and writes project states.
Definition: qgsproject.h:89
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins...
void writeGetCoverage(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output WCS DescribeCoverage response.
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
This class represents a coordinate reference system (CRS).
Class for doing transforms between two map coordinate systems.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
A helper class that centralizes restrictions given by all the access control filter plugins...
QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QString name
Definition: qgsmaplayer.h:82
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
WCS implementation.
Definition: qgswcs.cpp:29
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:85
QMap< QString, QString > Parameters
Q_DECL_DEPRECATED void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
Sets the source and destination CRS.
QByteArray getCoverageData(QgsServerInterface *serverIface, const QgsProject *project, const QgsServerRequest &request)
Compute coverage data.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
The raster file writer which allows you to save a raster to a new file.