LCOV - code coverage report
Current view: top level - frmts/sdts - sdtsdataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 93 121 76.9 %
Date: 2024-11-21 22:18:42 Functions: 9 11 81.8 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SDTS Translator
       4             :  * Purpose:  GDALDataset driver for SDTS Raster translator.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  * Copyright (c) 2008-2011, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "gdal_frmts.h"
      15             : #include "gdal_pam.h"
      16             : #include "ogr_spatialref.h"
      17             : #include "sdts_al.h"
      18             : 
      19             : /**
      20             :  \file sdtsdataset.cpp
      21             : 
      22             :  exclude
      23             : */
      24             : 
      25             : /************************************************************************/
      26             : /* ==================================================================== */
      27             : /*                              SDTSDataset                             */
      28             : /* ==================================================================== */
      29             : /************************************************************************/
      30             : 
      31             : class SDTSRasterBand;
      32             : 
      33             : class SDTSDataset final : public GDALPamDataset
      34             : {
      35             :     friend class SDTSRasterBand;
      36             : 
      37             :     SDTSTransfer *poTransfer;
      38             :     SDTSRasterReader *poRL;
      39             : 
      40             :     OGRSpatialReference m_oSRS{};
      41             : 
      42             :   public:
      43             :     SDTSDataset();
      44             :     virtual ~SDTSDataset();
      45             : 
      46             :     static GDALDataset *Open(GDALOpenInfo *);
      47             : 
      48           1 :     const OGRSpatialReference *GetSpatialRef() const override
      49             :     {
      50           1 :         return &m_oSRS;
      51             :     }
      52             : 
      53             :     virtual CPLErr GetGeoTransform(double *) override;
      54             : };
      55             : 
      56             : class SDTSRasterBand final : public GDALPamRasterBand
      57             : {
      58             :     friend class SDTSDataset;
      59             : 
      60             :     SDTSRasterReader *poRL;
      61             : 
      62             :   public:
      63             :     SDTSRasterBand(SDTSDataset *, int, SDTSRasterReader *);
      64             : 
      65             :     virtual CPLErr IReadBlock(int, int, void *) override;
      66             : 
      67             :     virtual double GetNoDataValue(int *pbSuccess) override;
      68             :     virtual const char *GetUnitType() override;
      69             : };
      70             : 
      71             : /************************************************************************/
      72             : /*                             SDTSDataset()                            */
      73             : /************************************************************************/
      74             : 
      75           2 : SDTSDataset::SDTSDataset() : poTransfer(nullptr), poRL(nullptr)
      76             : {
      77           2 :     m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
      78           2 : }
      79             : 
      80             : /************************************************************************/
      81             : /*                            ~SDTSDataset()                            */
      82             : /************************************************************************/
      83             : 
      84           4 : SDTSDataset::~SDTSDataset()
      85             : 
      86             : {
      87           2 :     FlushCache(true);
      88             : 
      89           2 :     if (poTransfer != nullptr)
      90           2 :         delete poTransfer;
      91             : 
      92           2 :     if (poRL != nullptr)
      93           2 :         delete poRL;
      94           4 : }
      95             : 
      96             : /************************************************************************/
      97             : /*                                Open()                                */
      98             : /************************************************************************/
      99             : 
     100       35652 : GDALDataset *SDTSDataset::Open(GDALOpenInfo *poOpenInfo)
     101             : 
     102             : {
     103             :     /* -------------------------------------------------------------------- */
     104             :     /*      Before trying SDTSOpen() we first verify that the first         */
     105             :     /*      record is in fact a SDTS file descriptor record.                */
     106             :     /* -------------------------------------------------------------------- */
     107       35652 :     if (poOpenInfo->nHeaderBytes < 24)
     108       28644 :         return nullptr;
     109             : 
     110        7008 :     char *pachLeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
     111        7008 :     if (pachLeader[5] != '1' && pachLeader[5] != '2' && pachLeader[5] != '3')
     112        6653 :         return nullptr;
     113             : 
     114         355 :     if (pachLeader[6] != 'L')
     115         303 :         return nullptr;
     116             : 
     117          52 :     if (pachLeader[8] != '1' && pachLeader[8] != ' ')
     118           0 :         return nullptr;
     119             : 
     120             :     /* -------------------------------------------------------------------- */
     121             :     /*      Try opening the dataset.                                        */
     122             :     /* -------------------------------------------------------------------- */
     123          52 :     SDTSTransfer *poTransfer = new SDTSTransfer;
     124             : 
     125          51 :     if (!poTransfer->Open(poOpenInfo->pszFilename))
     126             :     {
     127          49 :         delete poTransfer;
     128          49 :         return nullptr;
     129             :     }
     130             : 
     131             :     /* -------------------------------------------------------------------- */
     132             :     /*      Confirm the requested access is supported.                      */
     133             :     /* -------------------------------------------------------------------- */
     134           2 :     if (poOpenInfo->eAccess == GA_Update)
     135             :     {
     136           0 :         delete poTransfer;
     137           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     138             :                  "The SDTS driver does not support update access to existing"
     139             :                  " datasets.\n");
     140           0 :         return nullptr;
     141             :     }
     142             : 
     143             :     /* -------------------------------------------------------------------- */
     144             :     /*      Find the first raster layer.  If there are none, abort          */
     145             :     /*      returning an error.                                             */
     146             :     /* -------------------------------------------------------------------- */
     147           2 :     SDTSRasterReader *poRL = nullptr;
     148             : 
     149           2 :     for (int i = 0; i < poTransfer->GetLayerCount(); i++)
     150             :     {
     151           2 :         if (poTransfer->GetLayerType(i) == SLTRaster)
     152             :         {
     153           2 :             poRL = poTransfer->GetLayerRasterReader(i);
     154           2 :             break;
     155             :         }
     156             :     }
     157             : 
     158           2 :     if (poRL == nullptr)
     159             :     {
     160           0 :         delete poTransfer;
     161             : 
     162           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     163             :                  "%s is an SDTS transfer, but has no raster cell layers.\n"
     164             :                  "Perhaps it is a vector transfer?\n",
     165             :                  poOpenInfo->pszFilename);
     166           0 :         return nullptr;
     167             :     }
     168             : 
     169             :     /* -------------------------------------------------------------------- */
     170             :     /*      Initialize a corresponding GDALDataset.                         */
     171             :     /* -------------------------------------------------------------------- */
     172           2 :     SDTSDataset *poDS = new SDTSDataset();
     173             : 
     174           2 :     poDS->poTransfer = poTransfer;
     175           2 :     poDS->poRL = poRL;
     176             : 
     177             :     /* -------------------------------------------------------------------- */
     178             :     /*      Capture some information from the file that is of interest.     */
     179             :     /* -------------------------------------------------------------------- */
     180           2 :     poDS->nRasterXSize = poRL->GetXSize();
     181           2 :     poDS->nRasterYSize = poRL->GetYSize();
     182             : 
     183             :     /* -------------------------------------------------------------------- */
     184             :     /*      Create band information objects.                                */
     185             :     /* -------------------------------------------------------------------- */
     186           2 :     poDS->nBands = 1;
     187           2 :     poDS->papoBands = reinterpret_cast<GDALRasterBand **>(
     188           2 :         VSICalloc(sizeof(GDALRasterBand *), poDS->nBands));
     189             : 
     190           4 :     for (int i = 0; i < poDS->nBands; i++)
     191           2 :         poDS->SetBand(i + 1, new SDTSRasterBand(poDS, i + 1, poRL));
     192             : 
     193             :     /* -------------------------------------------------------------------- */
     194             :     /*      Try to establish the projection string.  For now we only        */
     195             :     /*      support UTM and GEO.                                            */
     196             :     /* -------------------------------------------------------------------- */
     197           2 :     SDTS_XREF *poXREF = poTransfer->GetXREF();
     198             : 
     199           2 :     if (EQUAL(poXREF->pszSystemName, "UTM"))
     200             :     {
     201           2 :         poDS->m_oSRS.SetUTM(poXREF->nZone);
     202             :     }
     203           0 :     else if (EQUAL(poXREF->pszSystemName, "GEO"))
     204             :     {
     205             :         /* we set datum later */
     206             :     }
     207             :     else
     208           0 :         poDS->m_oSRS.SetLocalCS(poXREF->pszSystemName);
     209             : 
     210           2 :     if (poDS->m_oSRS.IsLocal())
     211             :         /* don't try to set datum. */;
     212           2 :     else if (EQUAL(poXREF->pszDatum, "NAS"))
     213           2 :         poDS->m_oSRS.SetWellKnownGeogCS("NAD27");
     214           0 :     else if (EQUAL(poXREF->pszDatum, "NAX"))
     215           0 :         poDS->m_oSRS.SetWellKnownGeogCS("NAD83");
     216           0 :     else if (EQUAL(poXREF->pszDatum, "WGC"))
     217           0 :         poDS->m_oSRS.SetWellKnownGeogCS("WGS72");
     218             :     else /* if( EQUAL(poXREF->pszDatum, "WGE") ) or default */
     219           0 :         poDS->m_oSRS.SetWellKnownGeogCS("WGS84");
     220             : 
     221             :     /* -------------------------------------------------------------------- */
     222             :     /*      Get metadata from the IDEN file.                                */
     223             :     /* -------------------------------------------------------------------- */
     224             :     const char *pszIDENFilePath =
     225           2 :         poTransfer->GetCATD()->GetModuleFilePath("IDEN");
     226           2 :     if (pszIDENFilePath)
     227             :     {
     228           4 :         DDFModule oIDENFile;
     229           2 :         if (oIDENFile.Open(pszIDENFilePath))
     230             :         {
     231           2 :             DDFRecord *poRecord = nullptr;
     232             : 
     233           2 :             while ((poRecord = oIDENFile.ReadRecord()) != nullptr)
     234             :             {
     235             : 
     236           2 :                 if (poRecord->GetStringSubfield("IDEN", 0, "MODN", 0) ==
     237             :                     nullptr)
     238           0 :                     continue;
     239             : 
     240             :                 static const char *const fields[][2] = {
     241             :                     {"TITL", "TITLE"},
     242             :                     {"DAID", "DATASET_ID"},
     243             :                     {"DAST", "DATA_STRUCTURE"},
     244             :                     {"MPDT", "MAP_DATE"},
     245             :                     {"DCDT", "DATASET_CREATION_DATE"}};
     246             : 
     247          12 :                 for (int i = 0; i < static_cast<int>(sizeof(fields)) /
     248             :                                         static_cast<int>(sizeof(fields[0]));
     249             :                      i++)
     250             :                 {
     251             :                     const char *pszFieldValue =
     252          10 :                         poRecord->GetStringSubfield("IDEN", 0, fields[i][0], 0);
     253          10 :                     if (pszFieldValue)
     254          10 :                         poDS->SetMetadataItem(fields[i][1], pszFieldValue);
     255             :                 }
     256             : 
     257           2 :                 break;
     258             :             }
     259             :         }
     260             :     }
     261             : 
     262             :     /* -------------------------------------------------------------------- */
     263             :     /*      Initialize any PAM information.                                 */
     264             :     /* -------------------------------------------------------------------- */
     265           2 :     poDS->SetDescription(poOpenInfo->pszFilename);
     266           2 :     poDS->TryLoadXML();
     267             : 
     268             :     /* -------------------------------------------------------------------- */
     269             :     /*      Check for external overviews.                                   */
     270             :     /* -------------------------------------------------------------------- */
     271           4 :     poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename,
     272           2 :                                 poOpenInfo->GetSiblingFiles());
     273             : 
     274           2 :     return poDS;
     275             : }
     276             : 
     277             : /************************************************************************/
     278             : /*                          GetGeoTransform()                           */
     279             : /************************************************************************/
     280             : 
     281           1 : CPLErr SDTSDataset::GetGeoTransform(double *padfTransform)
     282             : 
     283             : {
     284           1 :     if (poRL->GetTransform(padfTransform))
     285           1 :         return CE_None;
     286             : 
     287           0 :     return CE_Failure;
     288             : }
     289             : 
     290             : /************************************************************************/
     291             : /* ==================================================================== */
     292             : /*                            SDTSRasterBand                             */
     293             : /* ==================================================================== */
     294             : /************************************************************************/
     295             : 
     296             : /************************************************************************/
     297             : /*                           SDTSRasterBand()                            */
     298             : /************************************************************************/
     299             : 
     300           2 : SDTSRasterBand::SDTSRasterBand(SDTSDataset *poDSIn, int nBandIn,
     301           2 :                                SDTSRasterReader *poRLIn)
     302           2 :     : poRL(poRLIn)
     303             : {
     304           2 :     poDS = poDSIn;
     305           2 :     nBand = nBandIn;
     306             : 
     307           2 :     if (poRL->GetRasterType() == SDTS_RT_INT16)
     308           2 :         eDataType = GDT_Int16;
     309             :     else
     310           0 :         eDataType = GDT_Float32;
     311             : 
     312           2 :     nBlockXSize = poRL->GetBlockXSize();
     313           2 :     nBlockYSize = poRL->GetBlockYSize();
     314           2 : }
     315             : 
     316             : /************************************************************************/
     317             : /*                             IReadBlock()                             */
     318             : /************************************************************************/
     319             : 
     320          25 : CPLErr SDTSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
     321             : 
     322             : {
     323          25 :     if (poRL->GetBlock(nBlockXOff, nBlockYOff, pImage))
     324          25 :         return CE_None;
     325             : 
     326           0 :     return CE_Failure;
     327             : }
     328             : 
     329             : /************************************************************************/
     330             : /*                           GetNoDataValue()                           */
     331             : /************************************************************************/
     332             : 
     333           0 : double SDTSRasterBand::GetNoDataValue(int *pbSuccess)
     334             : 
     335             : {
     336           0 :     if (pbSuccess != nullptr)
     337           0 :         *pbSuccess = TRUE;
     338             : 
     339           0 :     return -32766.0;
     340             : }
     341             : 
     342             : /************************************************************************/
     343             : /*                            GetUnitType()                             */
     344             : /************************************************************************/
     345             : 
     346           0 : const char *SDTSRasterBand::GetUnitType()
     347             : 
     348             : {
     349           0 :     if (EQUAL(poRL->szUNITS, "FEET"))
     350           0 :         return "ft";
     351           0 :     else if (STARTS_WITH_CI(poRL->szUNITS, "MET"))
     352           0 :         return "m";
     353             : 
     354           0 :     return poRL->szUNITS;
     355             : }
     356             : 
     357             : /************************************************************************/
     358             : /*                         GDALRegister_SDTS()                          */
     359             : /************************************************************************/
     360             : 
     361        1595 : void GDALRegister_SDTS()
     362             : 
     363             : {
     364        1595 :     if (GDALGetDriverByName("SDTS") != nullptr)
     365         302 :         return;
     366             : 
     367        1293 :     GDALDriver *poDriver = new GDALDriver();
     368             : 
     369        1293 :     poDriver->SetDescription("SDTS");
     370        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     371        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "SDTS Raster");
     372        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/sdts.html");
     373        1293 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "ddf");
     374        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     375             : 
     376        1293 :     poDriver->pfnOpen = SDTSDataset::Open;
     377             : 
     378        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     379             : }

Generated by: LCOV version 1.14