LCOV - code coverage report
Current view: directory - frmts/usgsdem - usgsdemdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 310 276 89.0 %
Date: 2013-03-30 Functions: 23 18 78.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: usgsdemdataset.cpp 25675 2013-02-23 15:33:45Z rouault $
       3                 :  *
       4                 :  * Project:  USGS DEM Driver
       5                 :  * Purpose:  All reader for USGS DEM Reader
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  * Portions of this module derived from the VTP USGS DEM driver by Ben
       9                 :  * Discoe, see http://www.vterrain.org
      10                 :  *
      11                 :  ******************************************************************************
      12                 :  * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
      13                 :  *
      14                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      15                 :  * copy of this software and associated documentation files (the "Software"),
      16                 :  * to deal in the Software without restriction, including without limitation
      17                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18                 :  * and/or sell copies of the Software, and to permit persons to whom the
      19                 :  * Software is furnished to do so, subject to the following conditions:
      20                 :  *
      21                 :  * The above copyright notice and this permission notice shall be included
      22                 :  * in all copies or substantial portions of the Software.
      23                 :  *
      24                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      25                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      27                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30                 :  * DEALINGS IN THE SOFTWARE.
      31                 :  ****************************************************************************/
      32                 : 
      33                 : #include "gdal_pam.h"
      34                 : #include "ogr_spatialref.h"
      35                 : 
      36                 : CPL_CVSID("$Id: usgsdemdataset.cpp 25675 2013-02-23 15:33:45Z rouault $");
      37                 : 
      38                 : CPL_C_START
      39                 : void  GDALRegister_USGSDEM(void);
      40                 : CPL_C_END
      41                 : 
      42                 : typedef struct {
      43                 :     double  x;
      44                 :     double  y;
      45                 : } DPoint2;
      46                 : 
      47                 : #define USGSDEM_NODATA  -32767
      48                 : 
      49                 : GDALDataset *USGSDEMCreateCopy( const char *, GDALDataset *, int, char **,
      50                 :                                 GDALProgressFunc pfnProgress, 
      51                 :                                 void * pProgressData );
      52                 : 
      53                 : 
      54                 : /************************************************************************/
      55                 : /*                              ReadInt()                               */
      56                 : /************************************************************************/
      57                 : 
      58             240 : static int ReadInt( VSILFILE *fp )
      59                 : {
      60             240 :     int nVal = 0;
      61                 :     char c;
      62             240 :     int nRead = 0;
      63             240 :     vsi_l_offset nOffset = VSIFTellL(fp);
      64                 : 
      65            1604 :     while (TRUE)
      66                 :     {
      67            1844 :         if (VSIFReadL(&c, 1, 1, fp) != 1)
      68                 :         {
      69               0 :             return 0;
      70                 :         }
      71                 :         else
      72            1844 :             nRead ++;
      73            1844 :         if (!isspace((int)c))
      74                 :             break;
      75                 :     }
      76                 : 
      77             240 :     int nSign = 1;
      78             240 :     if (c == '-')
      79               0 :         nSign = -1;
      80             240 :     else if (c == '+')
      81               0 :         nSign = 1;
      82             479 :     else if (c >= '0' && c <= '9')
      83             239 :         nVal = c - '0';
      84                 :     else
      85                 :     {
      86               1 :         VSIFSeekL(fp, nOffset + nRead, SEEK_SET);
      87               1 :         return 0;
      88                 :     }
      89                 : 
      90              45 :     while (TRUE)
      91                 :     {
      92             284 :         if (VSIFReadL(&c, 1, 1, fp) != 1)
      93               0 :             return nSign * nVal;
      94             284 :         nRead ++;
      95             284 :         if (c >= '0' && c <= '9')
      96              45 :             nVal = nVal * 10 + (c - '0');
      97                 :         else
      98                 :         {
      99             239 :             VSIFSeekL(fp, nOffset + (nRead - 1), SEEK_SET);
     100             239 :             return nSign * nVal;
     101                 :         }
     102                 :     }
     103                 : }
     104                 : 
     105                 : typedef struct
     106                 : {
     107                 :     VSILFILE *fp;
     108                 :     int max_size;
     109                 :     char* buffer;
     110                 :     int buffer_size;
     111                 :     int cur_index;
     112                 : } Buffer;
     113                 : 
     114                 : /************************************************************************/
     115                 : /*                       USGSDEMRefillBuffer()                          */
     116                 : /************************************************************************/
     117                 : 
     118              16 : static void USGSDEMRefillBuffer( Buffer* psBuffer )
     119                 : {
     120                 :     memmove(psBuffer->buffer, psBuffer->buffer + psBuffer->cur_index,
     121              16 :             psBuffer->buffer_size - psBuffer->cur_index);
     122                 : 
     123              16 :     psBuffer->buffer_size -= psBuffer->cur_index;
     124                 :     psBuffer->buffer_size += VSIFReadL(psBuffer->buffer + psBuffer->buffer_size,
     125                 :                                        1, psBuffer->max_size - psBuffer->buffer_size,
     126              16 :                                        psBuffer->fp);
     127              16 :     psBuffer->cur_index = 0;
     128              16 : }
     129                 : 
     130                 : /************************************************************************/
     131                 : /*               USGSDEMReadIntFromBuffer()                             */
     132                 : /************************************************************************/
     133                 : 
     134           40262 : static int USGSDEMReadIntFromBuffer( Buffer* psBuffer, int* pbSuccess = NULL )
     135                 : {
     136           40262 :     int nVal = 0;
     137                 :     char c;
     138                 : 
     139          156438 :     while (TRUE)
     140                 :     {
     141          196700 :         if (psBuffer->cur_index >= psBuffer->buffer_size)
     142                 :         {
     143              16 :             USGSDEMRefillBuffer(psBuffer);
     144              16 :             if (psBuffer->cur_index >= psBuffer->buffer_size)
     145                 :             {
     146               0 :                 if( pbSuccess ) *pbSuccess = FALSE;
     147               0 :                 return 0;
     148                 :             }
     149                 :         }
     150                 : 
     151          196700 :         c = psBuffer->buffer[psBuffer->cur_index];
     152          196700 :         psBuffer->cur_index ++;
     153          196700 :         if (!isspace((int)c))
     154                 :             break;
     155                 :     }
     156                 : 
     157           40262 :     int nSign = 1;
     158           40262 :     if (c == '-')
     159            6192 :         nSign = -1;
     160           34070 :     else if (c == '+')
     161               0 :         nSign = 1;
     162           68140 :     else if (c >= '0' && c <= '9')
     163           34070 :         nVal = c - '0';
     164                 :     else
     165                 :     {
     166               0 :         if( pbSuccess ) *pbSuccess = FALSE;
     167               0 :         return 0;
     168                 :     }
     169                 : 
     170           84005 :     while (TRUE)
     171                 :     {
     172          124267 :         if (psBuffer->cur_index >= psBuffer->buffer_size)
     173                 :         {
     174               0 :             USGSDEMRefillBuffer(psBuffer);
     175               0 :             if (psBuffer->cur_index >= psBuffer->buffer_size)
     176                 :             {
     177               0 :                 if( pbSuccess ) *pbSuccess = TRUE;
     178               0 :                 return nSign * nVal;
     179                 :             }
     180                 :         }
     181                 : 
     182          124267 :         c = psBuffer->buffer[psBuffer->cur_index];
     183          124267 :         if (c >= '0' && c <= '9')
     184                 :         {
     185           84005 :             psBuffer->cur_index ++;
     186           84005 :             nVal = nVal * 10 + (c - '0');
     187                 :         }
     188                 :         else
     189                 :         {
     190           40262 :             if( pbSuccess ) *pbSuccess = TRUE;
     191           40262 :             return nSign * nVal;
     192                 :         }
     193                 :     }
     194                 : }
     195                 : 
     196                 : /************************************************************************/
     197                 : /*                USGSDEMReadDoubleFromBuffer()                         */
     198                 : /************************************************************************/
     199                 : 
     200            1280 : static double USGSDEMReadDoubleFromBuffer( Buffer* psBuffer, int nCharCount )
     201                 : 
     202                 : {
     203                 :     int     i;
     204                 : 
     205            1280 :     if (psBuffer->cur_index + nCharCount > psBuffer->buffer_size)
     206                 :     {
     207               0 :         USGSDEMRefillBuffer(psBuffer);
     208               0 :         if (psBuffer->cur_index + nCharCount > psBuffer->buffer_size)
     209                 :         {
     210               0 :             return 0;
     211                 :         }
     212                 :     }
     213                 : 
     214            1280 :     char* szPtr = psBuffer->buffer + psBuffer->cur_index;
     215            1280 :     char backupC = szPtr[nCharCount];
     216            1280 :     szPtr[nCharCount] = 0;
     217           32000 :     for( i = 0; i < nCharCount; i++ )
     218                 :     {
     219           30720 :         if( szPtr[i] == 'D' )
     220            1266 :             szPtr[i] = 'E';
     221                 :     }
     222                 : 
     223            1280 :     double dfVal = CPLAtof(szPtr);
     224            1280 :     szPtr[nCharCount] = backupC;
     225            1280 :     psBuffer->cur_index += nCharCount;
     226                 : 
     227            1280 :     return dfVal;
     228                 : }
     229                 : 
     230                 : /************************************************************************/
     231                 : /*                              DConvert()                              */
     232                 : /************************************************************************/
     233                 : 
     234             318 : static double DConvert( VSILFILE *fp, int nCharCount )
     235                 : 
     236                 : {
     237                 :     char  szBuffer[100];
     238                 :     int   i;
     239                 : 
     240             318 :     VSIFReadL( szBuffer, nCharCount, 1, fp );
     241             318 :     szBuffer[nCharCount] = '\0';
     242                 : 
     243            8238 :     for( i = 0; i < nCharCount; i++ )
     244                 :     {
     245            7920 :         if( szBuffer[i] == 'D' )
     246             309 :             szBuffer[i] = 'E';
     247                 :     }
     248                 : 
     249             318 :     return CPLAtof(szBuffer);
     250                 : }
     251                 : 
     252                 : /************************************************************************/
     253                 : /* ==================================================================== */
     254                 : /*        USGSDEMDataset        */
     255                 : /* ==================================================================== */
     256                 : /************************************************************************/
     257                 : 
     258                 : class USGSDEMRasterBand;
     259                 : 
     260                 : class USGSDEMDataset : public GDALPamDataset
     261                 : {
     262                 :     friend class USGSDEMRasterBand;
     263                 : 
     264                 :     int         nDataStartOffset;
     265                 :     GDALDataType eNaturalDataFormat;
     266                 : 
     267                 :     double      adfGeoTransform[6];
     268                 :     char        *pszProjection; 
     269                 : 
     270                 :     double      fVRes;
     271                 : 
     272                 :     const char  *pszUnits; 
     273                 : 
     274                 :     int         LoadFromFile( VSILFILE * );
     275                 : 
     276                 :     VSILFILE  *fp;
     277                 : 
     278                 :   public:
     279                 :                 USGSDEMDataset();
     280                 :     ~USGSDEMDataset();
     281                 :     
     282                 :     static int  Identify( GDALOpenInfo * );
     283                 :     static GDALDataset *Open( GDALOpenInfo * );
     284                 :     CPLErr  GetGeoTransform( double * padfTransform );
     285                 :     const char *GetProjectionRef();
     286                 : };
     287                 : 
     288                 : /************************************************************************/
     289                 : /* ==================================================================== */
     290                 : /*                            USGSDEMRasterBand                         */
     291                 : /* ==================================================================== */
     292                 : /************************************************************************/
     293                 : 
     294                 : class USGSDEMRasterBand : public GDALPamRasterBand
     295              24 : {
     296                 :     friend class USGSDEMDataset;
     297                 : 
     298                 :   public:
     299                 : 
     300                 :         USGSDEMRasterBand( USGSDEMDataset * );
     301                 :     
     302                 :     virtual const char *GetUnitType();
     303                 :     virtual double GetNoDataValue( int *pbSuccess = NULL );
     304                 :     virtual CPLErr IReadBlock( int, int, void * );
     305                 : };
     306                 : 
     307                 : 
     308                 : /************************************************************************/
     309                 : /*                           USGSDEMRasterBand()                            */
     310                 : /************************************************************************/
     311                 : 
     312              24 : USGSDEMRasterBand::USGSDEMRasterBand( USGSDEMDataset *poDS )
     313                 : 
     314                 : {
     315              24 :     this->poDS = poDS;
     316              24 :     this->nBand = 1;
     317                 : 
     318              24 :     eDataType = poDS->eNaturalDataFormat;
     319                 : 
     320              24 :     nBlockXSize = poDS->GetRasterXSize();
     321              24 :     nBlockYSize = poDS->GetRasterYSize();
     322                 : 
     323              24 : }
     324                 : 
     325                 : /************************************************************************/
     326                 : /*                             IReadBlock()                             */
     327                 : /************************************************************************/
     328                 : 
     329              10 : CPLErr USGSDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     330                 :                                       void * pImage )
     331                 : 
     332                 : {
     333                 :     double  dfYMin;
     334              10 :     int   bad = FALSE;
     335              10 :     USGSDEMDataset *poGDS = (USGSDEMDataset *) poDS;
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Initialize image buffer to nodata value.                        */
     339                 : /* -------------------------------------------------------------------- */
     340           40678 :     for( int k = GetXSize() * GetYSize() - 1; k >= 0; k-- )
     341                 :     {
     342           40668 :         if( GetRasterDataType() == GDT_Int16 )
     343           37846 :             ((GInt16 *) pImage)[k] = USGSDEM_NODATA;
     344                 :         else
     345            2822 :             ((float *) pImage)[k] = USGSDEM_NODATA;
     346                 :     }
     347                 : 
     348                 : /* -------------------------------------------------------------------- */
     349                 : /*      Seek to data.                                                   */
     350                 : /* -------------------------------------------------------------------- */
     351              10 :     VSIFSeekL(poGDS->fp, poGDS->nDataStartOffset, 0);
     352                 : 
     353              10 :     dfYMin = poGDS->adfGeoTransform[3] 
     354              10 :         + (GetYSize()-0.5) * poGDS->adfGeoTransform[5];
     355                 : 
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      Read all the profiles into the image buffer.                    */
     358                 : /* -------------------------------------------------------------------- */
     359                 : 
     360                 :     Buffer sBuffer;
     361              10 :     sBuffer.max_size = 32768;
     362              10 :     sBuffer.buffer = (char*) CPLMalloc(sBuffer.max_size + 1);
     363              10 :     sBuffer.fp = poGDS->fp;
     364              10 :     sBuffer.buffer_size = 0;
     365              10 :     sBuffer.cur_index = 0;
     366                 : 
     367             266 :     for( int i = 0; i < GetXSize(); i++)
     368                 :     {
     369                 :         int njunk, nCPoints, lygap;
     370                 :         double  djunk, dxStart, dyStart, dfElevOffset;
     371                 : 
     372             256 :         njunk = USGSDEMReadIntFromBuffer(&sBuffer);
     373             256 :         njunk = USGSDEMReadIntFromBuffer(&sBuffer);
     374             256 :         nCPoints = USGSDEMReadIntFromBuffer(&sBuffer);
     375             256 :         njunk = USGSDEMReadIntFromBuffer(&sBuffer);
     376                 : 
     377             256 :         dxStart = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
     378             256 :         dyStart = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
     379             256 :         dfElevOffset = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
     380             256 :         djunk = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
     381             256 :         djunk = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
     382                 : 
     383             256 :         if( EQUALN(poGDS->pszProjection,"GEOGCS",6) )
     384             246 :             dyStart = dyStart / 3600.0;
     385                 :         
     386             256 :         lygap = (int)((dfYMin - dyStart)/poGDS->adfGeoTransform[5]+ 0.5);
     387                 : 
     388           39494 :         for (int j=lygap; j < (nCPoints+(int)lygap); j++)
     389                 :         {
     390           39238 :             int   iY = GetYSize() - j - 1;
     391                 :             int         nElev;
     392                 :             int     bSuccess;
     393                 : 
     394           39238 :             nElev = USGSDEMReadIntFromBuffer(&sBuffer, &bSuccess);
     395           39238 :             if( !bSuccess )
     396                 :             {
     397               0 :                 CPLFree(sBuffer.buffer);
     398               0 :                 return CE_Failure;
     399                 :             }
     400                 :             
     401           39238 :             if (iY < 0 || iY >= GetYSize() )
     402               0 :                 bad = TRUE;
     403           39238 :             else if( nElev == USGSDEM_NODATA )
     404                 :                 /* leave in output buffer as nodata */;
     405                 :             else
     406                 :             {
     407                 :                 float fComputedElev = 
     408           33846 :                     (float)(nElev * poGDS->fVRes + dfElevOffset);
     409                 : 
     410           33846 :                 if( GetRasterDataType() == GDT_Int16 )
     411                 :                 {
     412           33785 :                     ((GInt16 *) pImage)[i + iY*GetXSize()] = 
     413           33785 :                         (GInt16) fComputedElev;
     414                 :                 }
     415                 :                 else
     416                 :                 {
     417              61 :                     ((float *) pImage)[i + iY*GetXSize()] = fComputedElev;
     418                 :                 }
     419                 :             }
     420                 :         }
     421                 :     }
     422              10 :     CPLFree(sBuffer.buffer);
     423                 : 
     424              10 :     return CE_None;
     425                 : }
     426                 : 
     427                 : /************************************************************************/
     428                 : /*                           GetNoDataValue()                           */
     429                 : /************************************************************************/
     430                 : 
     431              16 : double USGSDEMRasterBand::GetNoDataValue( int *pbSuccess )
     432                 : 
     433                 : {
     434              16 :     if( pbSuccess != NULL )
     435              14 :         *pbSuccess = TRUE;
     436                 : 
     437              16 :     return USGSDEM_NODATA;
     438                 : }
     439                 : 
     440                 : /************************************************************************/
     441                 : /*                            GetUnitType()                             */
     442                 : /************************************************************************/
     443               9 : const char *USGSDEMRasterBand::GetUnitType()
     444                 : {
     445               9 :     USGSDEMDataset *poGDS = (USGSDEMDataset *) poDS;
     446                 : 
     447               9 :     return poGDS->pszUnits;
     448                 : }
     449                 : 
     450                 : /************************************************************************/
     451                 : /* ==================================================================== */
     452                 : /*        USGSDEMDataset        */
     453                 : /* ==================================================================== */
     454                 : /************************************************************************/
     455                 : 
     456                 : /************************************************************************/
     457                 : /*                           USGSDEMDataset()                           */
     458                 : /************************************************************************/
     459                 : 
     460              24 : USGSDEMDataset::USGSDEMDataset()
     461                 : 
     462                 : {
     463              24 :     fp = NULL;
     464              24 :     pszProjection = NULL;
     465              24 : }
     466                 : 
     467                 : /************************************************************************/
     468                 : /*                            ~USGSDEMDataset()                         */
     469                 : /************************************************************************/
     470                 : 
     471              24 : USGSDEMDataset::~USGSDEMDataset()
     472                 : 
     473                 : {
     474              24 :     FlushCache();
     475                 : 
     476              24 :     CPLFree( pszProjection );
     477              24 :     if( fp != NULL )
     478              24 :         VSIFCloseL( fp );
     479              24 : }
     480                 : 
     481                 : /************************************************************************/
     482                 : /*                            LoadFromFile()                            */
     483                 : /*                                                                      */
     484                 : /*      If the data from DEM is in meters, then values are stored as    */
     485                 : /*      shorts. If DEM data is in feet, then height data will be        */
     486                 : /*      stored in float, to preserve the precision of the original      */
     487                 : /*      data. returns true if the file was successfully opened and      */
     488                 : /*      read.                                                           */
     489                 : /************************************************************************/
     490                 : 
     491              24 : int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
     492                 : {
     493                 :     int   i, j;
     494                 :     int   nRow, nColumn;
     495                 :     int   nVUnit, nGUnit;
     496                 :     double  dxdelta, dydelta;
     497                 :     double  dElevMax, dElevMin;
     498                 :     int   bNewFormat;
     499                 :     int   nCoordSystem;
     500                 :     int   nProfiles;
     501                 :     char  szDateBuffer[5];
     502                 :     DPoint2 corners[4];     // SW, NW, NE, SE
     503                 :     DPoint2 extent_min, extent_max;
     504                 :     int   iUTMZone;
     505                 : 
     506                 :     // check for version of DEM format
     507              24 :     VSIFSeekL(InDem, 864, 0);
     508                 : 
     509                 :     // Read DEM into matrix
     510              24 :     nRow = ReadInt(InDem);
     511              24 :     nColumn = ReadInt(InDem);
     512              24 :     bNewFormat = ((nRow!=1)||(nColumn!=1));
     513              24 :     if (bNewFormat)
     514                 :     {
     515              23 :         VSIFSeekL(InDem, 1024, 0);  // New Format
     516              23 :         i = ReadInt(InDem);
     517              23 :         j = ReadInt(InDem);
     518              24 :         if ((i!=1)||(j!=1 && j != 0)) // File OK?
     519                 :         {
     520               1 :             VSIFSeekL(InDem, 893, 0);   // Undocumented Format (39109h1.dem)
     521               1 :             i = ReadInt(InDem);
     522               1 :             j = ReadInt(InDem);
     523               1 :             if ((i!=1)||(j!=1))     // File OK?
     524                 :             {
     525                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     526               0 :                           "Does not appear to be a USGS DEM file." );
     527               0 :                 return FALSE;
     528                 :             }
     529                 :             else
     530               1 :                 nDataStartOffset = 893;
     531                 :         }
     532                 :         else
     533              22 :             nDataStartOffset = 1024;
     534                 :     }
     535                 :     else
     536               1 :         nDataStartOffset = 864;
     537                 : 
     538              24 :     VSIFSeekL(InDem, 156, 0);
     539              24 :     nCoordSystem = ReadInt(InDem);
     540              24 :     iUTMZone = ReadInt(InDem);
     541                 : 
     542              24 :     VSIFSeekL(InDem, 528, 0);
     543              24 :     nGUnit = ReadInt(InDem);
     544              24 :     nVUnit = ReadInt(InDem);
     545                 : 
     546                 :     // Vertical Units in meters
     547              24 :     if (nVUnit==1)
     548               0 :         pszUnits = "ft";
     549                 :     else
     550              24 :         pszUnits = "m";
     551                 : 
     552              24 :     VSIFSeekL(InDem, 816, 0);
     553              24 :     dxdelta = DConvert(InDem, 12);
     554              24 :     dydelta = DConvert(InDem, 12);
     555              24 :     fVRes = DConvert(InDem, 12);
     556                 : 
     557                 : /* -------------------------------------------------------------------- */
     558                 : /*      Should we treat this as floating point, or GInt16.              */
     559                 : /* -------------------------------------------------------------------- */
     560              25 :     if (nVUnit==1 || fVRes < 1.0)
     561               1 :         eNaturalDataFormat = GDT_Float32;
     562                 :     else
     563              23 :         eNaturalDataFormat = GDT_Int16;
     564                 : 
     565                 : /* -------------------------------------------------------------------- */
     566                 : /*      Read four corner coordinates.                                   */
     567                 : /* -------------------------------------------------------------------- */
     568              24 :     VSIFSeekL(InDem, 546, 0);
     569             120 :     for (i = 0; i < 4; i++)
     570                 :     {
     571              96 :         corners[i].x = DConvert(InDem, 24);
     572              96 :         corners[i].y = DConvert(InDem, 24);
     573                 :     }
     574                 :     
     575                 :     // find absolute extents of raw vales
     576              24 :     extent_min.x = MIN(corners[0].x, corners[1].x);
     577              24 :     extent_max.x = MAX(corners[2].x, corners[3].x);
     578              24 :     extent_min.y = MIN(corners[0].y, corners[3].y);
     579              24 :     extent_max.y = MAX(corners[1].y, corners[2].y);
     580                 : 
     581              24 :     dElevMin = DConvert(InDem, 48);
     582              24 :     dElevMax = DConvert(InDem, 48);
     583                 : 
     584              24 :     VSIFSeekL(InDem, 858, 0);
     585              24 :     nProfiles = ReadInt(InDem);
     586                 : 
     587                 : /* -------------------------------------------------------------------- */
     588                 : /*      Collect the spatial reference system.                           */
     589                 : /* -------------------------------------------------------------------- */
     590              24 :     OGRSpatialReference sr;
     591              24 :     int bNAD83 =TRUE;
     592                 : 
     593                 :     // OLD format header ends at byte 864
     594              24 :     if (bNewFormat)
     595                 :     {
     596                 :         char szHorzDatum[3];
     597                 : 
     598                 :         // year of data compilation
     599              23 :         VSIFSeekL(InDem, 876, 0);
     600              23 :         VSIFReadL(szDateBuffer, 4, 1, InDem);
     601              23 :         szDateBuffer[4] = 0;
     602                 : 
     603                 :         // Horizontal datum
     604                 :         // 1=North American Datum 1927 (NAD 27)
     605                 :         // 2=World Geodetic System 1972 (WGS 72)
     606                 :         // 3=WGS 84
     607                 :         // 4=NAD 83
     608                 :         // 5=Old Hawaii Datum
     609                 :         // 6=Puerto Rico Datum
     610                 :         int datum;
     611              23 :         VSIFSeekL(InDem, 890, 0);
     612              23 :         VSIFReadL( szHorzDatum, 1, 2, InDem );
     613              23 :         szHorzDatum[2] = '\0';
     614              23 :         datum = atoi(szHorzDatum);
     615              23 :         switch (datum)
     616                 :         {
     617                 :           case 1:
     618               1 :             sr.SetWellKnownGeogCS( "NAD27" );
     619               1 :             bNAD83 = FALSE;
     620               1 :             break;
     621                 : 
     622                 :           case 2:
     623               5 :             sr.SetWellKnownGeogCS( "WGS72" );
     624               5 :             break;
     625                 : 
     626                 :           case 3:
     627              14 :             sr.SetWellKnownGeogCS( "WGS84" );
     628              14 :             break;
     629                 : 
     630                 :           case 4:
     631               1 :             sr.SetWellKnownGeogCS( "NAD83" );
     632               1 :             break;
     633                 : 
     634                 :           case -9:
     635               0 :             break;
     636                 : 
     637                 :           default:
     638               2 :             sr.SetWellKnownGeogCS( "NAD27" );
     639                 :             break;
     640                 :         }
     641                 :     }
     642                 :     else
     643                 :     {
     644               1 :         sr.SetWellKnownGeogCS( "NAD27" );
     645               1 :         bNAD83 = FALSE;
     646                 :     }
     647                 : 
     648              24 :     if (nCoordSystem == 1)  // UTM
     649               6 :         sr.SetUTM( iUTMZone, TRUE );
     650                 : 
     651              18 :     else if (nCoordSystem == 2) // state plane
     652                 :     {
     653               0 :         if( nGUnit == 1 )
     654                 :             sr.SetStatePlane( iUTMZone, bNAD83,
     655               0 :                               "Foot", CPLAtof(SRS_UL_US_FOOT_CONV) );
     656                 :         else
     657               0 :             sr.SetStatePlane( iUTMZone, bNAD83 );
     658                 :     }
     659                 : 
     660              24 :     sr.exportToWkt( &pszProjection );
     661                 : 
     662                 : /* -------------------------------------------------------------------- */
     663                 : /*      For UTM we use the extents (really the UTM coordinates of       */
     664                 : /*      the lat/long corners of the quad) to determine the size in      */
     665                 : /*      pixels and lines, but we have to make the anchors be modulus    */
     666                 : /*      the pixel size which what really gets used.                     */
     667                 : /* -------------------------------------------------------------------- */
     668              30 :     if (nCoordSystem == 1          // UTM
     669                 :         || nCoordSystem == 2     // State Plane
     670                 :         || nCoordSystem == -9999 ) // unknown
     671                 :     {
     672                 :         int njunk;
     673                 :         double  dxStart;
     674                 : 
     675                 :         // expand extents modulus the pixel size.
     676               6 :         extent_min.y = floor(extent_min.y/dydelta) * dydelta;
     677               6 :         extent_max.y = ceil(extent_max.y/dydelta) * dydelta;
     678                 : 
     679                 :         // Forceably compute X extents based on first profile and pixelsize.
     680               6 :         VSIFSeekL(InDem, nDataStartOffset, 0);
     681               6 :         njunk = ReadInt(InDem);
     682               6 :         njunk = ReadInt(InDem);
     683               6 :         njunk = ReadInt(InDem);
     684               6 :         njunk = ReadInt(InDem);
     685               6 :         dxStart = DConvert(InDem, 24);
     686                 :         
     687               6 :         nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
     688               6 :         nRasterXSize = nProfiles;
     689                 : 
     690               6 :         adfGeoTransform[0] = dxStart - dxdelta/2.0;
     691               6 :         adfGeoTransform[1] = dxdelta;
     692               6 :         adfGeoTransform[2] = 0.0;
     693               6 :         adfGeoTransform[3] = extent_max.y + dydelta/2.0;
     694               6 :         adfGeoTransform[4] = 0.0;
     695               6 :         adfGeoTransform[5] = -dydelta;
     696                 :     }
     697                 : /* -------------------------------------------------------------------- */
     698                 : /*      Geographic -- use corners directly.                             */
     699                 : /* -------------------------------------------------------------------- */
     700                 :     else
     701                 :     {
     702              18 :         nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
     703              18 :         nRasterXSize = nProfiles;
     704                 : 
     705                 :         // Translate extents from arc-seconds to decimal degrees.
     706              18 :         adfGeoTransform[0] = (extent_min.x - dxdelta/2.0) / 3600.0;
     707              18 :         adfGeoTransform[1] = dxdelta / 3600.0;
     708              18 :         adfGeoTransform[2] = 0.0;
     709              18 :         adfGeoTransform[3] = (extent_max.y + dydelta/2.0) / 3600.0;
     710              18 :         adfGeoTransform[4] = 0.0;
     711              18 :         adfGeoTransform[5] = (-dydelta) / 3600.0;
     712                 :     }
     713                 : 
     714              24 :     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
     715                 :     {
     716               0 :         return FALSE;
     717                 :     }
     718                 : 
     719              24 :     return TRUE;
     720                 : }
     721                 : 
     722                 : /************************************************************************/
     723                 : /*                          GetGeoTransform()                           */
     724                 : /************************************************************************/
     725                 : 
     726              31 : CPLErr USGSDEMDataset::GetGeoTransform( double * padfTransform )
     727                 : 
     728                 : {
     729              31 :     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     730              31 :     return CE_None;
     731                 : }
     732                 : 
     733                 : /************************************************************************/
     734                 : /*                          GetProjectionRef()                          */
     735                 : /************************************************************************/
     736                 : 
     737              47 : const char *USGSDEMDataset::GetProjectionRef()
     738                 : 
     739                 : {
     740              47 :     return pszProjection;
     741                 : }
     742                 : 
     743                 : 
     744                 : /************************************************************************/
     745                 : /*                              Identify()                              */
     746                 : /************************************************************************/
     747                 : 
     748           11903 : int USGSDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
     749                 : 
     750                 : {
     751           11903 :     if( poOpenInfo->nHeaderBytes < 200 )
     752           11381 :         return FALSE;
     753                 : 
     754             522 :     if( !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     0",6)
     755                 :         && !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     1",6)
     756                 :         && !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     2",6) 
     757                 :         && !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     3",6)
     758                 :         && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " -9999",6) )
     759             498 :         return FALSE;
     760                 : 
     761              24 :     if( !EQUALN((const char *) poOpenInfo->pabyHeader+150, "     1",6) 
     762                 :         && !EQUALN((const char *) poOpenInfo->pabyHeader+150, "     4",6))
     763               0 :         return FALSE;
     764                 : 
     765              24 :     return TRUE;
     766                 : }
     767                 : 
     768                 : /************************************************************************/
     769                 : /*                                Open()                                */
     770                 : /************************************************************************/
     771                 : 
     772            1774 : GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
     773                 : 
     774                 : {
     775            1774 :     if( !Identify( poOpenInfo ) )
     776            1750 :         return NULL;
     777                 : 
     778              24 :     VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     779              24 :     if (fp == NULL)
     780               0 :         return NULL;
     781                 : 
     782                 : /* -------------------------------------------------------------------- */
     783                 : /*      Create a corresponding GDALDataset.                             */
     784                 : /* -------------------------------------------------------------------- */
     785                 :     USGSDEMDataset  *poDS;
     786                 : 
     787              24 :     poDS = new USGSDEMDataset();
     788                 : 
     789              24 :     poDS->fp = fp;
     790                 :     
     791                 : /* -------------------------------------------------------------------- */
     792                 : /*  Read the file.              */
     793                 : /* -------------------------------------------------------------------- */
     794              24 :     if( !poDS->LoadFromFile( poDS->fp ) )
     795                 :     {
     796               0 :         delete poDS;
     797               0 :         return NULL;
     798                 :     }
     799                 :     
     800                 : /* -------------------------------------------------------------------- */
     801                 : /*      Confirm the requested access is supported.                      */
     802                 : /* -------------------------------------------------------------------- */
     803              24 :     if( poOpenInfo->eAccess == GA_Update )
     804                 :     {
     805               0 :         delete poDS;
     806                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     807                 :                   "The USGSDEM driver does not support update access to existing"
     808               0 :                   " datasets.\n" );
     809               0 :         return NULL;
     810                 :     }
     811                 :     
     812                 : /* -------------------------------------------------------------------- */
     813                 : /*      Create band information objects.                                */
     814                 : /* -------------------------------------------------------------------- */
     815              24 :     poDS->SetBand( 1, new USGSDEMRasterBand( poDS ));
     816                 : 
     817              24 :     poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
     818                 : 
     819                 : /* -------------------------------------------------------------------- */
     820                 : /*      Initialize any PAM information.                                 */
     821                 : /* -------------------------------------------------------------------- */
     822              24 :     poDS->SetDescription( poOpenInfo->pszFilename );
     823              24 :     poDS->TryLoadXML();
     824                 : 
     825                 : /* -------------------------------------------------------------------- */
     826                 : /*      Open overviews.                                                 */
     827                 : /* -------------------------------------------------------------------- */
     828              24 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     829                 : 
     830              24 :     return( poDS );
     831                 : }
     832                 : 
     833                 : /************************************************************************/
     834                 : /*                        GDALRegister_USGSDEM()                        */
     835                 : /************************************************************************/
     836                 : 
     837             610 : void GDALRegister_USGSDEM()
     838                 : 
     839                 : {
     840                 :     GDALDriver  *poDriver;
     841                 : 
     842             610 :     if( GDALGetDriverByName( "USGSDEM" ) == NULL )
     843                 :     {
     844             588 :         poDriver = new GDALDriver();
     845                 :         
     846             588 :         poDriver->SetDescription( "USGSDEM" );
     847                 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, 
     848             588 :                                    "dem" );
     849                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     850             588 :                                    "USGS Optional ASCII DEM (and CDED)" );
     851                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     852             588 :                                    "frmt_usgsdem.html" );
     853             588 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Int16" );
     854                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
     855                 : "<CreationOptionList>"
     856                 : "   <Option name='PRODUCT' type='string-select' description='Specific Product Type'>"
     857                 : "       <Value>DEFAULT</Value>"
     858                 : "       <Value>CDED50K</Value>"
     859                 : "   </Option>"
     860                 : "   <Option name='TOPLEFT' type='string' description='Top left product corner (ie. 117d15w,52d30n'/>"
     861                 : "   <Option name='RESAMPLE' type='string-select' description='Resampling kernel to use if resampled.'>"
     862                 : "       <Value>Nearest</Value>"
     863                 : "       <Value>Bilinear</Value>"
     864                 : "       <Value>Cubic</Value>"
     865                 : "       <Value>CubicSpline</Value>"
     866                 : "   </Option>"
     867                 : "   <Option name='TEMPLATE' type='string' description='File to default metadata from.'/>"
     868                 : "   <Option name='DEMLevelCode' type='int' description='DEM Level (1, 2 or 3 if set)'/>"
     869                 : "   <Option name='DataSpecVersion' type='int' description='Data and Specification version/revision (eg. 1020)'/>"
     870                 : "   <Option name='PRODUCER' type='string' description='Producer Agency (up to 60 characters)'/>"
     871                 : "   <Option name='OriginCode' type='string' description='Origin code (up to 4 characters, YT for Yukon)'/>"
     872                 : "   <Option name='ProcessCode' type='string' description='Processing Code (8=ANUDEM, 9=FME, A=TopoGrid)'/>"
     873                 : "   <Option name='ZRESOLUTION' type='float' description='Scaling factor for elevation values'/>"
     874                 : "   <Option name='NTS' type='string' description='NTS Mapsheet name, used to derive TOPLEFT.'/>"
     875                 : "   <Option name='INTERNALNAME' type='string' description='Dataset name written into file header.'/>"
     876             588 : "</CreationOptionList>" );
     877                 : 
     878             588 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     879                 : 
     880             588 :         poDriver->pfnOpen = USGSDEMDataset::Open;
     881             588 :         poDriver->pfnCreateCopy = USGSDEMCreateCopy;
     882             588 :         poDriver->pfnIdentify = USGSDEMDataset::Identify;
     883                 : 
     884             588 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     885                 :     }
     886             610 : }

Generated by: LCOV version 1.7