QGIS API Documentation 3.99.0-Master (e9821da5c6b)
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,
39 const QgsCoordinateReferenceSystem &source,
40 const QgsCoordinateReferenceSystem &destination,
41 const QgsCoordinateTransformContext &context,
42 const bool &ballparkTransformsAreAppropriate
43)
44{
45 QgsCoordinateTransform transformer { source, destination, context };
46 transformer.setBallparkTransformsAreAppropriate( ballparkTransformsAreAppropriate );
47 // Transform extent and do not catch exception
48 return transformer.transformBoundingBox( extent );
49}
50
52 const QgsRectangle &extent,
53 const QgsCoordinateReferenceSystem &source,
54 const QList<QgsCoordinateReferenceSystem> &destinations,
56)
57{
58 QMap<QString, QgsRectangle> crsExtents;
59 if ( extent.isEmpty() )
60 {
61 return crsExtents;
62 }
63 for ( const QgsCoordinateReferenceSystem &destination : std::as_const( destinations ) )
64 {
65 // Transform extent and do not catch exception
66 QgsCoordinateTransform crsTransform { source, destination, context };
67 crsExtents[destination.authid()] = crsTransform.transformBoundingBox( extent );
68 }
69 return crsExtents;
70}
71
72
74 const QgsProject *project,
75 QgsWmsLayerInfos &pLayer,
76 QgsMapLayer *ml,
77 const QgsRectangle &wmsExtent,
79 const QList<QgsCoordinateReferenceSystem> &outputCrsList
80)
81{
82 QgsRectangle layerExtent = ml->extent();
83 if ( layerExtent.isEmpty() )
84 {
85 // if the extent is empty (not only Null), use the wms extent
86 // defined in the project...
87 if ( wmsExtent.isNull() )
88 {
89 // or the CRS extent otherwise
90 layerExtent = ml->crs().bounds();
91 }
92 else
93 {
94 layerExtent = QgsRectangle( wmsExtent );
95 if ( ml->crs() != project->crs() )
96 {
97 // If CRS is different transform it to layer's CRS
98 try
99 {
100 layerExtent = QgsWmsLayerInfos::transformExtent( wmsExtent, project->crs(), ml->crs(), project->transformContext() );
101 }
102 catch ( QgsCsException &cse )
103 {
104 QgsMessageLog::logMessage( u"Error transforming extent for layer %1: %2"_s.arg( ml->name() ).arg( cse.what() ), u"Server"_s, Qgis::MessageLevel::Warning );
105 return false;
106 }
107 }
108 }
109
110 // Now we have a layer Extent we need the WGS84 bounding rectangle
111 try
112 {
113 pLayer.wgs84BoundingRect = QgsWmsLayerInfos::transformExtent( layerExtent, ml->crs(), wgs84, project->transformContext(), true );
114 }
115 catch ( const QgsCsException &cse )
116 {
117 QgsMessageLog::logMessage( u"Error transforming extent for layer %1: %2"_s.arg( ml->name() ).arg( cse.what() ), u"Server"_s, Qgis::MessageLevel::Warning );
118 return false;
119 }
120 }
121 else
122 {
123 pLayer.wgs84BoundingRect = ml->wgs84Extent();
124 }
125
126 try
127 {
129 layerExtent, ml->crs(), outputCrsList, project->transformContext()
130 );
131 }
132 catch ( QgsCsException &cse )
133 {
134 QgsMessageLog::logMessage( u"Error transforming extent for layer %1: %2"_s.arg( ml->name() ).arg( cse.what() ), u"Server"_s, Qgis::MessageLevel::Warning );
135 return false;
136 }
137
138 return true;
139}
140
141// ===================================
142// Get wms layer infos
143// ===================================
144QMap<QString, QgsWmsLayerInfos> QgsWmsLayerInfos::buildWmsLayerInfos(
145 QgsServerInterface *serverIface,
146 const QgsProject *project,
147 const QList<QgsCoordinateReferenceSystem> &outputCrsList
148)
149{
150 QMap<QString, QgsWmsLayerInfos> wmsLayers;
151#ifdef HAVE_SERVER_PYTHON_PLUGINS
152 QgsAccessControl *accessControl = serverIface->accessControls();
153#else
154 ( void ) serverIface;
155#endif
156
157 bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
158 const QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
159 const QgsRectangle wmsExtent = QgsServerProjectUtils::wmsExtent( *project );
161
162 for ( QgsMapLayer *ml : project->mapLayers() )
163 {
164 if ( !ml || restrictedLayers.contains( ml->name() ) ) //unpublished layer
165 {
166 continue;
167 }
168
169#ifdef HAVE_SERVER_PYTHON_PLUGINS
170 if ( accessControl && !accessControl->layerReadPermission( ml ) )
171 {
172 continue;
173 }
174#endif
175
176 QgsWmsLayerInfos pLayer;
177 pLayer.id = ml->id();
178
179 // Calculate layer extents for the WMS output CRSes list
180 // First define if the layer has an extent
181 // Vector layer with No Geometry has no extent the other has one
182 bool hasExtent = true;
183 if ( ml->type() == Qgis::LayerType::Vector )
184 {
185 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( ml );
186 if ( !vLayer || vLayer->wkbType() == Qgis::WkbType::NoGeometry )
187 {
188 hasExtent = false;
189 }
190 }
191
192 // If the layer has an extent and we cannot get CRS bounding boxes, do not keep the layer
193 if ( hasExtent && !setBoundingRect( project, pLayer, ml, wmsExtent, wgs84, outputCrsList ) )
194 continue;
195
196 // layer type
197 pLayer.type = ml->type();
198 // layer wms name
199 pLayer.name = ml->name();
200 if ( useLayerIds )
201 {
202 pLayer.name = ml->id();
203 }
204 else if ( !ml->serverProperties()->shortName().isEmpty() )
205 {
206 pLayer.name = ml->serverProperties()->shortName();
207 }
208 // layer is queryable
209 pLayer.queryable = ml->flags().testFlag( QgsMapLayer::Identifiable );
210 // layer styles
211 pLayer.styles = ml->styleManager()->styles();
212 // layer legend URL
213 pLayer.legendUrl = ml->serverProperties()->legendUrl();
214 // layer legend URL format
215 pLayer.legendUrlFormat = ml->serverProperties()->legendUrlFormat();
216 // layer min/max scales
217 if ( ml->hasScaleBasedVisibility() )
218 {
219 pLayer.hasScaleBasedVisibility = ml->hasScaleBasedVisibility();
220 pLayer.maxScale = ml->maximumScale();
221 pLayer.minScale = ml->minimumScale();
222 }
223
224 wmsLayers[pLayer.id] = pLayer;
225 }
226
227 return wmsLayers;
228}
@ Warning
Warning message.
Definition qgis.h:161
@ Vector
Vector layer.
Definition qgis.h:194
static QString geographicCrsAuthId()
Geographic coordinate system auth:id string for a default geographic CRS (EPSG:4326).
Definition qgis.h:6649
@ NoGeometry
No geometry.
Definition qgis.h:298
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
QgsRectangle wgs84Extent(bool forceRecalculate=false) const
Returns the WGS84 extent (EPSG:4326) of the layer according to ReadFlag::FlagTrustLayerMetadata.
virtual 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())
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:113
QgsCoordinateTransformContext transformContext
Definition qgsproject.h:120
QgsCoordinateReferenceSystem crs
Definition qgsproject.h:119
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 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)