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 );
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.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
QgsTileMatrix tileMatrix(int zoom) const
Returns the tile matrix corresponding to the specified zoom.
QgsRectangle extent() const
Returns extent of the tile matrix.
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(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.
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...
Encapsulates properties of a vector tile matrix set, including tile origins and scaling information.
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)