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 QgsFields layerFields = perLayerFields[layerName];
115 const auto allLayerFields = perLayerFields.find( QString() );
116 if ( allLayerFields != perLayerFields.end() )
119 for (
const QgsField &field : allLayerFields.value() )
121 if ( layerFields.
lookupField( field.name() ) == -1 )
123 layerFields.
append( field );
129 QHash<int, int> tagKeyIndexToFieldIndex;
130 for (
int i = 0; i < layer.keys_size(); ++i )
132 const int fieldIndex = layerFields.
indexOf( layer.keys( i ).c_str() );
133 if ( fieldIndex != -1 )
134 tagKeyIndexToFieldIndex.insert( i, fieldIndex );
138 for (
int featureNum = 0; featureNum < layer.features_size(); featureNum++ )
140 const ::vector_tile::Tile_Feature &feature = layer.features( featureNum );
146 if ( feature.has_id() )
155 fid |= ( layerNum & 0xff ) << 24;
166 for (
int tagNum = 0; tagNum + 1 < feature.tags_size(); tagNum += 2 )
168 const int keyIndex =
static_cast<int>( feature.tags( tagNum ) );
169 const int fieldIndex = tagKeyIndexToFieldIndex.value( keyIndex, -1 );
170 if ( fieldIndex == -1 )
173 const int valueIndex =
static_cast<int>( feature.tags( tagNum + 1 ) );
174 if ( valueIndex >= layer.values_size() )
176 QgsDebugError( QStringLiteral(
"Invalid value index for attribute" ) );
179 const ::vector_tile::Tile_Value &value = layer.values( valueIndex );
181 if ( value.has_string_value() )
182 f.
setAttribute( fieldIndex, QString::fromStdString( value.string_value() ) );
183 else if ( value.has_float_value() )
184 f.
setAttribute( fieldIndex,
static_cast<double>( value.float_value() ) );
185 else if ( value.has_double_value() )
187 else if ( value.has_int_value() )
188 f.
setAttribute( fieldIndex,
static_cast<int>( value.int_value() ) );
189 else if ( value.has_uint_value() )
190 f.
setAttribute( fieldIndex,
static_cast<int>( value.uint_value() ) );
191 else if ( value.has_sint_value() )
192 f.
setAttribute( fieldIndex,
static_cast<int>( value.sint_value() ) );
193 else if ( value.has_bool_value() )
194 f.
setAttribute( fieldIndex,
static_cast<bool>( value.bool_value() ) );
197 QgsDebugError( QStringLiteral(
"Unexpected attribute value" ) );
205 const int extent =
static_cast<int>( layer.extent() );
206 int cursorx = 0, cursory = 0;
208 QVector<QgsPoint *> outputPoints;
209 QVector<QgsLineString *> outputLinestrings;
210 QVector<QgsPolygon *> outputPolygons;
211 QVector<QgsPoint> tmpPoints;
213 for (
int i = 0; i < feature.geometry_size(); i ++ )
215 const unsigned g = feature.geometry( i );
216 const unsigned cmdId = g & 0x7;
217 const unsigned cmdCount = g >> 3;
220 if ( i +
static_cast<int>( cmdCount ) * 2 >= feature.geometry_size() )
222 QgsDebugError( QStringLiteral(
"Malformed geometry: invalid cmdCount" ) );
226 if ( feature.type() == vector_tile::Tile_GeomType_POINT )
227 outputPoints.reserve( outputPoints.size() + cmdCount );
229 tmpPoints.reserve( tmpPoints.size() + cmdCount );
231 for (
unsigned j = 0; j < cmdCount; j++ )
233 const unsigned v = feature.geometry( i + 1 );
234 const unsigned w = feature.geometry( i + 2 );
235 const int dx = ( ( v >> 1 ) ^ ( -( v & 1 ) ) );
236 const int dy = ( ( w >> 1 ) ^ ( -( w & 1 ) ) );
239 const double px = tileXMin + tileDX * double( cursorx ) / double( extent );
240 const double py = tileYMax - tileDY * double( cursory ) / double( extent );
242 if ( feature.type() == vector_tile::Tile_GeomType_POINT )
244 outputPoints.append(
new QgsPoint( px, py ) );
246 else if ( feature.type() == vector_tile::Tile_GeomType_LINESTRING )
248 if ( tmpPoints.size() > 0 )
253 tmpPoints.append(
QgsPoint( px, py ) );
255 else if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
257 tmpPoints.append(
QgsPoint( px, py ) );
262 else if ( cmdId == 2 )
264 if ( i +
static_cast<int>( cmdCount ) * 2 >= feature.geometry_size() )
266 QgsDebugError( QStringLiteral(
"Malformed geometry: invalid cmdCount" ) );
269 tmpPoints.reserve( tmpPoints.size() + cmdCount );
270 for (
unsigned j = 0; j < cmdCount; j++ )
272 const unsigned v = feature.geometry( i + 1 );
273 const unsigned w = feature.geometry( i + 2 );
274 const int dx = ( ( v >> 1 ) ^ ( -( v & 1 ) ) );
275 const int dy = ( ( w >> 1 ) ^ ( -( w & 1 ) ) );
278 const double px = tileXMin + tileDX * double( cursorx ) / double( extent );
279 const double py = tileYMax - tileDY * double( cursory ) / double( extent );
281 tmpPoints.push_back(
QgsPoint( px, py ) );
285 else if ( cmdId == 7 )
287 if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
289 tmpPoints.append( tmpPoints.first() );
291 std::unique_ptr<QgsLineString> ring(
new QgsLineString( tmpPoints ) );
299 outputPolygons.append( p );
304 if ( outputPolygons.count() != 0 )
306 outputPolygons[outputPolygons.count() - 1]->addInteriorRing( ring.release() );
310 QgsDebugError( QStringLiteral(
"Malformed geometry: first ring of a polygon is interior ring" ) );
318 QgsDebugError( QStringLiteral(
"Unexpected command ID: %1" ).arg( cmdId ) );
323 if ( feature.type() == vector_tile::Tile_GeomType_POINT )
325 geomType = QStringLiteral(
"Point" );
326 if ( outputPoints.count() == 1 )
331 mp->
reserve( outputPoints.count() );
332 for (
int k = 0; k < outputPoints.count(); ++k )
337 else if ( feature.type() == vector_tile::Tile_GeomType_LINESTRING )
339 geomType = QStringLiteral(
"LineString" );
344 if ( outputLinestrings.count() == 1 )
349 mls->
reserve( outputLinestrings.size() );
350 for (
int k = 0; k < outputLinestrings.count(); ++k )
355 else if ( feature.type() == vector_tile::Tile_GeomType_POLYGON )
357 geomType = QStringLiteral(
"Polygon" );
359 if ( outputPolygons.count() == 1 )
364 mpl->
reserve( outputPolygons.size() );
365 for (
int k = 0; k < outputPolygons.count(); ++k )
371 f.
setAttribute( QStringLiteral(
"_geom_type" ), geomType );