LCOV - code coverage report
Current view: top level - frmts/sdts - sdtsdataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 92 120 76.7 %
Date: 2024-05-04 12:52:34 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "gdal_frmts.h"
      31             : #include "gdal_pam.h"
      32             : #include "ogr_spatialref.h"
      33             : #include "sdts_al.h"
      34             : 
      35             : /**
      36             :  \file sdtsdataset.cpp
      37             : 
      38             :  exclude
      39             : */
      40             : 
      41             : /************************************************************************/
      42             : /* ==================================================================== */
      43             : /*                              SDTSDataset                             */
      44             : /* ==================================================================== */
      45             : /************************************************************************/
      46             : 
      47             : class SDTSRasterBand;
      48             : 
      49             : class SDTSDataset final : public GDALPamDataset
      50             : {
      51             :     friend class SDTSRasterBand;
      52             : 
      53             :     SDTSTransfer *poTransfer;
      54             :     SDTSRasterReader *poRL;
      55             : 
      56             :     OGRSpatialReference m_oSRS{};
      57             : 
      58             :   public:
      59             :     SDTSDataset();
      60             :     virtual ~SDTSDataset();
      61             : 
      62             :     static GDALDataset *Open(GDALOpenInfo *);
      63             : 
      64           1 :     const OGRSpatialReference *GetSpatialRef() const override
      65             :     {
      66           1 :         return &m_oSRS;
      67             :     }
      68             : 
      69             :     virtual CPLErr GetGeoTransform(double *) override;
      70             : };
      71             : 
      72             : class SDTSRasterBand final : public GDALPamRasterBand
      73             : {
      74             :     friend class SDTSDataset;
      75             : 
      76             :     SDTSRasterReader *poRL;
      77             : 
      78             :   public:
      79             :     SDTSRasterBand(SDTSDataset *, int, SDTSRasterReader *);
      80             : 
      81             :     virtual CPLErr IReadBlock(int, int, void *) override;
      82             : 
      83             :     virtual double GetNoDataValue(int *pbSuccess) override;
      84             :     virtual const char *GetUnitType() override;
      85             : };
      86             : 
      87             : /************************************************************************/
      88             : /*                             SDTSDataset()                            */
      89             : /************************************************************************/
      90             : 
      91           2 : SDTSDataset::SDTSDataset() : poTransfer(nullptr), poRL(nullptr)
      92             : {
      93           2 :     m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
      94           2 : }
      95             : 
      96             : /************************************************************************/
      97             : /*                            ~SDTSDataset()                            */
      98             : /************************************************************************/
      99             : 
     100           4 : SDTSDataset::~SDTSDataset()
     101             : 
     102             : {
     103           2 :     FlushCache(true);
     104             : 
     105           2 :     if (poTransfer != nullptr)
     106           2 :         delete poTransfer;
     107             : 
     108           2 :     if (poRL != nullptr)
     109           2 :         delete poRL;
     110           4 : }
     111             : 
     112             : /************************************************************************/
     113             : /*                                Open()                                */
     114             : /************************************************************************/
     115             : 
     116       33849 : GDALDataset *SDTSDataset::Open(GDALOpenInfo *poOpenInfo)
     117             : 
     118             : {
     119             :     /* -------------------------------------------------------------------- */
     120             :     /*      Before trying SDTSOpen() we first verify that the first         */
     121             :     /*      record is in fact a SDTS file descriptor record.                */
     122             :     /* -------------------------------------------------------------------- */
     123       33849 :     if (poOpenInfo->nHeaderBytes < 24)
     124       27264 :         return nullptr;
     125             : 
     126        6585 :     char *pachLeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
     127        6585 :     if (pachLeader[5] != '1' && pachLeader[5] != '2' && pachLeader[5] != '3')
     128        6233 :         return nullptr;
     129             : 
     130         352 :     if (pachLeader[6] != 'L')
     131         301 :         return nullptr;
     132             : 
     133          51 :     if (pachLeader[8] != '1' && pachLeader[8] != ' ')
     134           0 :         return nullptr;
     135             : 
     136             :     /* -------------------------------------------------------------------- */
     137             :     /*      Try opening the dataset.                                        */
     138             :     /* -------------------------------------------------------------------- */
     139          51 :     SDTSTransfer *poTransfer = new SDTSTransfer;
     140             : 
     141          51 :     if (!poTransfer->Open(poOpenInfo->pszFilename))
     142             :     {
     143          49 :         delete poTransfer;
     144          49 :         return nullptr;
     145             :     }
     146             : 
     147             :     /* -------------------------------------------------------------------- */
     148             :     /*      Confirm the requested access is supported.                      */
     149             :     /* -------------------------------------------------------------------- */
     150           2 :     if (poOpenInfo->eAccess == GA_Update)
     151             :     {
     152           0 :         delete poTransfer;
     153           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     154             :                  "The SDTS driver does not support update access to existing"
     155             :                  " datasets.\n");
     156           0 :         return nullptr;
     157             :     }
     158             : 
     159             :     /* -------------------------------------------------------------------- */
     160             :     /*      Find the first raster layer.  If there are none, abort          */
     161             :     /*      returning an error.                                             */
     162             :     /* -------------------------------------------------------------------- */
     163           2 :     SDTSRasterReader *poRL = nullptr;
     164             : 
     165           2 :     for (int i = 0; i < poTransfer->GetLayerCount(); i++)
     166             :     {
     167           2 :         if (poTransfer->GetLayerType(i) == SLTRaster)
     168             :         {
     169           2 :             poRL = poTransfer->GetLayerRasterReader(i);
     170           2 :             break;
     171             :         }
     172             :     }
     173             : 
     174           2 :     if (poRL == nullptr)
     175             :     {
     176           0 :         delete poTransfer;
     177             : 
     178           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     179             :                  "%s is an SDTS transfer, but has no raster cell layers.\n"
     180             :                  "Perhaps it is a vector transfer?\n",
     181             :                  poOpenInfo->pszFilename);
     182           0 :         return nullptr;
     183             :     }
     184             : 
     185             :     /* -------------------------------------------------------------------- */
     186             :     /*      Initialize a corresponding GDALDataset.                         */
     187             :     /* -------------------------------------------------------------------- */
     188           2 :     SDTSDataset *poDS = new SDTSDataset();
     189             : 
     190           2 :     poDS->poTransfer = poTransfer;
     191           2 :     poDS->poRL = poRL;
     192             : 
     193             :     /* -------------------------------------------------------------------- */
     194             :     /*      Capture some information from the file that is of interest.     */
     195             :     /* -------------------------------------------------------------------- */
     196           2 :     poDS->nRasterXSize = poRL->GetXSize();
     197           2 :     poDS->nRasterYSize = poRL->GetYSize();
     198             : 
     199             :     /* -------------------------------------------------------------------- */
     200             :     /*      Create band information objects.                                */
     201             :     /* -------------------------------------------------------------------- */
     202           2 :     poDS->nBands = 1;
     203           2 :     poDS->papoBands = reinterpret_cast<GDALRasterBand **>(
     204           2 :         VSICalloc(sizeof(GDALRasterBand *), poDS->nBands));
     205             : 
     206           4 :     for (int i = 0; i < poDS->nBands; i++)
     207           2 :         poDS->SetBand(i + 1, new SDTSRasterBand(poDS, i + 1, poRL));
     208             : 
     209             :     /* -------------------------------------------------------------------- */
     210             :     /*      Try to establish the projection string.  For now we only        */
     211             :     /*      support UTM and GEO.                                            */
     212             :     /* -------------------------------------------------------------------- */
     213           2 :     SDTS_XREF *poXREF = poTransfer->GetXREF();
     214             : 
     215           2 :     if (EQUAL(poXREF->pszSystemName, "UTM"))
     216             :     {
     217           2 :         poDS->m_oSRS.SetUTM(poXREF->nZone);
     218             :     }
     219           0 :     else if (EQUAL(poXREF->pszSystemName, "GEO"))
     220             :     {
     221             :         /* we set datum later */
     222             :     }
     223             :     else
     224           0 :         poDS->m_oSRS.SetLocalCS(poXREF->pszSystemName);
     225             : 
     226           2 :     if (poDS->m_oSRS.IsLocal())
     227             :         /* don't try to set datum. */;
     228           2 :     else if (EQUAL(poXREF->pszDatum, "NAS"))
     229           2 :         poDS->m_oSRS.SetWellKnownGeogCS("NAD27");
     230           0 :     else if (EQUAL(poXREF->pszDatum, "NAX"))
     231           0 :         poDS->m_oSRS.SetWellKnownGeogCS("NAD83");
     232           0 :     else if (EQUAL(poXREF->pszDatum, "WGC"))
     233           0 :         poDS->m_oSRS.SetWellKnownGeogCS("WGS72");
     234             :     else /* if( EQUAL(poXREF->pszDatum, "WGE") ) or default */
     235           0 :         poDS->m_oSRS.SetWellKnownGeogCS("WGS84");
     236             : 
     237             :     /* -------------------------------------------------------------------- */
     238             :     /*      Get metadata from the IDEN file.                                */
     239             :     /* -------------------------------------------------------------------- */
     240             :     const char *pszIDENFilePath =
     241           2 :         poTransfer->GetCATD()->GetModuleFilePath("IDEN");
     242           2 :     if (pszIDENFilePath)
     243             :     {
     244           4 :         DDFModule oIDENFile;
     245           2 :         if (oIDENFile.Open(pszIDENFilePath))
     246             :         {
     247           2 :             DDFRecord *poRecord = nullptr;
     248             : 
     249           2 :             while ((poRecord = oIDENFile.ReadRecord()) != nullptr)
     250             :             {
     251             : 
     252           2 :                 if (poRecord->GetStringSubfield("IDEN", 0, "MODN", 0) ==
     253             :                     nullptr)
     254           0 :                     continue;
     255             : 
     256             :                 static const char *const fields[][2] = {
     257             :                     {"TITL", "TITLE"},
     258             :                     {"DAID", "DATASET_ID"},
     259             :                     {"DAST", "DATA_STRUCTURE"},
     260             :                     {"MPDT", "MAP_DATE"},
     261             :                     {"DCDT", "DATASET_CREATION_DATE"}};
     262             : 
     263          12 :                 for (int i = 0; i < static_cast<int>(sizeof(fields)) /
     264             :                                         static_cast<int>(sizeof(fields[0]));
     265             :                      i++)
     266             :                 {
     267             :                     const char *pszFieldValue =
     268          10 :                         poRecord->GetStringSubfield("IDEN", 0, fields[i][0], 0);
     269          10 :                     if (pszFieldValue)
     270          10 :                         poDS->SetMetadataItem(fields[i][1], pszFieldValue);
     271             :                 }
     272             : 
     273           2 :                 break;
     274             :             }
     275             :         }
     276             :     }
     277             : 
     278             :     /* -------------------------------------------------------------------- */
     279             :     /*      Initialize any PAM information.                                 */
     280             :     /* -------------------------------------------------------------------- */
     281           2 :     poDS->SetDescription(poOpenInfo->pszFilename);
     282           2 :     poDS->TryLoadXML();
     283             : 
     284             :     /* -------------------------------------------------------------------- */
     285             :     /*      Check for external overviews.                                   */
     286             :     /* -------------------------------------------------------------------- */
     287           2 :     poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename,
     288             :                                 poOpenInfo->GetSiblingFiles());
     289             : 
     290           2 :     return poDS;
     291             : }
     292             : 
     293             : /************************************************************************/
     294             : /*                          GetGeoTransform()                           */
     295             : /************************************************************************/
     296             : 
     297           1 : CPLErr SDTSDataset::GetGeoTransform(double *padfTransform)
     298             : 
     299             : {
     300           1 :     if (poRL->GetTransform(padfTransform))
     301           1 :         return CE_None;
     302             : 
     303           0 :     return CE_Failure;
     304             : }
     305             : 
     306             : /************************************************************************/
     307             : /* ==================================================================== */
     308             : /*                            SDTSRasterBand                             */
     309             : /* ==================================================================== */
     310             : /************************************************************************/
     311             : 
     312             : /************************************************************************/
     313             : /*                           SDTSRasterBand()                            */
     314             : /************************************************************************/
     315             : 
     316           2 : SDTSRasterBand::SDTSRasterBand(SDTSDataset *poDSIn, int nBandIn,
     317           2 :                                SDTSRasterReader *poRLIn)
     318           2 :     : poRL(poRLIn)
     319             : {
     320           2 :     poDS = poDSIn;
     321           2 :     nBand = nBandIn;
     322             : 
     323           2 :     if (poRL->GetRasterType() == SDTS_RT_INT16)
     324           2 :         eDataType = GDT_Int16;
     325             :     else
     326           0 :         eDataType = GDT_Float32;
     327             : 
     328           2 :     nBlockXSize = poRL->GetBlockXSize();
     329           2 :     nBlockYSize = poRL->GetBlockYSize();
     330           2 : }
     331             : 
     332             : /************************************************************************/
     333             : /*                             IReadBlock()                             */
     334             : /************************************************************************/
     335             : 
     336          25 : CPLErr SDTSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
     337             : 
     338             : {
     339          25 :     if (poRL->GetBlock(nBlockXOff, nBlockYOff, pImage))
     340          25 :         return CE_None;
     341             : 
     342           0 :     return CE_Failure;
     343             : }
     344             : 
     345             : /************************************************************************/
     346             : /*                           GetNoDataValue()                           */
     347             : /************************************************************************/
     348             : 
     349           0 : double SDTSRasterBand::GetNoDataValue(int *pbSuccess)
     350             : 
     351             : {
     352           0 :     if (pbSuccess != nullptr)
     353           0 :         *pbSuccess = TRUE;
     354             : 
     355           0 :     return -32766.0;
     356             : }
     357             : 
     358             : /************************************************************************/
     359             : /*                            GetUnitType()                             */
     360             : /************************************************************************/
     361             : 
     362           0 : const char *SDTSRasterBand::GetUnitType()
     363             : 
     364             : {
     365           0 :     if (EQUAL(poRL->szUNITS, "FEET"))
     366           0 :         return "ft";
     367           0 :     else if (STARTS_WITH_CI(poRL->szUNITS, "MET"))
     368           0 :         return "m";
     369             : 
     370           0 :     return poRL->szUNITS;
     371             : }
     372             : 
     373             : /************************************************************************/
     374             : /*                         GDALRegister_SDTS()                          */
     375             : /************************************************************************/
     376             : 
     377        1520 : void GDALRegister_SDTS()
     378             : 
     379             : {
     380        1520 :     if (GDALGetDriverByName("SDTS") != nullptr)
     381         301 :         return;
     382             : 
     383        1219 :     GDALDriver *poDriver = new GDALDriver();
     384             : 
     385        1219 :     poDriver->SetDescription("SDTS");
     386        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     387        1219 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "SDTS Raster");
     388        1219 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/sdts.html");
     389        1219 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "ddf");
     390        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     391             : 
     392        1219 :     poDriver->pfnOpen = SDTSDataset::Open;
     393             : 
     394        1219 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     395             : }

Generated by: LCOV version 1.14