28 #include <nlohmann/json.hpp>
45 mErrorMessage = tr(
"Invalid min. zoom level" );
50 mErrorMessage = tr(
"Invalid max. zoom level" );
54 std::unique_ptr<QgsMbTiles> mbtiles;
59 QString sourceType = dsUri.
param( QStringLiteral(
"type" ) );
60 QString sourcePath = dsUri.
param( QStringLiteral(
"url" ) );
61 if ( sourceType == QLatin1String(
"xyz" ) )
64 sourcePath = QUrl( sourcePath ).toLocalFile();
68 mErrorMessage = tr(
"Invalid template for XYZ: " ) + sourcePath;
72 else if ( sourceType == QLatin1String(
"mbtiles" ) )
78 mErrorMessage = tr(
"Unsupported source type for writing: " ) + sourceType;
88 mErrorMessage = tr(
"Failed to calculate output extent" );
94 int tilesToCreate = 0;
95 for (
int zoomLevel = mMinZoom; zoomLevel <= mMaxZoom; ++zoomLevel )
100 tilesToCreate += ( tileRange.
endRow() - tileRange.
startRow() + 1 ) *
104 if ( tilesToCreate == 0 )
106 mErrorMessage = tr(
"No tiles to generate" );
112 if ( !mbtiles->create() )
114 mErrorMessage = tr(
"Failed to create MBTiles file: " ) + sourcePath;
119 mbtiles->setMetadataValue(
"format",
"pbf" );
120 mbtiles->setMetadataValue(
"json", mbtilesJsonSchema() );
123 const QStringList metaKeys = mMetadata.keys();
124 for (
const QString &key : metaKeys )
126 mbtiles->setMetadataValue( key, mMetadata[key].toString() );
130 if ( !mMetadata.contains(
"name" ) )
131 mbtiles->setMetadataValue(
"name",
"unnamed" );
132 if ( !mMetadata.contains(
"minzoom" ) )
133 mbtiles->setMetadataValue(
"minzoom", QString::number( mMinZoom ) );
134 if ( !mMetadata.contains(
"maxzoom" ) )
135 mbtiles->setMetadataValue(
"maxzoom", QString::number( mMaxZoom ) );
136 if ( !mMetadata.contains(
"bounds" ) )
142 QString boundsStr = QString(
"%1,%2,%3,%4" )
145 mbtiles->setMetadataValue(
"bounds", boundsStr );
154 int tilesCreated = 0;
155 for (
int zoomLevel = mMinZoom; zoomLevel <= mMaxZoom; ++zoomLevel )
160 for (
int row = tileRange.
startRow(); row <= tileRange.
endRow(); ++row )
168 for (
const Layer &layer : std::as_const( mLayers ) )
170 if ( ( layer.minZoom() >= 0 && zoomLevel < layer.minZoom() ) ||
171 ( layer.maxZoom() >= 0 && zoomLevel > layer.maxZoom() ) )
174 encoder.
addLayer( layer.layer(), feedback, layer.filterExpression(), layer.layerName() );
179 mErrorMessage = tr(
"Operation has been canceled" );
183 QByteArray tileData = encoder.
encode();
188 feedback->
setProgress(
static_cast<double>( tilesCreated ) / tilesToCreate * 100 );
191 if ( tileData.isEmpty() )
197 if ( sourceType == QLatin1String(
"xyz" ) )
199 if ( !writeTileFileXYZ( sourcePath, tileID, tileMatrix, tileData ) )
204 QByteArray gzipTileData;
206 int rowTMS = pow( 2, tileID.
zoomLevel() ) - tileID.
row() - 1;
207 mbtiles->setTileData( tileID.
zoomLevel(), tileID.
column(), rowTMS, gzipTileData );
221 for (
const Layer &layer : mLayers )
232 QgsDebugMsg(
"Failed to reproject layer extent to destination CRS" );
238 bool QgsVectorTileWriter::writeTileFileXYZ(
const QString &sourcePath,
QgsTileXYZ tileID,
const QgsTileMatrix &tileMatrix,
const QByteArray &tileData )
243 QFileInfo fi( filePath );
244 QDir fileDir = fi.dir();
245 if ( !fileDir.exists() )
247 if ( !fileDir.mkpath(
"." ) )
249 mErrorMessage = tr(
"Cannot create directory " ) + fileDir.path();
255 if ( !f.open( QIODevice::WriteOnly ) )
257 mErrorMessage = tr(
"Cannot open file for writing " ) + filePath;
267 QString QgsVectorTileWriter::mbtilesJsonSchema()
269 QVariantList arrayLayers;
270 for (
const Layer &layer : std::as_const( mLayers ) )
275 QVariantMap fieldsObj;
278 QString fieldTypeStr;
280 fieldTypeStr = QStringLiteral(
"Boolean" );
282 fieldTypeStr = QStringLiteral(
"Number" );
284 fieldTypeStr = QStringLiteral(
"String" );
289 QVariantMap layerObj;
290 layerObj[
"id"] = vl->
name();
291 layerObj[
"fields"] = fieldsObj;
292 arrayLayers.append( layerObj );
296 rootObj[
"vector_layers"] = arrayLayers;
This class represents a coordinate reference system (CRS).
Custom exception class for Coordinate Reference System related exceptions.
Class for storing the component parts of a RDBMS data source URI (e.g.
void setEncodedUri(const QByteArray &uri)
Sets the complete encoded uri.
QString param(const QString &key) const
Returns a generic parameter value corresponding to the specified key.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
static json jsonFromVariant(const QVariant &v)
Converts a QVariant v to a json object.
QgsCoordinateReferenceSystem crs
Utility class for reading and writing MBTiles files (which are SQLite3 databases).
static bool encodeGzip(const QByteArray &bytesIn, QByteArray &bytesOut)
Encodes gzip byte stream, returns true on success. Useful for writing vector tiles.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
bool isEmpty() const
Returns true if the rectangle is empty.
Defines a matrix of tiles for a single zoom level: it is defined by its size (width *.
QgsTileRange tileRangeFromExtent(const QgsRectangle &mExtent)
Returns tile range that fully covers the given extent.
static QgsTileMatrix fromWebMercator(int mZoomLevel)
Returns a tile matrix for the usual web mercator.
Range of tiles in a tile matrix to be rendered.
int endColumn() const
Returns index of the last column in the range.
int endRow() const
Returns index of the last row in the range.
int startRow() const
Returns index of the first row in the range.
int startColumn() const
Returns index of the first column in the range.
Stores coordinates of a tile in a tile matrix set.
int zoomLevel() const
Returns tile's zoom level (Z)
int column() const
Returns tile's column index (X)
int row() const
Returns tile's row index (Y)
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
Handles conversion of vector features to Mapbox vector tiles encoding.
void addLayer(QgsVectorLayer *layer, QgsFeedback *feedback=nullptr, QString filterExpression=QString(), QString layerName=QString())
Fetches data from vector layer for the given tile, does reprojection and clipping.
QByteArray encode() const
Encodes MVT using data stored previously with addLayer() calls.
void setTransformContext(const QgsCoordinateTransformContext &transformContext)
Sets coordinate transform context for transforms between layers and tile matrix CRS.
static bool checkXYZUrlTemplate(const QString &url)
Checks whether the URL template string is correct (contains {x}, {y} / {-y}, {z} placeholders)
static QString formatXYZUrlTemplate(const QString &url, QgsTileXYZ tile, const QgsTileMatrix &tileMatrix)
Returns formatted tile URL string replacing {x}, {y}, {z} placeholders (or {-y} instead of {y} for TM...
Configuration of a single input vector layer to be included in the output.
QgsRectangle fullExtent() const
Returns calculated extent that combines extent of all input layers.
bool writeTiles(QgsFeedback *feedback=nullptr)
Writes vector tiles according to the configuration.