35 : mStructure( structure )
42 if ( !tile.ParseFromArray( rawTileData.
data.constData(), rawTileData.
data.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 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 );
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.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
void reserve(int size)
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)
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 xMinimum() const
Returns the x minimum value (left side of rectangle).
double width() const
Returns the width of the rectangle.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
double height() const
Returns the height 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.
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()
bool decode(const QgsVectorTileRawData &rawTileData)
Tries to decode raw tile data, returns true on success.
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.
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.
Keeps track of raw tile data that need to be decoded.
QByteArray data
Raw tile data.
QgsTileXYZ tileGeometryId
Tile id associated with the raw tile data.
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
#define QgsDebugError(str)
QMap< QString, QVector< QgsFeature > > QgsVectorTileFeatures
Features of a vector tile, grouped by sub-layer names (key of the map)