115  const int numTiles = 
static_cast<int>( pow( 2, mTileID.
zoomLevel() ) ); 
 
  117  const double z0Width = rootMatrix.
extent().
width();
 
  122  const double tileDX = z0Width / numTiles;
 
  123  const double tileDY = z0Height / numTiles;
 
  124  const double tileXMin = z0xMinimum + mTileID.
column() * tileDX;
 
  125  const double tileYMax = z0yMaximum - mTileID.
row() * tileDY;
 
  127  QMap<QString, vector_tile::Tile>::const_iterator it = tiles.constBegin();
 
  128  for ( ; it != tiles.constEnd(); ++it )
 
  130    vector_tile::Tile tile = it.value();
 
  132    for ( 
int layerNum = 0; layerNum < tile.layers_size(); layerNum++ )
 
  134      const ::vector_tile::Tile_Layer &layer = tile.layers( layerNum );
 
  136      const QString layerName = layer.name().c_str();
 
  137      if ( layerSubset && !layerSubset->contains( QString() ) && !layerSubset->contains( layerName ) )
 
  141      QgsFields layerFields = perLayerFields[layerName];
 
  143      const auto allLayerFields = perLayerFields.find( QString() );
 
  144      if ( allLayerFields != perLayerFields.end() )
 
  147        for ( 
const QgsField &field : allLayerFields.value() )
 
  149          if ( layerFields.
lookupField( field.name() ) == -1 )
 
  151            layerFields.
append( field );
 
  157      QHash<int, int> tagKeyIndexToFieldIndex;
 
  158      for ( 
int i = 0; i < layer.keys_size(); ++i )
 
  160        const int fieldIndex = layerFields.
indexOf( layer.keys( i ).c_str() );
 
  161        if ( fieldIndex != -1 )
 
  162          tagKeyIndexToFieldIndex.insert( i, fieldIndex );
 
  166      for ( 
int featureNum = 0; featureNum < layer.features_size(); featureNum++ )
 
  168        const ::vector_tile::Tile_Feature &feature = layer.features( featureNum );
 
  176          fid |= ( layerNum & 0xff ) << 24;
 
  187        for ( 
int tagNum = 0; tagNum + 1 < feature.tags_size(); tagNum += 2 )
 
  189          const int keyIndex = 
static_cast<int>( feature.tags( tagNum ) );
 
  190          const int fieldIndex = tagKeyIndexToFieldIndex.value( keyIndex, -1 );
 
  191          if ( fieldIndex == -1 )
 
  194          const int valueIndex = 
static_cast<int>( feature.tags( tagNum + 1 ) );
 
  195          if ( valueIndex >= layer.values_size() )
 
  197            QgsDebugError( QStringLiteral( 
"Invalid value index for attribute" ) );
 
  200          const ::vector_tile::Tile_Value &value = layer.values( valueIndex );
 
  202          if ( value.has_string_value() )
 
  203            f.
setAttribute( fieldIndex, QString::fromStdString( value.string_value() ) );
 
  204          else if ( value.has_float_value() )
 
  205            f.
setAttribute( fieldIndex, 
static_cast<double>( value.float_value() ) );
 
  206          else if ( value.has_double_value() )
 
  208          else if ( value.has_int_value() )
 
  209            f.
setAttribute( fieldIndex, 
static_cast<long long>( value.int_value() ) );
 
  210          else if ( value.has_uint_value() )
 
  211            f.
setAttribute( fieldIndex, 
static_cast<long long>( value.uint_value() ) );
 
  212          else if ( value.has_sint_value() )
 
  213            f.
setAttribute( fieldIndex, 
static_cast<long long>( value.sint_value() ) );
 
  214          else if ( value.has_bool_value() )
 
  215            f.
setAttribute( fieldIndex, 
static_cast<bool>( value.bool_value() ) );
 
  218            QgsDebugError( QStringLiteral( 
"Unexpected attribute value" ) );
 
  226        const int extent = 
static_cast<int>( layer.extent() );
 
  227        int cursorx = 0, cursory = 0;
 
  229        QVector<QgsPoint *> outputPoints; 
 
  230        QVector<QgsLineString *> outputLinestrings;  
 
  231        QVector<QgsPolygon *> outputPolygons;
 
  232        QVector<QgsPoint> tmpPoints;
 
  234        for ( 
int i = 0; i < feature.geometry_size(); i ++ )
 
  236          const unsigned g = feature.geometry( i );
 
  237          const unsigned cmdId = g & 0x7;
 
  238          const int cmdCount = 
static_cast<int>( g >> 3 );
 
  241            if ( i + 
static_cast<int>( cmdCount ) * 2 >= feature.geometry_size() )
 
  243              QgsDebugError( QStringLiteral( 
"Malformed geometry: invalid cmdCount" ) );
 
  247            if ( feature.type() == vector_tile::Tile_GeomType_POINT )
 
  248              outputPoints.reserve( 
static_cast<int>( outputPoints.size() ) + cmdCount );
 
  250              tmpPoints.reserve( 
static_cast<int>( tmpPoints.size() ) + cmdCount );
 
  252            for ( 
int j = 0; j < cmdCount; j++ )
 
  254              const int v = 
static_cast<int>( feature.geometry( i + 1 ) );
 
  255              const int w = 
static_cast<int>( feature.geometry( i + 2 ) );
 
  256              const int dx = ( ( v >> 1 ) ^ ( -( v & 1 ) ) );
 
  257              const int dy = ( ( w >> 1 ) ^ ( -( w & 1 ) ) );
 
  260              const double px = tileXMin + tileDX * double( cursorx ) / double( extent );
 
  261              const double py = tileYMax - tileDY * double( cursory ) / double( extent );
 
  263              if ( feature.type() == vector_tile::Tile_GeomType_POINT )
 
  265                outputPoints.append( 
new QgsPoint( px, py ) );
 
  267              else if ( feature.type() == vector_tile::Tile_GeomType_LINESTRING )
 
  269                if ( tmpPoints.size() > 0 )
 
  274                tmpPoints.append( 
QgsPoint( px, py ) );
 
  276              else if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
 
  278                tmpPoints.append( 
QgsPoint( px, py ) );
 
  283          else if ( cmdId == 2 ) 
 
  285            if ( i + 
static_cast<int>( cmdCount ) * 2 >= feature.geometry_size() )
 
  287              QgsDebugError( QStringLiteral( 
"Malformed geometry: invalid cmdCount" ) );
 
  290            tmpPoints.reserve( tmpPoints.size() + cmdCount );
 
  291            for ( 
int j = 0; j < cmdCount; j++ )
 
  293              const int v = 
static_cast<int>( feature.geometry( i + 1 ) );
 
  294              const int w = 
static_cast<int>( feature.geometry( i + 2 ) );
 
  295              const int dx = ( v >> 1 ) ^ ( -( v & 1 ) );
 
  296              const int dy = ( w >> 1 ) ^ ( -( w & 1 ) );
 
  299              const double px = tileXMin + tileDX * double( cursorx ) / double( extent );
 
  300              const double py = tileYMax - tileDY * double( cursory ) / double( extent );
 
  302              tmpPoints.push_back( 
QgsPoint( px, py ) );
 
  306          else if ( cmdId == 7 ) 
 
  308            if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
 
  310              tmpPoints.append( tmpPoints.first() );  
 
  312              auto ring = std::make_unique<QgsLineString>( tmpPoints );
 
  320                outputPolygons.append( p );
 
  325                if ( outputPolygons.count() != 0 )
 
  327                  outputPolygons[outputPolygons.count() - 1]->addInteriorRing( ring.release() );
 
  331                  QgsDebugError( QStringLiteral( 
"Malformed geometry: first ring of a polygon is interior ring" ) );
 
  339            QgsDebugError( QStringLiteral( 
"Unexpected command ID: %1" ).arg( cmdId ) );
 
  344        if ( feature.type() == vector_tile::Tile_GeomType_POINT )
 
  346          geomType = QStringLiteral( 
"Point" );
 
  347          if ( outputPoints.count() == 1 )
 
  352            mp->
reserve( outputPoints.count() );
 
  353            for ( 
int k = 0; k < outputPoints.count(); ++k )
 
  358        else if ( feature.type() == vector_tile::Tile_GeomType_LINESTRING )
 
  360          geomType = QStringLiteral( 
"LineString" );
 
  365          if ( outputLinestrings.count() == 1 )
 
  370            mls->
reserve( outputLinestrings.size() );
 
  371            for ( 
int k = 0; k < outputLinestrings.count(); ++k )
 
  376        else if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
 
  378          geomType = QStringLiteral( 
"Polygon" );
 
  380          if ( outputPolygons.count() == 1 )
 
  385            mpl->
reserve( outputPolygons.size() );
 
  386            for ( 
int k = 0; k < outputPolygons.count(); ++k )
 
  392        f.
setAttribute( QStringLiteral( 
"_geom_type" ), geomType );