LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/pmtiles - ogrpmtilesdriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 64 73 87.7 %
Date: 2024-11-21 22:18:42 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implementation of PMTiles
       5             :  * Author:   Even Rouault <even.rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2023, Planet Labs
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_pmtiles.h"
      14             : 
      15             : #include "vsipmtiles.h"
      16             : 
      17             : #include "ogrpmtilesfrommbtiles.h"
      18             : 
      19             : #ifdef HAVE_MVT_WRITE_SUPPORT
      20             : #include "mvtutils.h"
      21             : #endif
      22             : 
      23             : /************************************************************************/
      24             : /*                     OGRPMTilesDriverIdentify()                       */
      25             : /************************************************************************/
      26             : 
      27       43110 : static int OGRPMTilesDriverIdentify(GDALOpenInfo *poOpenInfo)
      28             : {
      29       43110 :     if (poOpenInfo->nHeaderBytes < 127 || !poOpenInfo->fpL)
      30       42315 :         return FALSE;
      31         795 :     return memcmp(poOpenInfo->pabyHeader, "PMTiles\x03", 8) == 0;
      32             : }
      33             : 
      34             : /************************************************************************/
      35             : /*                       OGRPMTilesDriverOpen()                         */
      36             : /************************************************************************/
      37             : 
      38          42 : static GDALDataset *OGRPMTilesDriverOpen(GDALOpenInfo *poOpenInfo)
      39             : {
      40          42 :     if (!OGRPMTilesDriverIdentify(poOpenInfo))
      41           0 :         return nullptr;
      42          84 :     auto poDS = std::make_unique<OGRPMTilesDataset>();
      43          42 :     if (!poDS->Open(poOpenInfo))
      44           8 :         return nullptr;
      45          34 :     return poDS.release();
      46             : }
      47             : 
      48             : /************************************************************************/
      49             : /*                   OGRPMTilesDriverCanVectorTranslateFrom()           */
      50             : /************************************************************************/
      51             : 
      52           5 : static bool OGRPMTilesDriverCanVectorTranslateFrom(
      53             :     const char * /*pszDestName*/, GDALDataset *poSourceDS,
      54             :     CSLConstList papszVectorTranslateArguments, char ***ppapszFailureReasons)
      55             : {
      56           5 :     auto poSrcDriver = poSourceDS->GetDriver();
      57           5 :     if (!(poSrcDriver && EQUAL(poSrcDriver->GetDescription(), "MBTiles")))
      58             :     {
      59           1 :         if (ppapszFailureReasons)
      60           1 :             *ppapszFailureReasons = CSLAddString(
      61             :                 *ppapszFailureReasons, "Source driver is not MBTiles");
      62           1 :         return false;
      63             :     }
      64             : 
      65           4 :     if (papszVectorTranslateArguments)
      66             :     {
      67           2 :         const int nArgs = CSLCount(papszVectorTranslateArguments);
      68           4 :         for (int i = 0; i < nArgs; ++i)
      69             :         {
      70           2 :             if (i + 1 < nArgs &&
      71           2 :                 (strcmp(papszVectorTranslateArguments[i], "-f") == 0 ||
      72           0 :                  strcmp(papszVectorTranslateArguments[i], "-of") == 0))
      73             :             {
      74           2 :                 ++i;
      75             :             }
      76             :             else
      77             :             {
      78           0 :                 if (ppapszFailureReasons)
      79           0 :                     *ppapszFailureReasons =
      80           0 :                         CSLAddString(*ppapszFailureReasons,
      81             :                                      "Direct copy from MBTiles does not "
      82             :                                      "support GDALVectorTranslate() options");
      83           0 :                 return false;
      84             :             }
      85             :         }
      86             :     }
      87             : 
      88           4 :     return true;
      89             : }
      90             : 
      91             : /************************************************************************/
      92             : /*                   OGRPMTilesDriverVectorTranslateFrom()              */
      93             : /************************************************************************/
      94             : 
      95           2 : static GDALDataset *OGRPMTilesDriverVectorTranslateFrom(
      96             :     const char *pszDestName, GDALDataset *poSourceDS,
      97             :     CSLConstList papszVectorTranslateArguments,
      98             :     GDALProgressFunc /* pfnProgress */, void * /* pProgressData */)
      99             : {
     100           2 :     if (!OGRPMTilesDriverCanVectorTranslateFrom(
     101             :             pszDestName, poSourceDS, papszVectorTranslateArguments, nullptr))
     102             :     {
     103           0 :         return nullptr;
     104             :     }
     105             : 
     106           2 :     if (!OGRPMTilesConvertFromMBTiles(pszDestName,
     107           2 :                                       poSourceDS->GetDescription()))
     108             :     {
     109           0 :         return nullptr;
     110             :     }
     111             : 
     112           4 :     GDALOpenInfo oOpenInfo(pszDestName, GA_ReadOnly);
     113           2 :     return OGRPMTilesDriverOpen(&oOpenInfo);
     114             : }
     115             : 
     116             : #ifdef HAVE_MVT_WRITE_SUPPORT
     117             : /************************************************************************/
     118             : /*                                Create()                              */
     119             : /************************************************************************/
     120             : 
     121          34 : static GDALDataset *OGRPMTilesDriverCreate(const char *pszFilename, int nXSize,
     122             :                                            int nYSize, int nBandsIn,
     123             :                                            GDALDataType eDT,
     124             :                                            char **papszOptions)
     125             : {
     126          34 :     if (nXSize == 0 && nYSize == 0 && nBandsIn == 0 && eDT == GDT_Unknown)
     127             :     {
     128          68 :         auto poDS = std::make_unique<OGRPMTilesWriterDataset>();
     129          34 :         if (!poDS->Create(pszFilename, papszOptions))
     130           1 :             return nullptr;
     131          33 :         return poDS.release();
     132             :     }
     133           0 :     return nullptr;
     134             : }
     135             : #endif
     136             : 
     137             : /************************************************************************/
     138             : /*                          RegisterOGRPMTiles()                        */
     139             : /************************************************************************/
     140             : 
     141        1595 : void RegisterOGRPMTiles()
     142             : {
     143        1595 :     if (GDALGetDriverByName("PMTiles") != nullptr)
     144         302 :         return;
     145             : 
     146        1293 :     VSIPMTilesRegister();
     147             : 
     148        1293 :     GDALDriver *poDriver = new GDALDriver();
     149             : 
     150        1293 :     poDriver->SetDescription("PMTiles");
     151        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     152        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ProtoMap Tiles");
     153        1293 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "pmtiles");
     154        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
     155        1293 :                               "drivers/vector/pmtiles.html");
     156             : 
     157        1293 :     poDriver->SetMetadataItem(
     158             :         GDAL_DMD_OPENOPTIONLIST,
     159             :         "<OpenOptionList>"
     160             :         "  <Option name='ZOOM_LEVEL' type='integer' "
     161             :         "description='Zoom level of full resolution. If not specified, maximum "
     162             :         "non-empty zoom level'/>"
     163             :         "  <Option name='CLIP' type='boolean' "
     164             :         "description='Whether to clip geometries to tile extent' "
     165             :         "default='YES'/>"
     166             :         "  <Option name='ZOOM_LEVEL_AUTO' type='boolean' "
     167             :         "description='Whether to auto-select the zoom level for vector layers "
     168             :         "according to spatial filter extent. Only for display purpose' "
     169             :         "default='NO'/>"
     170             :         "  <Option name='JSON_FIELD' type='boolean' "
     171             :         "description='For vector layers, "
     172             :         "whether to put all attributes as a serialized JSon dictionary'/>"
     173        1293 :         "</OpenOptionList>");
     174             : 
     175        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     176             : 
     177        1293 :     poDriver->pfnOpen = OGRPMTilesDriverOpen;
     178        1293 :     poDriver->pfnIdentify = OGRPMTilesDriverIdentify;
     179        1293 :     poDriver->pfnCanVectorTranslateFrom =
     180             :         OGRPMTilesDriverCanVectorTranslateFrom;
     181        1293 :     poDriver->pfnVectorTranslateFrom = OGRPMTilesDriverVectorTranslateFrom;
     182             : 
     183             : #ifdef HAVE_MVT_WRITE_SUPPORT
     184        1293 :     poDriver->SetMetadataItem(
     185             :         GDAL_DMD_CREATIONOPTIONLIST,
     186             :         "<CreationOptionList>"
     187             :         "  <Option name='NAME' scope='raster,vector' type='string' "
     188             :         "description='Tileset name'/>"
     189             :         "  <Option name='DESCRIPTION' scope='raster,vector' type='string' "
     190             :         "description='A description of the layer'/>"
     191             :         "  <Option name='TYPE' scope='raster,vector' type='string-select' "
     192             :         "description='Layer type' default='overlay'>"
     193             :         "    <Value>overlay</Value>"
     194             :         "    <Value>baselayer</Value>"
     195        1293 :         "  </Option>" MVT_MBTILES_PMTILES_COMMON_DSCO "</CreationOptionList>");
     196             : 
     197        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
     198        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
     199        1293 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
     200        1293 :                               "Integer Integer64 Real String");
     201        1293 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATASUBTYPES,
     202        1293 :                               "Boolean Float32");
     203             : 
     204        1293 :     poDriver->SetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST, MVT_LCO);
     205             : 
     206        1293 :     poDriver->pfnCreate = OGRPMTilesDriverCreate;
     207             : #endif
     208             : 
     209        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     210             : }

Generated by: LCOV version 1.14