LCOV - code coverage report
Current view: top level - frmts/raw - ace2dataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 87 136 64.0 %
Date: 2024-05-04 12:52:34 Functions: 7 9 77.8 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  ACE2 Driver
       4             :  * Purpose:  Implementation of ACE2 elevation format read support.
       5             :  *           http://tethys.eaprs.cse.dmu.ac.uk/ACE2/shared/documentation
       6             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2011-2012, 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 "ogr_spatialref.h"
      32             : #include "rawdataset.h"
      33             : 
      34             : static const char *const apszCategorySource[] = {
      35             :     "Pure SRTM (above 60deg N pure GLOBE data, below 60S pure ACE [original] "
      36             :     "data)",
      37             :     "SRTM voids filled by interpolation and/or altimeter data",
      38             :     "SRTM data warped using the ERS-1 Geodetic Mission",
      39             :     "SRTM data warped using EnviSat & ERS-2 data",
      40             :     "Mean lake level data derived from Altimetry",
      41             :     "GLOBE/ACE data warped using combined altimetry (only above 60deg N)",
      42             :     "Pure altimetry data (derived from ERS-1 Geodetic Mission, ERS-2 and "
      43             :     "EnviSat data using Delaunay Triangulation",
      44             :     nullptr};
      45             : 
      46             : static const char *const apszCategoryQuality[] = {
      47             :     "Generic - use base datasets",
      48             :     "Accuracy of greater than +/- 16m",
      49             :     "Accuracy between +/- 16m - +/- 10m",
      50             :     "Accuracy between +/-10m - +/-5m",
      51             :     "Accuracy between +/-5m - +/-1m",
      52             :     "Accuracy between +/-1m",
      53             :     nullptr};
      54             : 
      55             : static const char *const apszCategoryConfidence[] = {
      56             :     "No confidence could be derived due to lack of data",
      57             :     "Heights generated by interpolation",
      58             :     "Low confidence",
      59             :     "Low confidence",
      60             :     "Low confidence",
      61             :     "Medium confidence",
      62             :     "Medium confidence",
      63             :     "Medium confidence",
      64             :     "Medium confidence",
      65             :     "Medium confidence",
      66             :     "Medium confidence",
      67             :     "Medium confidence",
      68             :     "Medium confidence",
      69             :     "High confidence",
      70             :     "High confidence",
      71             :     "High confidence",
      72             :     "High confidence",
      73             :     "Inland water confidence",
      74             :     "Inland water confidence",
      75             :     "Inland water confidence",
      76             :     "Inland water confidence",
      77             :     "Inland water confidence",
      78             :     nullptr};
      79             : 
      80             : /************************************************************************/
      81             : /* ==================================================================== */
      82             : /*                             ACE2Dataset                              */
      83             : /* ==================================================================== */
      84             : /************************************************************************/
      85             : 
      86             : class ACE2Dataset final : public GDALPamDataset
      87             : {
      88             :     friend class ACE2RasterBand;
      89             : 
      90             :     OGRSpatialReference m_oSRS{};
      91             :     double adfGeoTransform[6];
      92             : 
      93             :   public:
      94             :     ACE2Dataset();
      95             : 
      96           1 :     const OGRSpatialReference *GetSpatialRef() const override
      97             :     {
      98           1 :         return &m_oSRS;
      99             :     }
     100             : 
     101             :     CPLErr GetGeoTransform(double *) override;
     102             : 
     103             :     static GDALDataset *Open(GDALOpenInfo *);
     104             :     static int Identify(GDALOpenInfo *);
     105             : };
     106             : 
     107             : /************************************************************************/
     108             : /* ==================================================================== */
     109             : /*                            ACE2RasterBand                            */
     110             : /* ==================================================================== */
     111             : /************************************************************************/
     112             : 
     113             : class ACE2RasterBand final : public RawRasterBand
     114             : {
     115             :   public:
     116             :     ACE2RasterBand(VSILFILE *fpRaw, GDALDataType eDataType, int nXSize,
     117             :                    int nYSize);
     118             : 
     119             :     const char *GetUnitType() override;
     120             :     char **GetCategoryNames() override;
     121             : };
     122             : 
     123             : /************************************************************************/
     124             : /* ==================================================================== */
     125             : /*                             ACE2Dataset                              */
     126             : /* ==================================================================== */
     127             : /************************************************************************/
     128             : 
     129             : /************************************************************************/
     130             : /*                            ACE2Dataset()                             */
     131             : /************************************************************************/
     132             : 
     133           2 : ACE2Dataset::ACE2Dataset()
     134             : {
     135           2 :     m_oSRS.SetFromUserInput(SRS_WKT_WGS84_LAT_LONG);
     136           2 :     m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     137             : 
     138           2 :     adfGeoTransform[0] = 0.0;
     139           2 :     adfGeoTransform[1] = 1.0;
     140           2 :     adfGeoTransform[2] = 0.0;
     141           2 :     adfGeoTransform[3] = 0.0;
     142           2 :     adfGeoTransform[4] = 0.0;
     143           2 :     adfGeoTransform[5] = 1.0;
     144           2 : }
     145             : 
     146             : /************************************************************************/
     147             : /*                          GetGeoTransform()                           */
     148             : /************************************************************************/
     149             : 
     150           1 : CPLErr ACE2Dataset::GetGeoTransform(double *padfTransform)
     151             : 
     152             : {
     153           1 :     memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
     154           1 :     return CE_None;
     155             : }
     156             : 
     157             : /************************************************************************/
     158             : /*                          ACE2RasterBand()                            */
     159             : /************************************************************************/
     160             : 
     161           2 : ACE2RasterBand::ACE2RasterBand(VSILFILE *fpRawIn, GDALDataType eDataTypeIn,
     162           2 :                                int nXSize, int nYSize)
     163             :     : RawRasterBand(fpRawIn, 0, GDALGetDataTypeSizeBytes(eDataTypeIn),
     164           4 :                     nXSize * GDALGetDataTypeSizeBytes(eDataTypeIn), eDataTypeIn,
     165           2 :                     CPL_IS_LSB, nXSize, nYSize, RawRasterBand::OwnFP::YES)
     166             : {
     167           2 : }
     168             : 
     169             : /************************************************************************/
     170             : /*                             GetUnitType()                            */
     171             : /************************************************************************/
     172             : 
     173           0 : const char *ACE2RasterBand::GetUnitType()
     174             : {
     175           0 :     if (eDataType == GDT_Float32)
     176           0 :         return "m";
     177             : 
     178           0 :     return "";
     179             : }
     180             : 
     181             : /************************************************************************/
     182             : /*                         GetCategoryNames()                           */
     183             : /************************************************************************/
     184             : 
     185           0 : char **ACE2RasterBand::GetCategoryNames()
     186             : {
     187           0 :     if (eDataType != GDT_Int16)
     188           0 :         return nullptr;
     189             : 
     190           0 :     const char *pszName = poDS->GetDescription();
     191             : 
     192           0 :     if (strstr(pszName, "_SOURCE_"))
     193           0 :         return const_cast<char **>(apszCategorySource);
     194           0 :     if (strstr(pszName, "_QUALITY_"))
     195           0 :         return const_cast<char **>(apszCategoryQuality);
     196           0 :     if (strstr(pszName, "_CONF_"))
     197           0 :         return const_cast<char **>(apszCategoryConfidence);
     198             : 
     199           0 :     return nullptr;
     200             : }
     201             : 
     202             : /************************************************************************/
     203             : /*                             Identify()                               */
     204             : /************************************************************************/
     205             : 
     206       48738 : int ACE2Dataset::Identify(GDALOpenInfo *poOpenInfo)
     207             : 
     208             : {
     209       97472 :     if (!(EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "ACE2") ||
     210       48734 :           strstr(poOpenInfo->pszFilename, ".ACE2.gz") ||
     211       48734 :           strstr(poOpenInfo->pszFilename, ".ace2.gz")))
     212       48734 :         return FALSE;
     213             : 
     214           4 :     return TRUE;
     215             : }
     216             : 
     217             : /************************************************************************/
     218             : /*                                Open()                                */
     219             : /************************************************************************/
     220             : 
     221           2 : GDALDataset *ACE2Dataset::Open(GDALOpenInfo *poOpenInfo)
     222             : 
     223             : {
     224           2 :     if (!Identify(poOpenInfo))
     225           0 :         return nullptr;
     226             : 
     227           2 :     const char *pszBasename = CPLGetBasename(poOpenInfo->pszFilename);
     228             : 
     229           2 :     if (strlen(pszBasename) < 7)
     230           0 :         return nullptr;
     231             : 
     232             :     /* Determine southwest coordinates from filename */
     233             : 
     234             :     /* e.g. 30S120W_5M.ACE2 */
     235           2 :     char pszLatLonValueString[4] = {'\0'};
     236           2 :     memset(pszLatLonValueString, 0, 4);
     237             :     // cppcheck-suppress redundantCopy
     238           2 :     strncpy(pszLatLonValueString, &pszBasename[0], 2);
     239           2 :     int southWestLat = atoi(pszLatLonValueString);
     240           2 :     memset(pszLatLonValueString, 0, 4);
     241             :     // cppcheck-suppress redundantCopy
     242           2 :     strncpy(pszLatLonValueString, &pszBasename[3], 3);
     243           2 :     int southWestLon = atoi(pszLatLonValueString);
     244             : 
     245           2 :     if (pszBasename[2] == 'N' || pszBasename[2] == 'n')
     246             :         /*southWestLat = southWestLat*/;
     247           0 :     else if (pszBasename[2] == 'S' || pszBasename[2] == 's')
     248           0 :         southWestLat = southWestLat * -1;
     249             :     else
     250           0 :         return nullptr;
     251             : 
     252           2 :     if (pszBasename[6] == 'E' || pszBasename[6] == 'e')
     253             :         /*southWestLon = southWestLon*/;
     254           0 :     else if (pszBasename[6] == 'W' || pszBasename[6] == 'w')
     255           0 :         southWestLon = southWestLon * -1;
     256             :     else
     257           0 :         return nullptr;
     258             : 
     259           2 :     GDALDataType eDT = GDT_Unknown;
     260           2 :     if (strstr(pszBasename, "_CONF_") || strstr(pszBasename, "_QUALITY_") ||
     261           2 :         strstr(pszBasename, "_SOURCE_"))
     262           0 :         eDT = GDT_Int16;
     263             :     else
     264           2 :         eDT = GDT_Float32;
     265           2 :     int nWordSize = GDALGetDataTypeSize(eDT) / 8;
     266             : 
     267             :     VSIStatBufL sStat;
     268           2 :     if (strstr(pszBasename, "_5M"))
     269           2 :         sStat.st_size = 180 * 180 * nWordSize;
     270           0 :     else if (strstr(pszBasename, "_30S"))
     271           0 :         sStat.st_size = 1800 * 1800 * nWordSize;
     272           0 :     else if (strstr(pszBasename, "_9S"))
     273           0 :         sStat.st_size = 6000 * 6000 * nWordSize;
     274           0 :     else if (strstr(pszBasename, "_3S"))
     275           0 :         sStat.st_size = 18000 * 18000 * nWordSize;
     276             :     /* Check file size otherwise */
     277           0 :     else if (VSIStatL(poOpenInfo->pszFilename, &sStat) != 0)
     278             :     {
     279           0 :         return nullptr;
     280             :     }
     281             : 
     282           2 :     int nXSize = 0;
     283           2 :     int nYSize = 0;
     284             : 
     285           2 :     double dfPixelSize = 0;
     286           2 :     if (sStat.st_size == 180 * 180 * nWordSize)
     287             :     {
     288             :         /* 5 minute */
     289           2 :         nXSize = 180;
     290           2 :         nYSize = 180;
     291           2 :         dfPixelSize = 5.0 / 60;
     292             :     }
     293           0 :     else if (sStat.st_size == 1800 * 1800 * nWordSize)
     294             :     {
     295             :         /* 30 s */
     296           0 :         nXSize = 1800;
     297           0 :         nYSize = 1800;
     298           0 :         dfPixelSize = 30.0 / 3600;
     299             :     }
     300           0 :     else if (sStat.st_size == 6000 * 6000 * nWordSize)
     301             :     {
     302             :         /* 9 s */
     303           0 :         nXSize = 6000;
     304           0 :         nYSize = 6000;
     305           0 :         dfPixelSize = 9.0 / 3600;
     306             :     }
     307           0 :     else if (sStat.st_size == 18000 * 18000 * nWordSize)
     308             :     {
     309             :         /* 3 s */
     310           0 :         nXSize = 18000;
     311           0 :         nYSize = 18000;
     312           0 :         dfPixelSize = 3.0 / 3600;
     313             :     }
     314             :     else
     315           0 :         return nullptr;
     316             : 
     317             :     /* -------------------------------------------------------------------- */
     318             :     /*      Open file.                                                      */
     319             :     /* -------------------------------------------------------------------- */
     320             : 
     321           4 :     CPLString osFilename = poOpenInfo->pszFilename;
     322           2 :     if ((strstr(poOpenInfo->pszFilename, ".ACE2.gz") ||
     323           2 :          strstr(poOpenInfo->pszFilename, ".ace2.gz")) &&
     324           0 :         !STARTS_WITH(poOpenInfo->pszFilename, "/vsigzip/"))
     325           0 :         osFilename = "/vsigzip/" + osFilename;
     326             : 
     327           2 :     VSILFILE *fpImage = VSIFOpenL(osFilename, "rb+");
     328           2 :     if (fpImage == nullptr)
     329           0 :         return nullptr;
     330             : 
     331             :     /* -------------------------------------------------------------------- */
     332             :     /*      Create the dataset.                                             */
     333             :     /* -------------------------------------------------------------------- */
     334           4 :     auto poDS = std::make_unique<ACE2Dataset>();
     335             : 
     336           2 :     poDS->nRasterXSize = nXSize;
     337           2 :     poDS->nRasterYSize = nYSize;
     338             : 
     339           2 :     poDS->adfGeoTransform[0] = southWestLon;
     340           2 :     poDS->adfGeoTransform[1] = dfPixelSize;
     341           2 :     poDS->adfGeoTransform[2] = 0.0;
     342           2 :     poDS->adfGeoTransform[3] = southWestLat + nYSize * dfPixelSize;
     343           2 :     poDS->adfGeoTransform[4] = 0.0;
     344           2 :     poDS->adfGeoTransform[5] = -dfPixelSize;
     345             : 
     346             :     /* -------------------------------------------------------------------- */
     347             :     /*      Create band information objects                                 */
     348             :     /* -------------------------------------------------------------------- */
     349             :     auto poBand =
     350           4 :         std::make_unique<ACE2RasterBand>(fpImage, eDT, nXSize, nYSize);
     351           2 :     if (!poBand->IsValid())
     352           0 :         return nullptr;
     353           2 :     poDS->SetBand(1, std::move(poBand));
     354             : 
     355             :     /* -------------------------------------------------------------------- */
     356             :     /*      Initialize any PAM information.                                 */
     357             :     /* -------------------------------------------------------------------- */
     358           2 :     poDS->SetDescription(poOpenInfo->pszFilename);
     359           2 :     poDS->TryLoadXML();
     360             : 
     361             :     /* -------------------------------------------------------------------- */
     362             :     /*      Check for overviews.                                            */
     363             :     /* -------------------------------------------------------------------- */
     364           2 :     poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
     365             : 
     366           2 :     return poDS.release();
     367             : }
     368             : 
     369             : /************************************************************************/
     370             : /*                          GDALRegister_ACE2()                         */
     371             : /************************************************************************/
     372             : 
     373        1520 : void GDALRegister_ACE2()
     374             : 
     375             : {
     376        1520 :     if (GDALGetDriverByName("ACE2") != nullptr)
     377         301 :         return;
     378             : 
     379        1219 :     GDALDriver *poDriver = new GDALDriver();
     380             : 
     381        1219 :     poDriver->SetDescription("ACE2");
     382        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     383        1219 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ACE2");
     384        1219 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/ace2.html");
     385        1219 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "ACE2");
     386        1219 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     387             : 
     388        1219 :     poDriver->pfnOpen = ACE2Dataset::Open;
     389        1219 :     poDriver->pfnIdentify = ACE2Dataset::Identify;
     390             : 
     391        1219 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     392             : }

Generated by: LCOV version 1.14