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 );