1 /*************************************************************************** 2 qgsvectortilewriter.h 3 -------------------------------------- 4 Date : April 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 QGSVECTORTILEWRITER_H 17 #define QGSVECTORTILEWRITER_H 18 19 #include <QCoreApplication> 20 #include "qgstiles.h" 21 #include "qgsrectangle.h" 22 #include "qgscoordinatetransformcontext.h" 23 #include "qgscoordinatereferencesystem.h" 24 25 class QgsFeedback; 26 class QgsTileMatrix; 27 class QgsTileXYZ; 28 class QgsVectorLayer; 29 30 31 /** 32 * \ingroup core 33 * \brief Takes care of writing vector tiles. The intended use is to set up the class 34 * by setting the destination URI, extent, zoom level range and input vector 35 * layers. Then with a call to writeTiles() the data gets written. In case 36 * of a failure, errorMessage() returns the cause of the problem during writing. 37 * 38 * The syntax of destination URIs is the same like the data source string 39 * used by vector tile layers: parameters are encoded as a HTTP query string, 40 * where "type" key determines the type of the destination container, 41 * the "url" key is normally the path. Currently supported types: 42 * 43 * - "xyz" - tile data written as local files, using a template where {x},{y},{z} 44 * are replaced by the actual tile column, row and zoom level numbers, e.g.: 45 * file:///home/qgis/tiles/{z}/{x}/{y}.pbf 46 * - "mbtiles" - tile data written to a new MBTiles file, the "url" key should 47 * be ordinary file system path, e.g.: /home/qgis/output.mbtiles 48 * 49 * Currently the writer only support MVT encoding of data. 50 * 51 * Metadata support: it is possible to pass a QVariantMap with metadata. This 52 * is backend dependent. Currently only "mbtiles" source type supports writing 53 * of metadata. The key-value pairs will be written to the "metadata" table 54 * in the MBTiles file. Some useful metadata keys listed here, but see MBTiles spec 55 * for more details: 56 * 57 * - "name" - human-readable name of the tileset 58 * - "bounds" - extent in WGS 84: "minlon,minlat,maxlon,maxlat" 59 * - "center" - default view of the map: "longitude,latitude,zoomlevel" 60 * - "minzoom" - lowest zoom level 61 * - "maxzoom" - highest zoom level 62 * - "attribution" - string that explains the sources of data 63 * - "description" - descriptions of the content 64 * - "type" - whether this is an overlay or a basemap 65 * - "version" - version of the tileset 66 * 67 * Vector tile writer always writes "format" and "json" metadata. If not specified 68 * in metadata by the client, tile writer also writes "name", "bounds", "minzoom" 69 * and "maxzoom". 70 * 71 * 72 * \since QGIS 3.14 73 */ 74 class CORE_EXPORT QgsVectorTileWriter 75 { 76 Q_DECLARE_TR_FUNCTIONS( QgsVectorTileWriter ) 77 78 public: 79 QgsVectorTileWriter(); 80 81 /** 82 * \ingroup core 83 * \brief Configuration of a single input vector layer to be included in the output 84 * \since QGIS 3.14 85 */ 86 class Layer 87 { 88 public: 89 //! Constructs an entry for a vector layer Layer(QgsVectorLayer * layer)90 explicit Layer( QgsVectorLayer *layer ) 91 : mLayer( layer ) 92 { 93 } 94 95 //! Returns vector layer of this entry layer()96 QgsVectorLayer *layer() const { return mLayer; } 97 98 //! Returns filter expression. If not empty, only features matching the expression will be used filterExpression()99 QString filterExpression() const { return mFilterExpression; } 100 //! Sets filter expression. If not empty, only features matching the expression will be used setFilterExpression(const QString & expr)101 void setFilterExpression( const QString &expr ) { mFilterExpression = expr; } 102 103 //! Returns layer name in the output. If not set, layer()->name() will be used. layerName()104 QString layerName() const { return mLayerName; } 105 //! Sets layer name in the output. If not set, layer()->name() will be used. setLayerName(const QString & name)106 void setLayerName( const QString &name ) { mLayerName = name; } 107 108 //! Returns minimum zoom level at which this layer will be used. Negative value means no min. zoom level minZoom()109 int minZoom() const { return mMinZoom; } 110 //! Sets minimum zoom level at which this layer will be used. Negative value means no min. zoom level setMinZoom(int minzoom)111 void setMinZoom( int minzoom ) { mMinZoom = minzoom; } 112 113 //! Returns maximum zoom level at which this layer will be used. Negative value means no max. zoom level maxZoom()114 int maxZoom() const { return mMaxZoom; } 115 //! Sets maximum zoom level at which this layer will be used. Negative value means no max. zoom level setMaxZoom(int maxzoom)116 void setMaxZoom( int maxzoom ) { mMaxZoom = maxzoom; } 117 118 private: 119 QgsVectorLayer *mLayer; 120 QString mFilterExpression; 121 QString mLayerName; 122 int mMinZoom = -1; 123 int mMaxZoom = -1; 124 }; 125 126 /** 127 * Sets where and how the vector tiles will be written. 128 * See the class description about the syntax of destination URIs. 129 */ setDestinationUri(const QString & uri)130 void setDestinationUri( const QString &uri ) { mDestinationUri = uri; } 131 132 /** 133 * Sets extent of vector tile output. 134 * If unset, it will use the full extent of all input layers combined 135 */ setExtent(const QgsRectangle & extent)136 void setExtent( const QgsRectangle &extent ) { mExtent = extent; } 137 138 //! Sets the minimum zoom level of tiles. Allowed values are in interval [0,24] setMinZoom(int minZoom)139 void setMinZoom( int minZoom ) { mMinZoom = minZoom; } 140 //! Sets the maximum zoom level of tiles. Allowed values are in interval [0,24] setMaxZoom(int maxZoom)141 void setMaxZoom( int maxZoom ) { mMaxZoom = maxZoom; } 142 143 //! Sets vector layers and their configuration for output of vector tiles setLayers(const QList<QgsVectorTileWriter::Layer> & layers)144 void setLayers( const QList<QgsVectorTileWriter::Layer> &layers ) { mLayers = layers; } 145 146 //! Sets that will be written to the output dataset. See class description for more on metadata support setMetadata(const QVariantMap & metadata)147 void setMetadata( const QVariantMap &metadata ) { mMetadata = metadata; } 148 149 //! Sets coordinate transform context for transforms between layers and tile matrix CRS setTransformContext(const QgsCoordinateTransformContext & transformContext)150 void setTransformContext( const QgsCoordinateTransformContext &transformContext ) { mTransformContext = transformContext; } 151 152 /** 153 * Sets zoom level 0 tile matrix 154 */ 155 bool setRootTileMatrix( const QgsTileMatrix &tileMatrix ); 156 157 /** 158 * Writes vector tiles according to the configuration. 159 * Returns TRUE on success (upon failure one can get error cause using errorMessage()) 160 * 161 * If a pointer to a feedback object is provided, it can be used to track progress or 162 * provide cancellation functionality. 163 */ 164 bool writeTiles( QgsFeedback *feedback = nullptr ); 165 166 /** 167 * Returns error message related to the previous call to writeTiles(). Will return 168 * an empty string if writing was successful. 169 */ errorMessage()170 QString errorMessage() const { return mErrorMessage; } 171 172 //! Returns calculated extent that combines extent of all input layers 173 QgsRectangle fullExtent() const; 174 175 /** 176 * Encodes single MVT tile 177 * 178 * \param tileID Tile identifier 179 * \param feedback optional, provide cancellation functionality 180 * \param resolution the resolution of coordinates of geometries within the tile. The default is 4096 181 * \param buffer size of the buffer zone around tile edges in integer tile coordinates. The default is 256 (~6%) 182 * 183 * Returns a QByteArray with the encoded data 184 * 185 * \since QGIS 3.22 186 */ 187 QByteArray writeSingleTile( QgsTileXYZ tileID, QgsFeedback *feedback = nullptr, int buffer = 256, int resolution = 4096 ) const; 188 189 private: 190 bool writeTileFileXYZ( const QString &sourcePath, QgsTileXYZ tileID, const QgsTileMatrix &tileMatrix, const QByteArray &tileData ); 191 QString mbtilesJsonSchema(); 192 193 private: 194 QgsTileMatrix mRootTileMatrix; 195 QgsRectangle mExtent; 196 int mMinZoom = 0; 197 int mMaxZoom = 4; 198 QList<Layer> mLayers; 199 QString mDestinationUri; 200 QVariantMap mMetadata; 201 QgsCoordinateTransformContext mTransformContext; 202 203 QString mErrorMessage; 204 }; 205 206 #endif // QGSVECTORTILEWRITER_H 207