[gdal-dev] Decoding feature blobs and tracking FIDs in MVT datasets
Even Rouault
even.rouault at spatialys.com
Sun Nov 23 06:30:41 PST 2025
Linda,
the FID returned by the MVT driver, when opening on a directory, is a
composition of the (X,Y,Z) of the tile and the feature id within it.
The id part of the tile is
https://github.com/OSGeo/gdal/blob/master/ogr/ogrsf_frmts/mvt/ogrmvtdataset.cpp#L1672
:
m_nFIDBase = (static_cast<GIntBig>(nX) << m_nZ) | nY;
and then the feature ID is computed at
https://github.com/OSGeo/gdal/blob/master/ogr/ogrsf_frmts/mvt/ogrmvtdataset.cpp#L1873:
poFeature->SetFID(m_nFIDBase +
(poUnderlyingFeature->GetFID() << (2 *
m_nZ)));
so the ID in the tile is
(GetFID() - m_nFIDBase) >> (2 * m_nZ)
But I'm realizing that the (X,Y,Z) of the tile when reading the
directory are not accessible
Maybe you best chance is to slightly modify the driver so it creates a
field with that information
Even
Le 23/11/2025 à 13:01, Linda Kladivová via gdal-dev a écrit :
>
> Hi,
>
>
> I’d like to ask about one specific aspect of the MVT driver. In my
> workflow, I need to track the FIDs of features inside an MVT dataset
> together with their corresponding internal codes (actual parcel IDs).
>
>
> My use case involves an MVT dataset of about 20 million features that
> is frequently updated. For this purpose, I have implemented an
> extension of the MVT driver that can open an MVT dataset in update
> mode and create/delete features based on changes detected by a
> preceding ETL process. Updates typically affect only a few individual
> features every hour.
>
>
> After the initial loading of the full dataset using |ogr2ogr| I need a
> way to iterate through the dataset and build a separate table mapping
> each internal FID to the parcel’s real ID. I have tried opening and
> inspecting the |temp.db| file (which I do not delete):
>
>
> GDALDataset* poTempDb =
> (GDALDataset*) GDALOpenEx(dstTempDb.c_str(),
> GDAL_OF_VECTOR, nullptr, nullptr, nullptr);
>
> OGRLayer* poTempLayer = poTempDb->GetLayerByName("temp");
> poTempLayer->ResetReading();
>
> OGRFeature* poFeat = nullptr;
>
> while ((poFeat = poTempLayer->GetNextFeature()) != nullptr)
> {
> GIntBig fid = poFeat->GetFID();
> std::cout << "FID=" << fid << " — ";
> int idx = poFeat->GetFieldIndex("feature");
> int blobSize = 0;
> const GByte* pBlob = poFeat->GetFieldAsBinary(idx, &blobSize);
> std::cout << " Blob size=" << blobSize << std::endl;
> }
>
> I can successfully access the |feature| blob, but I need to decode it
> in order to extract my custom parcel ID attribute and store those
> values externally. This would allow me to keep track of which parcel
> corresponds to which internal FID.
>
>
> This is a one-time (potentially slow) process. Afterward, during
> incremental updates, I will be calling |CreateFeature| and
> |DeleteFeature| (and updating my external mapping table accordingly).
> For edits, I currently use a combination of |DeleteFeature| and
> |CreateFeature| (I haven’t implemented |SetFeature| yet).
>
>
> My question is:
> Is there a way to decode this blob using existing GDAL/MVT
> functionality, or would this require implementing a new function?
>
> Thank you very much for your help.
>
>
> Linda Karlovská
>
>
> _______________________________________________
> gdal-dev mailing list
> gdal-dev at lists.osgeo.org
> https://lists.osgeo.org/mailman/listinfo/gdal-dev
--
http://www.spatialys.com
My software is free, but my time generally not.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/gdal-dev/attachments/20251123/36e8e582/attachment.htm>
More information about the gdal-dev
mailing list