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
[email protected]
https://lists.osgeo.org/mailman/listinfo/gdal-dev

--
http://www.spatialys.com
My software is free, but my time generally not.
_______________________________________________
gdal-dev mailing list
[email protected]
https://lists.osgeo.org/mailman/listinfo/gdal-dev

Reply via email to