QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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// ===================================
128// Get wms layer infos
129// ===================================
130QMap<QString, QgsWmsLayerInfos> QgsWmsLayerInfos::buildWmsLayerInfos( QgsServerInterface *serverIface, const QgsProject *project, const QList<QgsCoordinateReferenceSystem> &outputCrsList )
131{
132 QMap<QString, QgsWmsLayerInfos> wmsLayers;
133#ifdef HAVE_SERVER_PYTHON_PLUGINS
134 QgsAccessControl *accessControl = serverIface->accessControls();
135#else
136 ( void ) serverIface;
137#endif
138
139 bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
140 const QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
141 const QgsRectangle wmsExtent = QgsServerProjectUtils::wmsExtent( *project );
143
144 for ( QgsMapLayer *ml : project->mapLayers() )
145 {
146 if ( !ml || restrictedLayers.contains( ml->name() ) ) //unpublished layer
147 {
148 continue;
149 }
150
151#ifdef HAVE_SERVER_PYTHON_PLUGINS
152 if ( accessControl && !accessControl->layerReadPermission( ml ) )
153 {
154 continue;
155 }
156#endif
157
158 QgsWmsLayerInfos pLayer;
159 pLayer.id = ml->id();
160
161 // Calculate layer extents for the WMS output CRSes list
162 // First define if the layer has an extent
163 // Vector layer with No Geometry has no extent the other has one
164 bool hasExtent = true;
165 if ( ml->type() == Qgis::LayerType::Vector )
166 {
167 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( ml );
168 if ( !vLayer || vLayer->wkbType() == Qgis::WkbType::NoGeometry )
169 {
170 hasExtent = false;
171 }
172 }
173
174 // If the layer has an extent and we cannot get CRS bounding boxes, do not keep the layer
175 if ( hasExtent && !setBoundingRect( project, pLayer, ml, wmsExtent, wgs84, outputCrsList ) )
176 continue;
177
178 // layer type
179 pLayer.type = ml->type();
180 // layer wms name
181 pLayer.name = ml->name();
182 if ( useLayerIds )
183 {
184 pLayer.name = ml->id();
185 }
186 else if ( !ml->serverProperties()->shortName().isEmpty() )
187 {
188 pLayer.name = ml->serverProperties()->shortName();
189 }
190 // layer is queryable
191 pLayer.queryable = ml->flags().testFlag( QgsMapLayer::Identifiable );
192 // layer styles
193 pLayer.styles = ml->styleManager()->styles();
194 // layer legend URL
195 pLayer.legendUrl = ml->serverProperties()->legendUrl();
196 // layer legend URL format
197 pLayer.legendUrlFormat = ml->serverProperties()->legendUrlFormat();
198 // layer min/max scales
199 if ( ml->hasScaleBasedVisibility() )
200 {
201 pLayer.hasScaleBasedVisibility = ml->hasScaleBasedVisibility();
202 pLayer.maxScale = ml->maximumScale();
203 pLayer.minScale = ml->minimumScale();
204 }
205
206 wmsLayers[pLayer.id] = pLayer;
207 }
208
209 return wmsLayers;
210}
@ 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:6714
@ NoGeometry
No geometry.
Definition qgis.h:312
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(), 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: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)