LCOV - code coverage report
Current view: directory - frmts/usgsdem - usgsdemdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 303 274 90.4 %
Date: 2012-04-28 Functions: 23 18 78.3 %

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

Generated by: LCOV version 1.7