35 : mStructure( structure )
42 if ( !tile.ParseFromArray( rawTileData.constData(), rawTileData.count() ) )
47 mLayerNameToIndex.clear();
48 for (
int layerNum = 0; layerNum < tile.layers_size(); layerNum++ )
50 const ::vector_tile::Tile_Layer &layer = tile.layers( layerNum );
51 const QString layerName = layer.name().c_str();
52 mLayerNameToIndex[layerName] = layerNum;
59 QStringList layerNames;
60 const int layerSize = tile.layers_size();
61 layerNames.reserve( layerSize );
62 for (
int layerNum = 0; layerNum < layerSize; layerNum++ )
64 const ::vector_tile::Tile_Layer &layer = tile.layers( layerNum );
65 const QString layerName = layer.name().c_str();
66 layerNames << layerName;
73 if ( !mLayerNameToIndex.contains( layerName ) )
76 const ::vector_tile::Tile_Layer &layer = tile.layers( mLayerNameToIndex[layerName] );
77 QStringList fieldNames;
78 const int size = layer.keys_size();
79 fieldNames.reserve( size );
80 for (
int i = 0; i < size; ++i )
82 const QString fieldName = layer.keys( i ).c_str();
83 fieldNames << fieldName;
92 const int numTiles =
static_cast<int>( pow( 2, mTileID.
zoomLevel() ) );
99 const double tileDX = z0Width / numTiles;
100 const double tileDY = z0Height / numTiles;
101 const double tileXMin = z0xMinimum + mTileID.
column() * tileDX;
102 const double tileYMax = z0yMaximum - mTileID.
row() * tileDY;
104 for (
int layerNum = 0; layerNum < tile.layers_size(); layerNum++ )
106 const ::vector_tile::Tile_Layer &layer = tile.layers( layerNum );
108 const QString layerName = layer.name().c_str();
109 if ( layerSubset && !layerSubset->contains( QString() ) && !layerSubset->contains( layerName ) )
113 const QgsFields layerFields = perLayerFields[layerName];
116 QHash<int, int> tagKeyIndexToFieldIndex;
117 for (
int i = 0; i < layer.keys_size(); ++i )
119 const int fieldIndex = layerFields.
indexOf( layer.keys( i ).c_str() );
120 if ( fieldIndex != -1 )
121 tagKeyIndexToFieldIndex.insert( i, fieldIndex );
125 for (
int featureNum = 0; featureNum < layer.features_size(); featureNum++ )
127 const ::vector_tile::Tile_Feature &feature = layer.features( featureNum );
133 if ( feature.has_id() )
142 fid |= ( layerNum & 0xff ) << 24;
153 for (
int tagNum = 0; tagNum + 1 < feature.tags_size(); tagNum += 2 )
155 const int keyIndex =
static_cast<int>( feature.tags( tagNum ) );
156 const int fieldIndex = tagKeyIndexToFieldIndex.value( keyIndex, -1 );
157 if ( fieldIndex == -1 )
160 const int valueIndex =
static_cast<int>( feature.tags( tagNum + 1 ) );
161 if ( valueIndex >= layer.values_size() )
163 QgsDebugMsg( QStringLiteral(
"Invalid value index for attribute" ) );
166 const ::vector_tile::Tile_Value &value = layer.values( valueIndex );
168 if ( value.has_string_value() )
169 f.
setAttribute( fieldIndex, QString::fromStdString( value.string_value() ) );
170 else if ( value.has_float_value() )
171 f.
setAttribute( fieldIndex,
static_cast<double>( value.float_value() ) );
172 else if ( value.has_double_value() )
174 else if ( value.has_int_value() )
175 f.
setAttribute( fieldIndex,
static_cast<int>( value.int_value() ) );
176 else if ( value.has_uint_value() )
177 f.
setAttribute( fieldIndex,
static_cast<int>( value.uint_value() ) );
178 else if ( value.has_sint_value() )
179 f.
setAttribute( fieldIndex,
static_cast<int>( value.sint_value() ) );
180 else if ( value.has_bool_value() )
181 f.
setAttribute( fieldIndex,
static_cast<bool>( value.bool_value() ) );
184 QgsDebugMsg( QStringLiteral(
"Unexpected attribute value" ) );
192 const int extent =
static_cast<int>( layer.extent() );
193 int cursorx = 0, cursory = 0;
195 QVector<QgsPoint *> outputPoints;
196 QVector<QgsLineString *> outputLinestrings;
197 QVector<QgsPolygon *> outputPolygons;
198 QVector<QgsPoint> tmpPoints;
200 for (
int i = 0; i < feature.geometry_size(); i ++ )
202 const unsigned g = feature.geometry( i );
203 const unsigned cmdId = g & 0x7;
204 const unsigned cmdCount = g >> 3;
207 if ( i +
static_cast<int>( cmdCount ) * 2 >= feature.geometry_size() )
209 QgsDebugMsg( QStringLiteral(
"Malformed geometry: invalid cmdCount" ) );
213 if ( feature.type() == vector_tile::Tile_GeomType_POINT )
214 outputPoints.reserve( outputPoints.size() + cmdCount );
216 tmpPoints.reserve( tmpPoints.size() + cmdCount );
218 for (
unsigned j = 0; j < cmdCount; j++ )
220 const unsigned v = feature.geometry( i + 1 );
221 const unsigned w = feature.geometry( i + 2 );
222 const int dx = ( ( v >> 1 ) ^ ( -( v & 1 ) ) );
223 const int dy = ( ( w >> 1 ) ^ ( -( w & 1 ) ) );
226 const double px = tileXMin + tileDX * double( cursorx ) / double( extent );
227 const double py = tileYMax - tileDY * double( cursory ) / double( extent );
229 if ( feature.type() == vector_tile::Tile_GeomType_POINT )
231 outputPoints.append(
new QgsPoint( px, py ) );
233 else if ( feature.type() == vector_tile::Tile_GeomType_LINESTRING )
235 if ( tmpPoints.size() > 0 )
240 tmpPoints.append(
QgsPoint( px, py ) );
242 else if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
244 tmpPoints.append(
QgsPoint( px, py ) );
249 else if ( cmdId == 2 )
251 if ( i +
static_cast<int>( cmdCount ) * 2 >= feature.geometry_size() )
253 QgsDebugMsg( QStringLiteral(
"Malformed geometry: invalid cmdCount" ) );
256 tmpPoints.reserve( tmpPoints.size() + cmdCount );
257 for (
unsigned j = 0; j < cmdCount; j++ )
259 const unsigned v = feature.geometry( i + 1 );
260 const unsigned w = feature.geometry( i + 2 );
261 const int dx = ( ( v >> 1 ) ^ ( -( v & 1 ) ) );
262 const int dy = ( ( w >> 1 ) ^ ( -( w & 1 ) ) );
265 const double px = tileXMin + tileDX * double( cursorx ) / double( extent );
266 const double py = tileYMax - tileDY * double( cursory ) / double( extent );
268 tmpPoints.push_back(
QgsPoint( px, py ) );
272 else if ( cmdId == 7 )
274 if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
276 tmpPoints.append( tmpPoints.first() );
278 std::unique_ptr<QgsLineString> ring(
new QgsLineString( tmpPoints ) );
286 outputPolygons.append( p );
291 if ( outputPolygons.count() != 0 )
293 outputPolygons[outputPolygons.count() - 1]->addInteriorRing( ring.release() );
297 QgsDebugMsg( QStringLiteral(
"Malformed geometry: first ring of a polygon is interior ring" ) );
305 QgsDebugMsg( QStringLiteral(
"Unexpected command ID: %1" ).arg( cmdId ) );
310 if ( feature.type() == vector_tile::Tile_GeomType_POINT )
312 geomType = QStringLiteral(
"Point" );
313 if ( outputPoints.count() == 1 )
318 mp->
reserve( outputPoints.count() );
319 for (
int k = 0; k < outputPoints.count(); ++k )
324 else if ( feature.type() == vector_tile::Tile_GeomType_LINESTRING )
326 geomType = QStringLiteral(
"LineString" );
331 if ( outputLinestrings.count() == 1 )
336 mls->
reserve( outputLinestrings.size() );
337 for (
int k = 0; k < outputLinestrings.count(); ++k )
342 else if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
344 geomType = QStringLiteral(
"Polygon" );
346 if ( outputPolygons.count() == 1 )
351 mpl->
reserve( outputPolygons.size() );
352 for (
int k = 0; k < outputPolygons.count(); ++k )
358 f.
setAttribute( QStringLiteral(
"_geom_type" ), geomType );
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Container of fields for a vector layer.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
void reserve(int size) SIP_HOLDGIL
Attempts to allocate memory for at least size geometries.
A geometry is the spatial representation of a feature.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Line string geometry type, with support for z-dimension and m-values.
Multi line string geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Multi point geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Multi polygon geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Point geometry type, with support for z-dimension and m-values.
void setExteriorRing(QgsCurve *ring) override
Sets the exterior ring of the polygon.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
QgsTileMatrix rootMatrix() const
Returns the root tile matrix (usually corresponding to zoom level 0).
Defines a matrix of tiles for a single zoom level: it is defined by its size (width *.
QgsRectangle extent() const
Returns extent of the tile matrix.
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)
~QgsVectorTileMVTDecoder()
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()
QStringList layers() const
Returns a list of sub-layer names in a tile. It can only be called after a successful decode()
QgsVectorTileMVTDecoder(const QgsVectorTileMatrixSet &structure)
Constructor for QgsVectorTileMVTDecoder, using the specified tile structure.
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 bool isExteriorRing(const QgsLineString *lineString)
Returns whether this linear ring forms an exterior ring according to MVT spec (depending on the orien...
Encapsulates properties of a vector tile matrix set, including tile origins and scaling information.
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QMap< QString, QVector< QgsFeature > > QgsVectorTileFeatures
Features of a vector tile, grouped by sub-layer names (key of the map)