QGIS API Documentation 3.29.0-Master (da8bb1db43)
qgsvectortileutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvectortileutils.cpp
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#include "qgsvectortileutils.h"
17
18#include <math.h>
19
20#include <QPolygon>
21
24#include "qgsfields.h"
25#include "qgslogger.h"
26#include "qgsmaptopixel.h"
27#include "qgsrectangle.h"
28#include "qgsvectorlayer.h"
29
31#include "qgsvectortilelayer.h"
33
34
35
37{
38 QgsRectangle r = tm.tileExtent( id );
39 QgsPointXY p00a = mtp.transform( ct.transform( r.xMinimum(), r.yMinimum() ) );
40 QgsPointXY p11a = mtp.transform( ct.transform( r.xMaximum(), r.yMaximum() ) );
41 QgsPointXY p01a = mtp.transform( ct.transform( r.xMinimum(), r.yMaximum() ) );
42 QgsPointXY p10a = mtp.transform( ct.transform( r.xMaximum(), r.yMinimum() ) );
43 QPolygon path;
44 path << p00a.toQPointF().toPoint();
45 path << p01a.toQPointF().toPoint();
46 path << p11a.toQPointF().toPoint();
47 path << p10a.toQPointF().toPoint();
48 return path;
49}
50
52{
53 QgsFields fields;
54 QStringList fieldsSorted = qgis::setToList( flds );
55 std::sort( fieldsSorted.begin(), fieldsSorted.end() );
56 for ( const QString &fieldName : std::as_const( fieldsSorted ) )
57 {
58 fields.append( QgsField( fieldName, QVariant::String ) );
59 }
60 return fields;
61}
62
63double QgsVectorTileUtils::scaleToZoom( double mapScale, double z0Scale )
64{
65 double s0 = z0Scale;
66 double tileZoom2 = log( s0 / mapScale ) / log( 2 );
67 tileZoom2 -= 1; // TODO: it seems that map scale is double (is that because of high-dpi screen?)
68 return tileZoom2;
69}
70
71int QgsVectorTileUtils::scaleToZoomLevel( double mapScale, int sourceMinZoom, int sourceMaxZoom, double z0Scale )
72{
73 int tileZoom = static_cast<int>( round( scaleToZoom( mapScale, z0Scale ) ) );
74
75 if ( tileZoom < sourceMinZoom )
76 tileZoom = sourceMinZoom;
77 if ( tileZoom > sourceMaxZoom )
78 tileZoom = sourceMaxZoom;
79
80 return tileZoom;
81}
82
84{
85 QgsVectorTileMVTDecoder decoder( mvt->tileMatrixSet() );
86 decoder.decode( tileID, mvt->getRawTile( tileID ) );
87 QSet<QString> fieldNames = qgis::listToSet( decoder.layerFieldNames( layerName ) );
88 fieldNames << QStringLiteral( "_geom_type" );
89 QMap<QString, QgsFields> perLayerFields;
90 QgsFields fields = QgsVectorTileUtils::makeQgisFields( fieldNames );
91 perLayerFields[layerName] = fields;
92 QgsVectorTileFeatures data = decoder.layerFeatures( perLayerFields, QgsCoordinateTransform() );
93 QgsFeatureList featuresList = data[layerName].toList();
94
95 // turn all geometries to geom. collections (otherwise they won't be accepted by memory provider)
96 for ( int i = 0; i < featuresList.count(); ++i )
97 {
98 QgsGeometry g = featuresList[i].geometry();
100 const QgsAbstractGeometry *gg = g.constGet();
101 if ( const QgsGeometryCollection *ggc = qgsgeometry_cast<const QgsGeometryCollection *>( gg ) )
102 {
103 for ( int k = 0; k < ggc->numGeometries(); ++k )
104 gc->addGeometry( ggc->geometryN( k )->clone() );
105 }
106 else
107 gc->addGeometry( gg->clone() );
108 featuresList[i].setGeometry( QgsGeometry( gc ) );
109 }
110
111 QgsVectorLayer *vl = new QgsVectorLayer( QStringLiteral( "GeometryCollection" ), layerName, QStringLiteral( "memory" ) );
112 vl->dataProvider()->addAttributes( fields.toList() );
113 vl->updateFields();
114 bool res = vl->dataProvider()->addFeatures( featuresList );
115 Q_UNUSED( res )
116 Q_ASSERT( res );
117 Q_ASSERT( featuresList.count() == vl->featureCount() );
118 vl->updateExtents();
119 QgsDebugMsgLevel( QStringLiteral( "Layer %1 features %2" ).arg( layerName ).arg( vl->featureCount() ), 2 );
120 return vl;
121}
122
123
124QString QgsVectorTileUtils::formatXYZUrlTemplate( const QString &url, QgsTileXYZ tile, const QgsTileMatrix &tileMatrix )
125{
126 QString turl( url );
127
128 turl.replace( QLatin1String( "{x}" ), QString::number( tile.column() ), Qt::CaseInsensitive );
129 if ( turl.contains( QLatin1String( "{-y}" ) ) )
130 {
131 turl.replace( QLatin1String( "{-y}" ), QString::number( tileMatrix.matrixHeight() - tile.row() - 1 ), Qt::CaseInsensitive );
132 }
133 else
134 {
135 turl.replace( QLatin1String( "{y}" ), QString::number( tile.row() ), Qt::CaseInsensitive );
136 }
137 turl.replace( QLatin1String( "{z}" ), QString::number( tile.zoomLevel() ), Qt::CaseInsensitive );
138 return turl;
139}
140
142{
143 return url.contains( QStringLiteral( "{x}" ) ) &&
144 ( url.contains( QStringLiteral( "{y}" ) ) || url.contains( QStringLiteral( "{-y}" ) ) ) &&
145 url.contains( QStringLiteral( "{z}" ) );
146}
147
150{
151 QPointF center;
153 {
154 QPointF p1( req1.column() + 0.5, req1.row() + 0.5 );
155 QPointF p2( req2.column() + 0.5, req2.row() + 0.5 );
156 // using chessboard distance (loading order more natural than euclidean/manhattan distance)
157 double d1 = std::max( std::fabs( center.x() - p1.x() ), std::fabs( center.y() - p1.y() ) );
158 double d2 = std::max( std::fabs( center.x() - p2.x() ), std::fabs( center.y() - p2.y() ) );
159 return d1 < d2;
160 }
161};
162
163QVector<QgsTileXYZ> QgsVectorTileUtils::tilesInRange( QgsTileRange range, int zoomLevel )
164{
165 QVector<QgsTileXYZ> tiles;
166 for ( int tileRow = range.startRow(); tileRow <= range.endRow(); ++tileRow )
167 {
168 for ( int tileColumn = range.startColumn(); tileColumn <= range.endColumn(); ++tileColumn )
169 {
170 tiles.append( QgsTileXYZ( tileColumn, tileRow, zoomLevel ) );
171 }
172 }
173 return tiles;
174}
175
176void QgsVectorTileUtils::sortTilesByDistanceFromCenter( QVector<QgsTileXYZ> &tiles, QPointF center )
177{
179 cmp.center = center;
180 std::sort( tiles.begin(), tiles.end(), cmp );
181}
Abstract base class for all geometries.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
Class for doing transforms between two map coordinate systems.
QgsPointXY transform(const QgsPointXY &point, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
Container of fields for a vector layer.
Definition: qgsfields.h:45
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfields.cpp:212
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
Geometry collection.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:39
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.h:90
A class to represent a 2D point.
Definition: qgspointxy.h:59
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspointxy.h:169
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
Defines a matrix of tiles for a single zoom level: it is defined by its size (width *.
Definition: qgstiles.h:108
QgsRectangle tileExtent(QgsTileXYZ id) const
Returns extent of the given tile in this matrix.
Definition: qgstiles.cpp:80
int matrixHeight() const
Returns number of rows of the tile matrix.
Definition: qgstiles.h:160
Range of tiles in a tile matrix to be rendered.
Definition: qgstiles.h:71
int endColumn() const
Returns index of the last column in the range.
Definition: qgstiles.h:83
int endRow() const
Returns index of the last row in the range.
Definition: qgstiles.h:87
int startRow() const
Returns index of the first row in the range.
Definition: qgstiles.h:85
int startColumn() const
Returns index of the first column in the range.
Definition: qgstiles.h:81
Stores coordinates of a tile in a tile matrix set.
Definition: qgstiles.h:38
int zoomLevel() const
Returns tile's zoom level (Z)
Definition: qgstiles.h:51
int column() const
Returns tile's column index (X)
Definition: qgstiles.h:47
int row() const
Returns tile's row index (Y)
Definition: qgstiles.h:49
bool addFeatures(QgsFeatureList &flist, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
virtual bool addAttributes(const QList< QgsField > &attributes)
Adds new attributes to the provider.
Represents a vector layer which manages a vector based data sets.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
virtual void updateExtents(bool force=false)
Update the extents for the layer.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Implements a map layer that is dedicated to rendering of vector tiles.
QByteArray getRawTile(QgsTileXYZ tileID)
Fetches raw tile data for the give tile coordinates.
QgsVectorTileMatrixSet & tileMatrixSet()
Returns the vector tile matrix set.
This class is responsible for decoding raw tile data written with Mapbox Vector Tiles encoding.
QStringList layerFieldNames(const QString &layerName) const
Returns a list of all field names in a tile. It can only be called after a successful decode()
QgsVectorTileFeatures layerFeatures(const QMap< QString, QgsFields > &perLayerFields, const QgsCoordinateTransform &ct, const QSet< QString > *layerSubset=nullptr) const
Returns decoded features grouped by sub-layers.
bool decode(QgsTileXYZ tileID, const QByteArray &rawTileData)
Tries to decode raw tile data, returns true on success.
static QgsVectorLayer * makeVectorLayerForTile(QgsVectorTileLayer *mvt, QgsTileXYZ tileID, const QString &layerName)
Returns a temporary vector layer for given sub-layer of tile in vector tile layer.
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...
static QVector< QgsTileXYZ > tilesInRange(QgsTileRange range, int zoomLevel)
Returns a list of tiles in the given tile range.
static void sortTilesByDistanceFromCenter(QVector< QgsTileXYZ > &tiles, QPointF center)
Orders tile requests according to the distance from view center (given in tile matrix coords)
static QPolygon tilePolygon(QgsTileXYZ id, const QgsCoordinateTransform &ct, const QgsTileMatrix &tm, const QgsMapToPixel &mtp)
Returns polygon (made by four corners of the tile) in screen coordinates.
static double scaleToZoom(double mapScale, double z0Scale=559082264.0287178)
Finds zoom level given map scale denominator.
static int scaleToZoomLevel(double mapScale, int sourceMinZoom, int sourceMaxZoom, double z0Scale=559082264.0287178)
Finds the best fitting zoom level given a map scale denominator and allowed zoom level range.
static QgsFields makeQgisFields(const QSet< QString > &flds)
Returns QgsFields instance based on the set of field names.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:920
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QMap< QString, QVector< QgsFeature > > QgsVectorTileFeatures
Features of a vector tile, grouped by sub-layer names (key of the map)
a helper class for ordering tile requests according to the distance from view center
bool operator()(QgsTileXYZ req1, QgsTileXYZ req2)
QPointF center
Center in tile matrix (!) coordinates.