1 /*************************************************************************** 2 qgsvectortilelayer.h 3 -------------------------------------- 4 Date : March 2020 5 Copyright : (C) 2020 by Martin Dobias 6 Email : wonder dot sk at gmail dot com 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 16 #ifndef QGSVECTORTILELAYER_H 17 #define QGSVECTORTILELAYER_H 18 19 #include "qgis_core.h" 20 #include "qgis_sip.h" 21 22 #include "qgsmaplayer.h" 23 24 class QgsVectorTileLabeling; 25 class QgsVectorTileRenderer; 26 27 class QgsTileXYZ; 28 29 /** 30 * \ingroup core 31 * \brief Implements a map layer that is dedicated to rendering of vector tiles. 32 * Vector tiles compared to "ordinary" vector layers are pre-processed data 33 * optimized for fast rendering. A dataset is provided with a series of zoom levels 34 * for different map scales. Each zoom level has a matrix of tiles that contain 35 * actual data. A single vector tile may be a a file stored on a local drive, 36 * requested over HTTP request or retrieved from a database. 37 * 38 * Content of a vector tile is divided into one or more named sub-layers. Each such 39 * sub-layer may contain many features which consist of geometry and attributes. 40 * Contrary to traditional vector layers, these sub-layers do not need to have a rigid 41 * schema where geometry type and attributes are the same for all features. A single 42 * sub-layer may have multiple geometry types in a single tile or have some attributes 43 * defined only at particular zoom levels. 44 * 45 * Vector tile layer currently does not use the concept of data providers that other 46 * layer types use. The process of rendering of vector tiles looks like this: 47 * 48 * +--------+ +------+ +---------+ 49 * | DATA | | RAW | | DECODED | 50 * | | --> LOADER --> | | --> DECODER --> | | --> RENDERER 51 * | SOURCE | | TILE | | TILE | 52 * +--------+ +------+ +---------+ 53 * 54 * Data source is a place from where tiles are fetched from (URL for HTTP access, local 55 * files, MBTiles file, GeoPackage file or others. Loader (QgsVectorTileLoader) class 56 * takes care of loading data from the data source. The "raw tile" data is just a blob 57 * (QByteArray) that is encoded in some way. There are multiple ways how vector tiles 58 * are encoded just like there are different formats how to store images. For example, 59 * tiles can be encoded using Mapbox Vector Tiles (MVT) format or in GeoJSON. Decoder 60 * (QgsVectorTileDecoder) takes care of decoding raw tile data into QgsFeature objects. 61 * A decoded tile is essentially an array of vector features for each sub-layer found 62 * in the tile - this is what vector tile renderer (QgsVectorTileRenderer) expects 63 * and does the map rendering. 64 * 65 * To construct a vector tile layer, it is best to use QgsDataSourceUri class and set 66 * the following parameters to get a valid encoded URI: 67 * 68 * - "type" - what kind of data source will be used 69 * - "url" - URL or path of the data source (specific to each data source type, see below) 70 * 71 * Currently supported data source types: 72 * 73 * - "xyz" - the "url" should be a template like http://example.com/{z}/{x}/{y}.pbf where 74 * {x},{y},{z} will be replaced by tile coordinates 75 * - "mbtiles" - tiles read from a MBTiles file (a SQLite database) 76 * 77 * Currently supported decoders: 78 * 79 * - MVT - following Mapbox Vector Tiles specification 80 * 81 * \since QGIS 3.14 82 */ 83 class CORE_EXPORT QgsVectorTileLayer : public QgsMapLayer 84 { 85 Q_OBJECT 86 87 public: 88 89 90 /** 91 * Setting options for loading vector tile layers. 92 * 93 * \since QGIS 3.22 94 */ 95 struct LayerOptions 96 { 97 98 /** 99 * Constructor for LayerOptions with optional \a transformContext. 100 */ 101 explicit LayerOptions( const QgsCoordinateTransformContext &transformContext = QgsCoordinateTransformContext( ) ) transformContextLayerOptions102 : transformContext( transformContext ) 103 {} 104 105 //! Coordinate transform context 106 QgsCoordinateTransformContext transformContext; 107 }; 108 109 //! Constructs a new vector tile layer 110 explicit QgsVectorTileLayer( const QString &path = QString(), const QString &baseName = QString(), const QgsVectorTileLayer::LayerOptions &options = QgsVectorTileLayer::LayerOptions() ); 111 ~QgsVectorTileLayer() override; 112 113 #ifdef SIP_RUN 114 SIP_PYOBJECT __repr__(); 115 % MethodCode 116 QString str = QStringLiteral( "<QgsVectorTileLayer: '%1'>" ).arg( sipCpp->name() ); 117 sipRes = PyUnicode_FromString( str.toUtf8().constData() ); 118 % End 119 #endif 120 121 // implementation of virtual functions from QgsMapLayer 122 123 QgsVectorTileLayer *clone() const override SIP_FACTORY; 124 QgsDataProvider *dataProvider() override; 125 const QgsDataProvider *dataProvider() const override SIP_SKIP; 126 QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY; 127 bool readXml( const QDomNode &layerNode, QgsReadWriteContext &context ) override; 128 bool writeXml( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const override; 129 bool readSymbology( const QDomNode &node, QString &errorMessage, 130 QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories ) override; 131 bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, 132 StyleCategories categories = AllStyleCategories ) const override; 133 void setTransformContext( const QgsCoordinateTransformContext &transformContext ) override; 134 QString loadDefaultStyle( bool &resultFlag SIP_OUT ) override; 135 136 /** 137 * Loads the default style for the layer, and returns TRUE if the style was 138 * successfully loaded. 139 * 140 * The \a error string will be filled with a translated error message if an error 141 * occurs during the style load. The \a warnings list will be populated with any 142 * warning messages generated during the style load (e.g. default style properties 143 * which could not be converted). 144 * 145 * \since QGIS 3.16 146 */ 147 bool loadDefaultStyle( QString &error, QStringList &warnings ) SIP_SKIP; 148 149 QString loadDefaultMetadata( bool &resultFlag SIP_OUT ) override; 150 151 QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const FINAL; 152 QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const FINAL; 153 QString htmlMetadata() const override; 154 155 // new methods 156 157 //! Returns type of the data source sourceType()158 QString sourceType() const { return mSourceType; } 159 //! Returns URL/path of the data source (syntax different to each data source type) sourcePath()160 QString sourcePath() const { return mSourcePath; } 161 162 //! Returns minimum zoom level at which source has any valid tiles (negative = unconstrained) sourceMinZoom()163 int sourceMinZoom() const { return mSourceMinZoom; } 164 //! Returns maximum zoom level at which source has any valid tiles (negative = unconstrained) sourceMaxZoom()165 int sourceMaxZoom() const { return mSourceMaxZoom; } 166 167 /** 168 * Fetches raw tile data for the give tile coordinates. If failed to fetch tile data, 169 * it will return an empty byte array. 170 * 171 * \note This call may issue a network request (depending on the source type) and will block 172 * the caller until the request is finished. 173 */ 174 QByteArray getRawTile( QgsTileXYZ tileID ) SIP_SKIP; 175 176 /** 177 * Sets renderer for the map layer. 178 * \note Takes ownership of the passed renderer 179 */ 180 void setRenderer( QgsVectorTileRenderer *r SIP_TRANSFER ); 181 //! Returns currently assigned renderer 182 QgsVectorTileRenderer *renderer() const; 183 184 /** 185 * Sets labeling for the map layer. 186 * \note Takes ownership of the passed labeling 187 */ 188 void setLabeling( QgsVectorTileLabeling *labeling SIP_TRANSFER ); 189 //! Returns currently assigned labeling 190 QgsVectorTileLabeling *labeling() const; 191 192 //! Sets whether to render also borders of tiles (useful for debugging) setTileBorderRenderingEnabled(bool enabled)193 void setTileBorderRenderingEnabled( bool enabled ) { mTileBorderRendering = enabled; } 194 //! Returns whether to render also borders of tiles (useful for debugging) isTileBorderRenderingEnabled()195 bool isTileBorderRenderingEnabled() const { return mTileBorderRendering; } 196 197 private: 198 bool loadDataSource(); 199 200 private: 201 //! Type of the data source 202 QString mSourceType; 203 //! URL/Path of the data source 204 QString mSourcePath; 205 //! Minimum zoom level at which source has any valid tiles (negative = unconstrained) 206 int mSourceMinZoom = -1; 207 //! Maximum zoom level at which source has any valid tiles (negative = unconstrained) 208 int mSourceMaxZoom = -1; 209 210 //! Renderer assigned to the layer to draw map 211 std::unique_ptr<QgsVectorTileRenderer> mRenderer; 212 //! Labeling assigned to the layer to produce labels 213 std::unique_ptr<QgsVectorTileLabeling> mLabeling; 214 //! Whether we draw borders of tiles 215 bool mTileBorderRendering = false; 216 217 QVariantMap mArcgisLayerConfiguration; 218 219 QgsCoordinateTransformContext mTransformContext; 220 221 std::unique_ptr< QgsDataProvider > mDataProvider; 222 223 bool setupArcgisVectorTileServiceConnection( const QString &uri, const QgsDataSourceUri &dataSourceUri ); 224 225 void setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, 226 const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags ) override; 227 228 }; 229 230 #ifndef SIP_RUN 231 ///@cond PRIVATE 232 233 /** 234 * A minimal data provider for vector tile layers. 235 * 236 * \since QGIS 3.22 237 */ 238 class QgsVectorTileDataProvider : public QgsDataProvider 239 { 240 Q_OBJECT 241 242 public: 243 QgsVectorTileDataProvider( const QgsDataProvider::ProviderOptions &providerOptions, 244 QgsDataProvider::ReadFlags flags ); 245 QgsCoordinateReferenceSystem crs() const override; 246 QString name() const override; 247 QString description() const override; 248 QgsRectangle extent() const override; 249 bool isValid() const override; 250 251 }; 252 ///@endcond 253 #endif 254 255 256 #endif // QGSVECTORTILELAYER_H 257