QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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  {
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 
QgsServerRequest::parameters
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
Definition: qgsserverrequest.cpp:85
QgsMapLayer::crs
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:89
qgsrasterprojector.h
QgsRasterFileWriter::NoError
@ NoError
Definition: qgsrasterfilewriter.h:49
qgswcsutils.h
qgsrasterlayer.h
qgsrasterpipe.h
QgsRasterPipe::insert
bool insert(int idx, QgsRasterInterface *interface)
Try to insert interface at specified index and connect if connection would fail, the interface is not...
Definition: qgsrasterpipe.cpp:81
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:51
QgsCoordinateReferenceSystem::fromOgcWmsCrs
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
Definition: qgscoordinatereferencesystem.cpp:200
QgsRasterPipe::set
bool set(QgsRasterInterface *interface)
Insert a new known interface in default place or replace interface of the same role if it already exi...
Definition: qgsrasterpipe.cpp:163
QgsMapLayer::shortName
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.cpp:179
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
qgsserverprojectutils.h
QgsRasterPipe
Base class for processing modules.
Definition: qgsrasterpipe.h:47
QgsAccessControl::layerReadPermission
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
Definition: qgsaccesscontrol.cpp:105
QgsServerRequest
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
Definition: qgsserverrequest.h:39
QgsProject::mapLayer
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
Definition: qgsproject.cpp:3208
QgsServerInterface::accessControls
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsRasterFileWriter::WriterError
WriterError
Definition: qgsrasterfilewriter.h:48
QgsServerProjectUtils::wcsLayerIds
SERVER_EXPORT QStringList wcsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WCS.
Definition: qgsserverprojectutils.cpp:367
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, TransformDirection direction=ForwardTransform, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:511
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:95
QgsServerRequest::Parameters
QMap< QString, QString > Parameters
Definition: qgsserverrequest.h:44
qgsrasterfilewriter.h
QgsRasterDataProvider::clone
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
QgsServerResponse::write
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
Definition: qgsserverresponse.cpp:25
QgsRasterProjector
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
Definition: qgsrasterprojector.h:48
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QgsMapLayerType::RasterLayer
@ RasterLayer
QgsWcs::QgsRequestNotWellFormedException
Exception thrown in case of malformed request.
Definition: qgswcsserviceexception.h:90
QgsRasterLayer::dataProvider
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
Definition: qgsrasterlayer.cpp:234
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:924
QgsRasterProjector::setCrs
Q_DECL_DEPRECATED void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
Sets the source and destination CRS.
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
QgsRasterLayer
Represents a raster layer.
Definition: qgsrasterlayer.h:71
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:206
QgsAccessControl
A helper class that centralizes restrictions given by all the access control filter plugins.
Definition: qgsaccesscontrol.h:37
QgsRasterFileWriter
The raster file writer which allows you to save a raster to a new file.
Definition: qgsrasterfilewriter.h:40
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QgsMapLayer::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
Definition: qgsmaplayer.cpp:785
QgsWcs::writeGetCoverage
void writeGetCoverage(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output WCS DescribeCoverage response.
Definition: qgswcsgetcoverage.cpp:40
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsRasterFileWriter::writeRaster
Q_DECL_DEPRECATED WriterError writeRaster(const QgsRasterPipe *pipe, int nCols, int nRows, const QgsRectangle &outputExtent, const QgsCoordinateReferenceSystem &crs, QgsRasterBlockFeedback *feedback=nullptr)
Write raster file.
Definition: qgsrasterfilewriter.cpp:77
QgsMapLayer::name
QString name
Definition: qgsmaplayer.h:86
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:53
QgsWcs::getCoverageData
QByteArray getCoverageData(QgsServerInterface *serverIface, const QgsProject *project, const QgsServerRequest &request)
Compute coverage data.
Definition: qgswcsgetcoverage.cpp:49
QgsRectangle::isEmpty
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:437
QgsWcs::parseBbox
QgsRectangle parseBbox(const QString &bboxStr)
Parse bounding box.
Definition: qgswcsutils.cpp:290
QgsServerInterface
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
Definition: qgsserverinterface.h:61
qgsproject.h
qgswcsgetcoverage.h
QgsWcs
WCS implementation.
Definition: qgswcs.cpp:30
QgsServerResponse
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
Definition: qgsserverresponse.h:44
qgsrasterdataprovider.h
QgsServerResponse::setHeader
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...
QgsMapLayer::type
QgsMapLayerType type
Definition: qgsmaplayer.h:90