QGIS API Documentation 4.3.0-Master (0cfde48c85b)
Loading...
Searching...
No Matches
qgswmslayerinfos.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgswmslayerinfos.cpp
3
4 Layer's information
5 ------------------------------------
6 begin : September 26 , 2022
7 copyright : (C) 2022 by René-Luc D'Hont and David Marteau
8 email : rldhont at 3liz doc com
9 dmarteau at 3liz dot com
10 ***************************************************************************/
11
12/***************************************************************************
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 ***************************************************************************/
20
21#include "qgswmslayerinfos.h"
22
23#include <algorithm>
24
27#include "qgsmessagelog.h"
28#include "qgsproject.h"
29#include "qgsserverinterface.h"
31#include "qgsvectorlayer.h"
32
33#include <QString>
34
35using namespace Qt::StringLiterals;
36
38 const QgsRectangle &extent, const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, const QgsCoordinateTransformContext &context, const bool &ballparkTransformsAreAppropriate
39)
40{
41 QgsCoordinateTransform transformer { source, destination, context };
42 transformer.setBallparkTransformsAreAppropriate( ballparkTransformsAreAppropriate );
43 // Transform extent and do not catch exception
44 return transformer.transformBoundingBox( extent );
45}
46
48 const QgsRectangle &extent, const QgsCoordinateReferenceSystem &source, const QList<QgsCoordinateReferenceSystem> &destinations, const QgsCoordinateTransformContext &context
49)
50{
51 QMap<QString, QgsRectangle> crsExtents;
52 if ( extent.isEmpty() )
53 {
54 return crsExtents;
55 }
56 for ( const QgsCoordinateReferenceSystem &destination : std::as_const( destinations ) )
57 {
58 // Transform extent and do not catch exception
59 QgsCoordinateTransform crsTransform { source, destination, context };
60 crsExtents[destination.authid()] = crsTransform.transformBoundingBox( extent );
61 }
62 return crsExtents;
63}
64
65
67 const QgsProject *project, QgsWmsLayerInfos &pLayer, QgsMapLayer *ml, const QgsRectangle &wmsExtent, const QgsCoordinateReferenceSystem &wgs84, const QList<QgsCoordinateReferenceSystem> &outputCrsList
68)
69{
70 QgsRectangle layerExtent = ml->extent();
71 if ( layerExtent.isEmpty() )
72 {
73 // if the extent is empty (not only Null), use the wms extent
74 // defined in the project...
75 if ( wmsExtent.isNull() )
76 {
77 // or the CRS extent otherwise
78 layerExtent = ml->crs().bounds();
79 }
80 else
81 {
82 layerExtent = QgsRectangle( wmsExtent );
83 if ( ml->crs() != project->crs() )
84 {
85 // If CRS is different transform it to layer's CRS
86 try
87 {
88 layerExtent = QgsWmsLayerInfos::transformExtent( wmsExtent, project->crs(), ml->crs(), project->transformContext() );
89 }
90 catch ( QgsCsException &cse )
91 {
92 QgsMessageLog::logMessage( u"Error transforming extent for layer %1: %2"_s.arg( ml->name() ).arg( cse.what() ), u"Server"_s, Qgis::MessageLevel::Warning );
93 return false;
94 }
95 }
96 }
97
98 // Now we have a layer Extent we need the WGS84 bounding rectangle
99 try
100 {
101 pLayer.wgs84BoundingRect = QgsWmsLayerInfos::transformExtent( layerExtent, ml->crs(), wgs84, project->transformContext(), true );
102 }
103 catch ( const QgsCsException &cse )
104 {
105 QgsMessageLog::logMessage( u"Error transforming extent for layer %1: %2"_s.arg( ml->name() ).arg( cse.what() ), u"Server"_s, Qgis::MessageLevel::Warning );
106 return false;
107 }
108 }
109 else
110 {
111 pLayer.wgs84BoundingRect = ml->wgs84Extent();
112 }
113
114 try
115 {
116 pLayer.crsExtents = QgsWmsLayerInfos::transformExtentToCrsList( layerExtent, ml->crs(), outputCrsList, project->transformContext() );
117 }
118 catch ( QgsCsException &cse )
119 {
120 QgsMessageLog::logMessage( u"Error transforming extent for layer %1: %2"_s.arg( ml->name() ).arg( cse.what() ), u"Server"_s, Qgis::MessageLevel::Warning );
121 return false;
122 }
123
124 return true;
125}
126
127
128QMap<QString, QgsWmsLayerInfos> QgsWmsLayerInfos::buildWmsLayerInfos( QgsServerInterface *serverIface, const QgsProject *project )
129{
130 auto outputCrsList = QList<QgsCoordinateReferenceSystem>();
131 for ( const QString &crsDef : QgsServerProjectUtils::wmsOutputCrsList( *project ) )
132 {
133 const auto crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crsDef );
134 if ( crs.isValid() )
135 {
136 outputCrsList.append( crs );
137 }
138 }
139
140 return buildWmsLayerInfos( serverIface, project, outputCrsList );
141}
142
143QMap<QString, QgsWmsLayerInfos> QgsWmsLayerInfos::buildWmsLayerInfos( QgsServerInterface *serverIface, const QgsProject *project, const QList<QgsCoordinateReferenceSystem> &outputCrsList )
144{
145 QMap<QString, QgsWmsLayerInfos> wmsLayers;
146#ifdef HAVE_SERVER_PYTHON_PLUGINS
147 QgsAccessControl *accessControl = serverIface->accessControls();
148#else
149 ( void ) serverIface;
150#endif
151
152 bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
153 const QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
154 const QgsRectangle wmsExtent = QgsServerProjectUtils::wmsExtent( *project );
156
157 for ( QgsMapLayer *ml : project->mapLayers() )
158 {
159 if ( !ml || restrictedLayers.contains( ml->name() ) ) //unpublished layer
160 {
161 continue;
162 }
163
164#ifdef HAVE_SERVER_PYTHON_PLUGINS
165 if ( accessControl && !accessControl->layerReadPermission( ml ) )
166 {
167 continue;
168 }
169#endif
170
171 QgsWmsLayerInfos pLayer;
172 pLayer.id = ml->id();
173
174 // Calculate layer extents for the WMS output CRSes list
175 // First define if the layer has an extent
176 // Vector layer with No Geometry has no extent the other has one
177 bool hasExtent = true;
178 if ( ml->type() == Qgis::LayerType::Vector )
179 {
180 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( ml );
181 if ( !vLayer || vLayer->wkbType() == Qgis::WkbType::NoGeometry )
182 {
183 hasExtent = false;
184 }
185 }
186
187 // If the layer has an extent and we cannot get CRS bounding boxes, do not keep the layer
188 if ( hasExtent && !setBoundingRect( project, pLayer, ml, wmsExtent, wgs84, outputCrsList ) )
189 continue;
190
191 // layer type
192 pLayer.type = ml->type();
193 // layer wms name
194 pLayer.name = ml->name();
195 if ( useLayerIds )
196 {
197 pLayer.name = ml->id();
198 }
199 else if ( !ml->serverProperties()->shortName().isEmpty() )
200 {
201 pLayer.name = ml->serverProperties()->shortName();
202 }
203 // layer is queryable
204 pLayer.queryable = ml->flags().testFlag( QgsMapLayer::Identifiable );
205 // layer styles
206 pLayer.styles = ml->styleManager()->styles();
207 // layer legend URL
208 pLayer.legendUrl = ml->serverProperties()->legendUrl();
209 // layer legend URL format
210 pLayer.legendUrlFormat = ml->serverProperties()->legendUrlFormat();
211 // layer min/max scales
212 if ( ml->hasScaleBasedVisibility() )
213 {
214 pLayer.hasScaleBasedVisibility = ml->hasScaleBasedVisibility();
215 pLayer.maxScale = ml->maximumScale();
216 pLayer.minScale = ml->minimumScale();
217 }
218
219 wmsLayers[pLayer.id] = pLayer;
220 }
221
222 return wmsLayers;
223}
@ Warning
Warning message.
Definition qgis.h:162
@ Vector
Vector layer.
Definition qgis.h:207
static QString geographicCrsAuthId()
Geographic coordinate system auth:id string for a default geographic CRS (EPSG:4326).
Definition qgis.h:7443
@ NoGeometry
No geometry.
Definition qgis.h:332
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.
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.
QgsRectangle bounds() const
Returns the approximate bounds for the region the CRS is usable within.
Contains information about the context in which a coordinate transform is executed.
Handles coordinate transforms between two coordinate systems.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
QString what() const
Base class for all map layer types.
Definition qgsmaplayer.h:83
QString name
Definition qgsmaplayer.h:87
Q_INVOKABLE QgsRectangle wgs84Extent(bool forceRecalculate=false) const
Returns the WGS84 extent (EPSG:4326) of the layer according to ReadFlag::FlagTrustLayerMetadata.
virtual Q_INVOKABLE QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:90
@ Identifiable
If the layer is identifiable using the identify map tool and as a WMS layer.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:114
QgsCoordinateTransformContext transformContext
Definition qgsproject.h:121
QgsCoordinateReferenceSystem crs
Definition qgsproject.h:120
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
A rectangle specified with double values.
Defines interfaces exposed by QGIS Server and made available to plugins.
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
static QgsRectangle wmsExtent(const QgsProject &project)
Returns the WMS Extent restriction.
static bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
static QStringList wmsOutputCrsList(const QgsProject &project)
Returns the WMS output CRS list.
static QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
Represents a vector layer which manages a vector based dataset.
Q_INVOKABLE Qgis::WkbType wkbType() const final
Returns the WKBType or WKBUnknown in case of error.
WMS Layer infos.
QString legendUrlFormat
WMS layer legend URL format.
QStringList styles
WMS layer styles.
QString legendUrl
WMS layer legend URL.
QString id
QGIS layer id.
static QgsRectangle transformExtent(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, const QgsCoordinateTransformContext &context, const bool &ballparkTransformsAreAppropriate=false)
Returns a transformed extent.
double maxScale
WMS layer maximum scale (if negative, no maximum scale is defined).
QMap< QString, QgsRectangle > crsExtents
WMS layer CRS extents (can be empty).
static QMap< QString, QgsRectangle > transformExtentToCrsList(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &source, const QList< QgsCoordinateReferenceSystem > &destinations, const QgsCoordinateTransformContext &context)
Returns a map with CRS authid as key and the transformed extent as value.
Qgis::LayerType type
QGIS layer type.
QString name
WMS layer name.
static QMap< QString, QgsWmsLayerInfos > buildWmsLayerInfos(QgsServerInterface *serverIface, const QgsProject *project, const QList< QgsCoordinateReferenceSystem > &outputCrsList)
Returns the WMS layers definition to build WMS capabilities.
bool hasScaleBasedVisibility
WMS layer has scale based visibility.
double minScale
WMS layer minimum scale (if negative, no maximum scale is defined).
bool queryable
WMS layer is queryable.
QgsRectangle wgs84BoundingRect
WMS layer WGS84 bounding rectangle (can be empty).
bool setBoundingRect(const QgsProject *project, QgsWmsLayerInfos &pLayer, QgsMapLayer *ml, const QgsRectangle &wmsExtent, const QgsCoordinateReferenceSystem &wgs84, const QList< QgsCoordinateReferenceSystem > &outputCrsList)