40   if ( !tile.ParseFromArray( rawTileData.constData(), rawTileData.count() ) )
 
   45   mLayerNameToIndex.clear();
 
   46   for ( 
int layerNum = 0; layerNum < tile.layers_size(); layerNum++ )
 
   48     const ::vector_tile::Tile_Layer &layer = tile.layers( layerNum );
 
   49     const QString layerName = layer.name().c_str();
 
   50     mLayerNameToIndex[layerName] = layerNum;
 
   57   QStringList layerNames;
 
   58   for ( 
int layerNum = 0; layerNum < tile.layers_size(); layerNum++ )
 
   60     const ::vector_tile::Tile_Layer &layer = tile.layers( layerNum );
 
   61     const QString layerName = layer.name().c_str();
 
   62     layerNames << layerName;
 
   69   if ( !mLayerNameToIndex.contains( layerName ) )
 
   72   const ::vector_tile::Tile_Layer &layer = tile.layers( mLayerNameToIndex[layerName] );
 
   73   QStringList fieldNames;
 
   74   for ( 
int i = 0; i < layer.keys_size(); ++i )
 
   76     const QString fieldName = layer.keys( i ).c_str();
 
   77     fieldNames << fieldName;
 
   86   const int numTiles = 
static_cast<int>( pow( 2, mTileID.
zoomLevel() ) ); 
 
   87   double z0xMin = -20037508.3427892, z0yMin = -20037508.3427892;
 
   88   double z0xMax =  20037508.3427892, z0yMax =  20037508.3427892;
 
   89   const double tileDX = ( z0xMax - z0xMin ) / numTiles;
 
   90   const double tileDY = ( z0yMax - z0yMin ) / numTiles;
 
   91   const double tileXMin = z0xMin + mTileID.
column() * tileDX;
 
   92   const double tileYMax = z0yMax - mTileID.
row() * tileDY;
 
   94   for ( 
int layerNum = 0; layerNum < tile.layers_size(); layerNum++ )
 
   96     const ::vector_tile::Tile_Layer &layer = tile.layers( layerNum );
 
   98     const QString layerName = layer.name().c_str();
 
   99     if ( layerSubset && !layerSubset->contains( QString() ) && !layerSubset->contains( layerName ) )
 
  103     const QgsFields layerFields = perLayerFields[layerName];
 
  106     QHash<int, int> tagKeyIndexToFieldIndex;
 
  107     for ( 
int i = 0; i < layer.keys_size(); ++i )
 
  109       const int fieldIndex = layerFields.
indexOf( layer.keys( i ).c_str() );
 
  110       if ( fieldIndex != -1 )
 
  111         tagKeyIndexToFieldIndex.insert( i, fieldIndex );
 
  115     for ( 
int featureNum = 0; featureNum < layer.features_size(); featureNum++ )
 
  117       const ::vector_tile::Tile_Feature &feature = layer.features( featureNum );
 
  123       if ( feature.has_id() )
 
  132         fid |= ( layerNum & 0xff ) << 24;
 
  143       for ( 
int tagNum = 0; tagNum + 1 < feature.tags_size(); tagNum += 2 )
 
  145         const int keyIndex = 
static_cast<int>( feature.tags( tagNum ) );
 
  146         const int fieldIndex = tagKeyIndexToFieldIndex.value( keyIndex, -1 );
 
  147         if ( fieldIndex == -1 )
 
  150         const int valueIndex = 
static_cast<int>( feature.tags( tagNum + 1 ) );
 
  151         if ( valueIndex >= layer.values_size() )
 
  153           QgsDebugMsg( QStringLiteral( 
"Invalid value index for attribute" ) );
 
  156         const ::vector_tile::Tile_Value &value = layer.values( valueIndex );
 
  158         if ( value.has_string_value() )
 
  159           f.
setAttribute( fieldIndex, QString::fromStdString( value.string_value() ) );
 
  160         else if ( value.has_float_value() )
 
  161           f.
setAttribute( fieldIndex, 
static_cast<double>( value.float_value() ) );
 
  162         else if ( value.has_double_value() )
 
  164         else if ( value.has_int_value() )
 
  165           f.
setAttribute( fieldIndex, 
static_cast<int>( value.int_value() ) );
 
  166         else if ( value.has_uint_value() )
 
  167           f.
setAttribute( fieldIndex, 
static_cast<int>( value.uint_value() ) );
 
  168         else if ( value.has_sint_value() )
 
  169           f.
setAttribute( fieldIndex, 
static_cast<int>( value.sint_value() ) );
 
  170         else if ( value.has_bool_value() )
 
  171           f.
setAttribute( fieldIndex, 
static_cast<bool>( value.bool_value() ) );
 
  174           QgsDebugMsg( QStringLiteral( 
"Unexpected attribute value" ) );
 
  182       const int extent = 
static_cast<int>( layer.extent() );
 
  183       int cursorx = 0, cursory = 0;
 
  185       QVector<QgsPoint *> outputPoints; 
 
  186       QVector<QgsLineString *> outputLinestrings;  
 
  187       QVector<QgsPolygon *> outputPolygons;
 
  188       QVector<QgsPoint> tmpPoints;
 
  190       for ( 
int i = 0; i < feature.geometry_size(); i ++ )
 
  192         const unsigned g = feature.geometry( i );
 
  193         const unsigned cmdId = g & 0x7;
 
  194         const unsigned cmdCount = g >> 3;
 
  197           if ( i + 
static_cast<int>( cmdCount ) * 2 >= feature.geometry_size() )
 
  199             QgsDebugMsg( QStringLiteral( 
"Malformed geometry: invalid cmdCount" ) );
 
  203           if ( feature.type() == vector_tile::Tile_GeomType_POINT )
 
  204             outputPoints.reserve( outputPoints.size() + cmdCount );
 
  206             tmpPoints.reserve( tmpPoints.size() + cmdCount );
 
  208           for ( 
unsigned j = 0; j < cmdCount; j++ )
 
  210             const unsigned v = feature.geometry( i + 1 );
 
  211             const unsigned w = feature.geometry( i + 2 );
 
  212             const int dx = ( ( v >> 1 ) ^ ( -( v & 1 ) ) );
 
  213             const int dy = ( ( w >> 1 ) ^ ( -( w & 1 ) ) );
 
  216             const double px = tileXMin + tileDX * double( cursorx ) / double( extent );
 
  217             const double py = tileYMax - tileDY * double( cursory ) / double( extent );
 
  219             if ( feature.type() == vector_tile::Tile_GeomType_POINT )
 
  221               outputPoints.append( 
new QgsPoint( px, py ) );
 
  223             else if ( feature.type() == vector_tile::Tile_GeomType_LINESTRING )
 
  225               if ( tmpPoints.size() > 0 )
 
  230               tmpPoints.append( 
QgsPoint( px, py ) );
 
  232             else if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
 
  234               tmpPoints.append( 
QgsPoint( px, py ) );
 
  239         else if ( cmdId == 2 ) 
 
  241           if ( i + 
static_cast<int>( cmdCount ) * 2 >= feature.geometry_size() )
 
  243             QgsDebugMsg( QStringLiteral( 
"Malformed geometry: invalid cmdCount" ) );
 
  246           tmpPoints.reserve( tmpPoints.size() + cmdCount );
 
  247           for ( 
unsigned j = 0; j < cmdCount; j++ )
 
  249             const unsigned v = feature.geometry( i + 1 );
 
  250             const unsigned w = feature.geometry( i + 2 );
 
  251             const int dx = ( ( v >> 1 ) ^ ( -( v & 1 ) ) );
 
  252             const int dy = ( ( w >> 1 ) ^ ( -( w & 1 ) ) );
 
  255             const double px = tileXMin + tileDX * double( cursorx ) / double( extent );
 
  256             const double py = tileYMax - tileDY * double( cursory ) / double( extent );
 
  258             tmpPoints.push_back( 
QgsPoint( px, py ) );
 
  262         else if ( cmdId == 7 ) 
 
  264           if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
 
  266             tmpPoints.append( tmpPoints.first() );  
 
  268             std::unique_ptr<QgsLineString> ring( 
new QgsLineString( tmpPoints ) );
 
  276               outputPolygons.append( p );
 
  281               if ( outputPolygons.count() != 0 )
 
  283                 outputPolygons[outputPolygons.count() - 1]->addInteriorRing( ring.release() );
 
  287                 QgsDebugMsg( QStringLiteral( 
"Malformed geometry: first ring of a polygon is interior ring" ) );
 
  295           QgsDebugMsg( QStringLiteral( 
"Unexpected command ID: %1" ).arg( cmdId ) );
 
  300       if ( feature.type() == vector_tile::Tile_GeomType_POINT )
 
  302         geomType = QStringLiteral( 
"Point" );
 
  303         if ( outputPoints.count() == 1 )
 
  308           mp->
reserve( outputPoints.count() );
 
  309           for ( 
int k = 0; k < outputPoints.count(); ++k )
 
  314       else if ( feature.type() == vector_tile::Tile_GeomType_LINESTRING )
 
  316         geomType = QStringLiteral( 
"LineString" );
 
  321         if ( outputLinestrings.count() == 1 )
 
  326           mls->
reserve( outputLinestrings.size() );
 
  327           for ( 
int k = 0; k < outputLinestrings.count(); ++k )
 
  332       else if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
 
  334         geomType = QStringLiteral( 
"Polygon" );
 
  336         if ( outputPolygons.count() == 1 )
 
  341           mpl->
reserve( outputPolygons.size() );
 
  342           for ( 
int k = 0; k < outputPolygons.count(); ++k )
 
  348       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.
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()
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...
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)