QGIS API Documentation  3.6.0-Noosa (5873452)
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 #endif
56  //defining coverage name
57  QString coveName;
58  //read COVERAGE
59  QMap<QString, QString>::const_iterator cove_name_it = parameters.constFind( QStringLiteral( "COVERAGE" ) );
60  if ( cove_name_it != parameters.constEnd() )
61  {
62  coveName = cove_name_it.value();
63  }
64  if ( coveName.isEmpty() )
65  {
66  QMap<QString, QString>::const_iterator cove_name_it = parameters.constFind( QStringLiteral( "IDENTIFIER" ) );
67  if ( cove_name_it != parameters.constEnd() )
68  {
69  coveName = cove_name_it.value();
70  }
71  }
72 
73  if ( coveName.isEmpty() )
74  {
75  throw QgsRequestNotWellFormedException( QStringLiteral( "COVERAGE is mandatory" ) );
76  }
77 
78  //get the raster layer
79  QStringList wcsLayersId = QgsServerProjectUtils::wcsLayerIds( *project );
80 
81  QgsRasterLayer *rLayer = nullptr;
82  for ( int i = 0; i < wcsLayersId.size(); ++i )
83  {
84  QgsMapLayer *layer = project->mapLayer( wcsLayersId.at( i ) );
85  if ( !layer )
86  {
87  continue;
88  }
89  if ( layer->type() != QgsMapLayer::LayerType::RasterLayer )
90  {
91  continue;
92  }
93 #ifdef HAVE_SERVER_PYTHON_PLUGINS
94  if ( !accessControl->layerReadPermission( layer ) )
95  {
96  continue;
97  }
98 #endif
99  QString name = layer->name();
100  if ( !layer->shortName().isEmpty() )
101  name = layer->shortName();
102  name = name.replace( QLatin1String( " " ), QLatin1String( "_" ) );
103 
104  if ( name == coveName )
105  {
106  rLayer = qobject_cast<QgsRasterLayer *>( layer );
107  break;
108  }
109  }
110  if ( !rLayer )
111  {
112  throw QgsRequestNotWellFormedException( QStringLiteral( "The layer for the COVERAGE '%1' is not found" ).arg( coveName ) );
113  }
114 
115  double minx = 0.0, miny = 0.0, maxx = 0.0, maxy = 0.0;
116  // WIDTh and HEIGHT
117  int width = 0, height = 0;
118  // CRS
119  QString crs;
120 
121  // read BBOX
122  QgsRectangle bbox = parseBbox( parameters.value( QStringLiteral( "BBOX" ) ) );
123  if ( !bbox.isEmpty() )
124  {
125  minx = bbox.xMinimum();
126  miny = bbox.yMinimum();
127  maxx = bbox.xMaximum();
128  maxy = bbox.yMaximum();
129  }
130  else
131  {
132  throw QgsRequestNotWellFormedException( QStringLiteral( "The BBOX is mandatory and has to be xx.xxx,yy.yyy,xx.xxx,yy.yyy" ) );
133  }
134 
135  // read WIDTH
136  bool conversionSuccess = false;
137  width = parameters.value( QStringLiteral( "WIDTH" ), QStringLiteral( "0" ) ).toInt( &conversionSuccess );
138  if ( !conversionSuccess )
139  {
140  width = 0;
141  }
142  // read HEIGHT
143  height = parameters.value( QStringLiteral( "HEIGHT" ), QStringLiteral( "0" ) ).toInt( &conversionSuccess );
144  if ( !conversionSuccess )
145  {
146  height = 0;
147  }
148 
149  if ( width < 0 || height < 0 )
150  {
151  throw QgsRequestNotWellFormedException( QStringLiteral( "The WIDTH and HEIGHT are mandatory and have to be integer" ) );
152  }
153 
154  crs = parameters.value( QStringLiteral( "CRS" ) );
155  if ( crs.isEmpty() )
156  {
157  throw QgsRequestNotWellFormedException( QStringLiteral( "The CRS is mandatory" ) );
158  }
159 
161  if ( !requestCRS.isValid() )
162  {
163  throw QgsRequestNotWellFormedException( QStringLiteral( "Invalid CRS" ) );
164  }
165 
166  QgsRectangle rect( minx, miny, maxx, maxy );
167 
168  // transform rect
169  if ( requestCRS != rLayer->crs() )
170  {
171  QgsCoordinateTransform t( requestCRS, rLayer->crs(), project );
172  rect = t.transformBoundingBox( rect );
173  }
174 
175  // RESPONSE_CRS
176  QgsCoordinateReferenceSystem responseCRS = rLayer->crs();
177  crs = parameters.value( QStringLiteral( "RESPONSE_CRS" ) );
178  if ( !crs.isEmpty() )
179  {
180  responseCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crs );
181  if ( !responseCRS.isValid() )
182  {
183  responseCRS = rLayer->crs();
184  }
185  }
186 
187  QTemporaryFile tempFile;
188  tempFile.open();
189  QgsRasterFileWriter fileWriter( tempFile.fileName() );
190 
191  // clone pipe/provider
192  QgsRasterPipe pipe;
193  if ( !pipe.set( rLayer->dataProvider()->clone() ) )
194  {
195  throw QgsRequestNotWellFormedException( QStringLiteral( "Cannot set pipe provider" ) );
196  }
197 
198  // add projector if necessary
199  if ( responseCRS != rLayer->crs() )
200  {
201  QgsRasterProjector *projector = new QgsRasterProjector;
202  projector->setCrs( rLayer->crs(), responseCRS );
203  if ( !pipe.insert( 2, projector ) )
204  {
205  throw QgsRequestNotWellFormedException( QStringLiteral( "Cannot set pipe projector" ) );
206  }
207  }
208 
209  QgsRasterFileWriter::WriterError err = fileWriter.writeRaster( &pipe, width, height, rect, responseCRS );
210  if ( err != QgsRasterFileWriter::NoError )
211  {
212  throw QgsRequestNotWellFormedException( QStringLiteral( "Cannot write raster error code: %1" ).arg( err ) );
213  }
214  return tempFile.readAll();
215  }
216 
217 } // namespace QgsWcs
218 
219 
220 
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:64
Base class for processing modules.
Definition: qgsrasterpipe.h:46
QgsRectangle parseBbox(const QString &bboxStr)
Parse bounding box.
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:258
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...
QgsMapLayer::LayerType type() const
Returns the type of the layer.
void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
Sets the source and destination CRS.
Exception thrown in case of malformed request.
QgsRasterDataProvider * dataProvider() override
Returns the layer&#39;s data provider, it may be null.
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
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:68
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:71
QMap< QString, QString > Parameters
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.