LCOV - code coverage report
Current view: directory - frmts/raw - lcpdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 384 278 72.4 %
Date: 2012-12-26 Functions: 11 7 63.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: lcpdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
       3                 :  *
       4                 :  * Project:  LCP Driver
       5                 :  * Purpose:  FARSITE v.4 Landscape file (.lcp) reader for GDAL
       6                 :  * Author:   Chris Toney
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2008, Chris Toney
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "rawdataset.h"
      31                 : #include "cpl_string.h"
      32                 : #include "ogr_spatialref.h"
      33                 : 
      34                 : CPL_CVSID("$Id: lcpdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
      35                 : 
      36                 : CPL_C_START
      37                 : void    GDALRegister_LCP(void);
      38                 : CPL_C_END
      39                 : 
      40                 : #define LCP_HEADER_SIZE 7316
      41                 : 
      42                 : /************************************************************************/
      43                 : /* ==================================================================== */
      44                 : /*                              LCPDataset                              */
      45                 : /* ==================================================================== */
      46                 : /************************************************************************/
      47                 : 
      48                 : class LCPDataset : public RawDataset
      49                 : {
      50                 :     VSILFILE    *fpImage;       // image data file.
      51                 :     char  pachHeader[LCP_HEADER_SIZE];
      52                 : 
      53                 :     CPLString   osPrjFilename;
      54                 :     char        *pszProjection;
      55                 : 
      56                 :   public:
      57                 :                 LCPDataset();
      58                 :                 ~LCPDataset();
      59                 : 
      60                 :     virtual char **GetFileList(void);
      61                 : 
      62                 :     virtual CPLErr GetGeoTransform( double * );
      63                 : 
      64                 :     static int          Identify( GDALOpenInfo * );
      65                 :     static GDALDataset *Open( GDALOpenInfo * );
      66                 :     
      67                 :     virtual const char *GetProjectionRef(void);
      68                 : };
      69                 : 
      70                 : /************************************************************************/
      71                 : /*                            LCPDataset()                             */
      72                 : /************************************************************************/
      73                 : 
      74               2 : LCPDataset::LCPDataset()
      75                 : {
      76               2 :     fpImage = NULL;
      77               2 :     pszProjection = NULL;
      78               2 : }
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                            ~LCPDataset()                            */
      82                 : /************************************************************************/
      83                 : 
      84               2 : LCPDataset::~LCPDataset()
      85                 : 
      86                 : {
      87               2 :     FlushCache();
      88               2 :     if( fpImage != NULL )
      89               2 :         VSIFCloseL( fpImage );
      90               2 :     CPLFree(pszProjection);
      91               2 : }
      92                 : 
      93                 : /************************************************************************/
      94                 : /*                          GetGeoTransform()                           */
      95                 : /************************************************************************/
      96                 : 
      97               2 : CPLErr LCPDataset::GetGeoTransform( double * padfTransform )
      98                 : {
      99                 :     double      dfEast, dfWest, dfNorth, dfSouth, dfCellX, dfCellY;
     100                 : 
     101               2 :     memcpy(&dfEast, pachHeader + 4172, sizeof(double));
     102               2 :     memcpy(&dfWest, pachHeader + 4180, sizeof(double));
     103               2 :     memcpy(&dfNorth, pachHeader + 4188, sizeof(double));
     104               2 :     memcpy(&dfSouth, pachHeader + 4196, sizeof(double));
     105               2 :     memcpy(&dfCellX, pachHeader + 4208, sizeof(double));
     106               2 :     memcpy(&dfCellY, pachHeader + 4216, sizeof(double));
     107                 :     CPL_LSBPTR64(&dfEast);
     108                 :     CPL_LSBPTR64(&dfWest);
     109                 :     CPL_LSBPTR64(&dfNorth);
     110                 :     CPL_LSBPTR64(&dfSouth);
     111                 :     CPL_LSBPTR64(&dfCellX);
     112                 :     CPL_LSBPTR64(&dfCellY);
     113                 : 
     114               2 :     padfTransform[0] = dfWest;
     115               2 :     padfTransform[3] = dfNorth;
     116               2 :     padfTransform[1] = dfCellX;
     117               2 :     padfTransform[2] = 0.0;
     118                 : 
     119               2 :     padfTransform[4] = 0.0;
     120               2 :     padfTransform[5] = -1 * dfCellY;
     121                 : 
     122               2 :     return CE_None;
     123                 : }
     124                 : 
     125                 : /************************************************************************/
     126                 : /*                              Identify()                              */
     127                 : /************************************************************************/
     128                 : 
     129           11953 : int LCPDataset::Identify( GDALOpenInfo * poOpenInfo )
     130                 : 
     131                 : {
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      Verify that this is a FARSITE v.4 LCP file                      */
     134                 : /* -------------------------------------------------------------------- */
     135           11953 :     if( poOpenInfo->nHeaderBytes < 50 )
     136           11364 :         return FALSE;
     137                 : 
     138                 :     /* check if first three fields have valid data */
     139             589 :     if( (CPL_LSBINT32PTR(poOpenInfo->pabyHeader) != 20
     140                 :           && CPL_LSBINT32PTR(poOpenInfo->pabyHeader) != 21)
     141                 :         || (CPL_LSBINT32PTR(poOpenInfo->pabyHeader+4) != 20
     142                 :           && CPL_LSBINT32PTR(poOpenInfo->pabyHeader+4) != 21)
     143                 :         || (CPL_LSBINT32PTR(poOpenInfo->pabyHeader+8) < -90
     144                 :              || CPL_LSBINT32PTR(poOpenInfo->pabyHeader+8) > 90) )
     145                 :     {
     146             587 :         return FALSE;
     147                 :     }
     148                 : 
     149               2 :     return TRUE;
     150                 : }
     151                 : 
     152                 : /************************************************************************/
     153                 : /*                            GetFileList()                             */
     154                 : /************************************************************************/
     155                 : 
     156               0 : char **LCPDataset::GetFileList()
     157                 : 
     158                 : {
     159               0 :     char **papszFileList = GDALPamDataset::GetFileList();
     160                 : 
     161               0 :     if( pszProjection != NULL )
     162               0 :         papszFileList = CSLAddString( papszFileList, osPrjFilename );
     163                 : 
     164               0 :     return papszFileList;
     165                 : }
     166                 : 
     167                 : /************************************************************************/
     168                 : /*                                Open()                                */
     169                 : /************************************************************************/
     170                 : 
     171            1860 : GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
     172                 : 
     173                 : {
     174                 : /* -------------------------------------------------------------------- */
     175                 : /*      Verify that this is a FARSITE LCP file    */
     176                 : /* -------------------------------------------------------------------- */
     177            1860 :     if( !Identify( poOpenInfo ) )
     178            1858 :         return NULL;
     179                 :         
     180                 : /* -------------------------------------------------------------------- */
     181                 : /*      Confirm the requested access is supported.                      */
     182                 : /* -------------------------------------------------------------------- */
     183               2 :     if( poOpenInfo->eAccess == GA_Update )
     184                 :     {
     185                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     186                 :                   "The LCP driver does not support update access to existing"
     187               0 :                   " datasets.\n" );
     188               0 :         return NULL;
     189                 :     }
     190                 :     
     191                 : /* -------------------------------------------------------------------- */
     192                 : /*      Create a corresponding GDALDataset.                             */
     193                 : /* -------------------------------------------------------------------- */
     194                 :     LCPDataset  *poDS;
     195                 :     VSILFILE        *fpImage;
     196                 : 
     197               2 :     fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     198               2 :     if (fpImage == NULL)
     199               0 :         return NULL;
     200                 : 
     201               2 :     poDS = new LCPDataset();
     202               2 :     poDS->fpImage = fpImage;
     203                 : 
     204                 : /* -------------------------------------------------------------------- */
     205                 : /*      Read the header and extract some information.                   */
     206                 : /* -------------------------------------------------------------------- */
     207                 :    int bHaveCrownFuels, bHaveGroundFuels;
     208                 :    int nBands, i;
     209               2 :    long nWidth = -1, nHeight = -1;
     210                 :    int nTemp, nTemp2;
     211                 :    char szTemp[32];
     212                 :    char* pszList;
     213                 : 
     214               2 :    VSIFSeekL( poDS->fpImage, 0, SEEK_SET );
     215               2 :    if (VSIFReadL( poDS->pachHeader, 1, LCP_HEADER_SIZE, poDS->fpImage ) != LCP_HEADER_SIZE)
     216                 :    {
     217               0 :        CPLError(CE_Failure, CPLE_FileIO, "File too short");
     218               0 :        delete poDS;
     219               0 :        return NULL;
     220                 :    }
     221                 : 
     222               2 :    nWidth = CPL_LSBINT32PTR (poDS->pachHeader + 4164);
     223               2 :    nHeight = CPL_LSBINT32PTR (poDS->pachHeader + 4168);
     224                 : 
     225               2 :    poDS->nRasterXSize = nWidth;
     226               2 :    poDS->nRasterYSize = nHeight;
     227                 : 
     228               2 :    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     229                 :    {
     230               0 :        delete poDS;
     231               0 :        return NULL;
     232                 :    }
     233                 : 
     234                 :    // crown fuels = canopy height, canopy base height, canopy bulk density
     235                 :    // 21 = have them, 20 = don't have them
     236               2 :    bHaveCrownFuels = ( CPL_LSBINT32PTR (poDS->pachHeader + 0) - 20 );
     237                 :    // ground fuels = duff loading, coarse woody
     238               2 :    bHaveGroundFuels = ( CPL_LSBINT32PTR (poDS->pachHeader + 4) - 20 );
     239                 : 
     240               2 :    if( bHaveCrownFuels )
     241                 :    {
     242               2 :        if( bHaveGroundFuels )
     243               0 :            nBands = 10;
     244                 :        else
     245               2 :            nBands = 8;
     246                 :    }
     247                 :    else
     248                 :    {
     249               0 :        if( bHaveGroundFuels )
     250               0 :            nBands = 7;
     251                 :        else
     252               0 :            nBands = 5;
     253                 :    }
     254                 : 
     255                 :    // add dataset-level metadata
     256                 : 
     257               2 :    nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 8);
     258               2 :    sprintf(szTemp, "%d", nTemp);
     259               2 :    poDS->SetMetadataItem( "LATITUDE", szTemp );
     260                 : 
     261               2 :    nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 4204);
     262               2 :    if ( nTemp == 0 )
     263               2 :       poDS->SetMetadataItem( "LINEAR_UNIT", "Meters" );
     264               2 :    if ( nTemp == 1 )
     265               0 :       poDS->SetMetadataItem( "LINEAR_UNIT", "Feet" );
     266                 : 
     267               2 :    poDS->pachHeader[LCP_HEADER_SIZE-1] = '\0';
     268               2 :    poDS->SetMetadataItem( "DESCRIPTION", poDS->pachHeader + 6804 );
     269                 : 
     270                 : 
     271                 : /* -------------------------------------------------------------------- */
     272                 : /*      Create band information objects.                                */
     273                 : /* -------------------------------------------------------------------- */
     274                 : 
     275                 :    int          iPixelSize;
     276               2 :    iPixelSize = nBands * 2;
     277                 :    int          bNativeOrder;
     278                 : 
     279               2 :    if (nWidth > INT_MAX / iPixelSize)
     280                 :    {
     281               0 :        CPLError( CE_Failure, CPLE_AppDefined,  "Int overflow occured");
     282               0 :        delete poDS;
     283               0 :        return NULL;
     284                 :    }
     285                 : 
     286                 : #ifdef CPL_LSB
     287               2 :    bNativeOrder = TRUE;
     288                 : #else
     289                 :    bNativeOrder = FALSE;
     290                 : #endif
     291                 : 
     292               2 :    pszList = (char*)CPLMalloc(2048);
     293                 : 
     294              18 :    for( int iBand = 1; iBand <= nBands; iBand++ )
     295                 :    {
     296              16 :         GDALRasterBand  *poBand = NULL;
     297                 : 
     298                 :         poBand = new RawRasterBand(
     299                 :                      poDS, iBand, poDS->fpImage, LCP_HEADER_SIZE + ((iBand-1)*2),
     300              16 :                      iPixelSize, iPixelSize * nWidth, GDT_Int16, bNativeOrder, TRUE );
     301                 : 
     302              16 :         poDS->SetBand(iBand, poBand);
     303                 : 
     304              16 :         switch ( iBand ) {
     305                 :         case 1:
     306               2 :            poBand->SetDescription("Elevation");
     307                 : 
     308               2 :            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4224);
     309               2 :            sprintf(szTemp, "%d", nTemp);
     310               2 :            poBand->SetMetadataItem( "ELEVATION_UNIT", szTemp );
     311                 : 
     312               2 :            if ( nTemp == 0 )
     313               2 :               poBand->SetMetadataItem( "ELEVATION_UNIT_NAME", "Meters" );
     314               2 :            if ( nTemp == 1 )
     315               0 :               poBand->SetMetadataItem( "ELEVATION_UNIT_NAME", "Feet" );
     316                 : 
     317               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 44);
     318               2 :            sprintf(szTemp, "%d", nTemp);
     319               2 :            poBand->SetMetadataItem( "ELEVATION_MIN", szTemp );
     320                 : 
     321               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 48);
     322               2 :            sprintf(szTemp, "%d", nTemp);
     323               2 :            poBand->SetMetadataItem( "ELEVATION_MAX", szTemp );
     324                 : 
     325               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 52);
     326               2 :            sprintf(szTemp, "%d", nTemp);
     327               2 :            poBand->SetMetadataItem( "ELEVATION_NUM_CLASSES", szTemp );
     328                 : 
     329               2 :            *(poDS->pachHeader + 4244 + 255) = '\0';
     330               2 :            poBand->SetMetadataItem( "ELEVATION_FILE", poDS->pachHeader + 4244 );
     331                 : 
     332               2 :            break;
     333                 : 
     334                 :         case 2:
     335               2 :            poBand->SetDescription("Slope");
     336                 : 
     337               2 :            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4226);
     338               2 :            sprintf(szTemp, "%d", nTemp);
     339               2 :            poBand->SetMetadataItem( "SLOPE_UNIT", szTemp );
     340                 : 
     341               2 :            if ( nTemp == 0 )
     342               2 :               poBand->SetMetadataItem( "SLOPE_UNIT_NAME", "Degrees" );
     343               2 :            if ( nTemp == 1 )
     344               0 :               poBand->SetMetadataItem( "SLOPE_UNIT_NAME", "Percent" );
     345                 : 
     346               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 456);
     347               2 :            sprintf(szTemp, "%d", nTemp);
     348               2 :            poBand->SetMetadataItem( "SLOPE_MIN", szTemp );
     349                 : 
     350               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 460);
     351               2 :            sprintf(szTemp, "%d", nTemp);
     352               2 :            poBand->SetMetadataItem( "SLOPE_MAX", szTemp );
     353                 : 
     354               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 464);
     355               2 :            sprintf(szTemp, "%d", nTemp);
     356               2 :            poBand->SetMetadataItem( "SLOPE_NUM_CLASSES", szTemp );
     357                 : 
     358               2 :            *(poDS->pachHeader + 4500 + 255) = '\0';
     359               2 :            poBand->SetMetadataItem( "SLOPE_FILE", poDS->pachHeader + 4500 );
     360                 : 
     361               2 :            break;
     362                 : 
     363                 :         case 3:
     364               2 :            poBand->SetDescription("Aspect");
     365                 : 
     366               2 :            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4228);
     367               2 :            sprintf(szTemp, "%d", nTemp);
     368               2 :            poBand->SetMetadataItem( "ASPECT_UNIT", szTemp );
     369                 : 
     370               2 :            if ( nTemp == 0 )
     371               0 :               poBand->SetMetadataItem( "ASPECT_UNIT_NAME", "Grass categories" );
     372               2 :            if ( nTemp == 1 )
     373               0 :               poBand->SetMetadataItem( "ASPECT_UNIT_NAME", "Grass degrees" );
     374               2 :            if ( nTemp == 2 )
     375               2 :               poBand->SetMetadataItem( "ASPECT_UNIT_NAME", "Azimuth degrees" );
     376                 : 
     377               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 868);
     378               2 :            sprintf(szTemp, "%d", nTemp);
     379               2 :            poBand->SetMetadataItem( "ASPECT_MIN", szTemp );
     380                 : 
     381               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 872);
     382               2 :            sprintf(szTemp, "%d", nTemp);
     383               2 :            poBand->SetMetadataItem( "ASPECT_MAX", szTemp );
     384                 : 
     385               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 876);
     386               2 :            sprintf(szTemp, "%d", nTemp);
     387               2 :            poBand->SetMetadataItem( "ASPECT_NUM_CLASSES", szTemp );
     388                 : 
     389               2 :            *(poDS->pachHeader + 4756 + 255) = '\0';
     390               2 :            poBand->SetMetadataItem( "ASPECT_FILE", poDS->pachHeader + 4756 );
     391                 : 
     392               2 :            break;
     393                 : 
     394                 :         case 4:
     395                 :            int nMinFM, nMaxFM;
     396                 : 
     397               2 :            poBand->SetDescription("Fuel models");
     398                 : 
     399               2 :            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4230);
     400               2 :            sprintf(szTemp, "%d", nTemp);
     401               2 :            poBand->SetMetadataItem( "FUEL_MODEL_OPTION", szTemp );
     402                 : 
     403               2 :            if ( nTemp == 0 )
     404               2 :               poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "no custom models AND no conversion file needed" );
     405               2 :            if ( nTemp == 1 )
     406               0 :               poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "custom models BUT no conversion file needed" );
     407               2 :            if ( nTemp == 2 )
     408               0 :               poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "no custom models BUT conversion file needed" );
     409               2 :            if ( nTemp == 3 )
     410               0 :               poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "custom models AND conversion file needed" );
     411                 : 
     412               2 :            nMinFM = CPL_LSBINT32PTR (poDS->pachHeader + 1280);
     413               2 :            sprintf(szTemp, "%d", nMinFM);
     414               2 :            poBand->SetMetadataItem( "FUEL_MODEL_MIN", szTemp );
     415                 : 
     416               2 :            nMaxFM = CPL_LSBINT32PTR (poDS->pachHeader + 1284);
     417               2 :            sprintf(szTemp, "%d", nMaxFM);
     418               2 :            poBand->SetMetadataItem( "FUEL_MODEL_MAX", szTemp );
     419                 : 
     420               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1288);
     421               2 :            sprintf(szTemp, "%d", nTemp);
     422               2 :            poBand->SetMetadataItem( "FUEL_MODEL_NUM_CLASSES", szTemp );
     423                 : 
     424               2 :            if (nTemp > 0 && nTemp <= 100) {
     425               2 :               strcpy(pszList, "");
     426              15 :               for ( i = 0; i <= nTemp; i++ ) {
     427              13 :                   nTemp2 = CPL_LSBINT32PTR (poDS->pachHeader + (1292+(i*4))) ;
     428              13 :                   if ( nTemp2 >= nMinFM && nTemp2 <= nMaxFM ) {
     429              11 :                      sprintf(szTemp, "%d", nTemp2);
     430              11 :                      strcat(pszList, szTemp);
     431              11 :                      if (i < (nTemp) )
     432               9 :                         strcat(pszList, ",");
     433                 :                   }
     434                 :               }
     435                 :            }
     436               2 :            poBand->SetMetadataItem( "FUEL_MODEL_VALUES", pszList );
     437                 : 
     438               2 :            *(poDS->pachHeader + 5012 + 255) = '\0';
     439               2 :            poBand->SetMetadataItem( "FUEL_MODEL_FILE", poDS->pachHeader + 5012 );
     440                 : 
     441               2 :            break;
     442                 : 
     443                 :         case 5:
     444               2 :            poBand->SetDescription("Canopy cover");
     445                 : 
     446               2 :            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4232);
     447               2 :            sprintf(szTemp, "%d", nTemp);
     448               2 :            poBand->SetMetadataItem( "CANOPY_COV_UNIT", szTemp );
     449                 : 
     450               2 :            if ( nTemp == 0 )
     451               1 :               poBand->SetMetadataItem( "CANOPY_COV_UNIT_NAME", "Categories (0-4)" );
     452               2 :            if ( nTemp == 1 )
     453               1 :               poBand->SetMetadataItem( "CANOPY_COV_UNIT_NAME", "Percent" );
     454                 : 
     455               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1692);
     456               2 :            sprintf(szTemp, "%d", nTemp);
     457               2 :            poBand->SetMetadataItem( "CANOPY_COV_MIN", szTemp );
     458                 : 
     459               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1696);
     460               2 :            sprintf(szTemp, "%d", nTemp);
     461               2 :            poBand->SetMetadataItem( "CANOPY_COV_MAX", szTemp );
     462                 : 
     463               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1700);
     464               2 :            sprintf(szTemp, "%d", nTemp);
     465               2 :            poBand->SetMetadataItem( "CANOPY_COV_NUM_CLASSES", szTemp );
     466                 : 
     467               2 :            *(poDS->pachHeader + 5268 + 255) = '\0';
     468               2 :            poBand->SetMetadataItem( "CANOPY_COV_FILE", poDS->pachHeader + 5268 );
     469                 : 
     470               2 :            break;
     471                 : 
     472                 :         case 6:
     473               2 :            if(bHaveCrownFuels) {
     474               2 :               poBand->SetDescription("Canopy height");
     475                 : 
     476               2 :               nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4234);
     477               2 :               sprintf(szTemp, "%d", nTemp);
     478               2 :               poBand->SetMetadataItem( "CANOPY_HT_UNIT", szTemp );
     479                 : 
     480               2 :               if ( nTemp == 1 )
     481               0 :                  poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Meters" );
     482               2 :               if ( nTemp == 2 )
     483               0 :                  poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Feet" );
     484               2 :               if ( nTemp == 3 )
     485               2 :                  poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Meters x 10" );
     486               2 :               if ( nTemp == 4 )
     487               0 :                  poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Feet x 10" );
     488                 : 
     489               2 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2104);
     490               2 :               sprintf(szTemp, "%d", nTemp);
     491               2 :               poBand->SetMetadataItem( "CANOPY_HT_MIN", szTemp );
     492                 : 
     493               2 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2108);
     494               2 :               sprintf(szTemp, "%d", nTemp);
     495               2 :               poBand->SetMetadataItem( "CANOPY_HT_MAX", szTemp );
     496                 : 
     497               2 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2112);
     498               2 :               sprintf(szTemp, "%d", nTemp);
     499               2 :               poBand->SetMetadataItem( "CANOPY_HT_NUM_CLASSES", szTemp );
     500                 : 
     501               2 :               *(poDS->pachHeader + 5524 + 255) = '\0';
     502               2 :               poBand->SetMetadataItem( "CANOPY_HT_FILE", poDS->pachHeader + 5524 );
     503                 :            }
     504                 :            else {
     505               0 :               poBand->SetDescription("Duff");
     506                 : 
     507               0 :               nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4240);
     508               0 :               sprintf(szTemp, "%d", nTemp);
     509               0 :               poBand->SetMetadataItem( "DUFF_UNIT", szTemp );
     510                 : 
     511               0 :               if ( nTemp == 1 )
     512               0 :                  poBand->SetMetadataItem( "DUFF_UNIT_NAME", "Mg/ha" );
     513               0 :               if ( nTemp == 2 )
     514               0 :                  poBand->SetMetadataItem( "DUFF_UNIT_NAME", "t/ac" );
     515                 : 
     516               0 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3340);
     517               0 :               sprintf(szTemp, "%d", nTemp);
     518               0 :               poBand->SetMetadataItem( "DUFF_MIN", szTemp );
     519                 : 
     520               0 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3344);
     521               0 :               sprintf(szTemp, "%d", nTemp);
     522               0 :               poBand->SetMetadataItem( "DUFF_MAX", szTemp );
     523                 : 
     524               0 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3348);
     525               0 :               sprintf(szTemp, "%d", nTemp);
     526               0 :               poBand->SetMetadataItem( "DUFF_NUM_CLASSES", szTemp );
     527                 : 
     528               0 :               *(poDS->pachHeader + 6292 + 255) = '\0';
     529               0 :               poBand->SetMetadataItem( "DUFF_FILE", poDS->pachHeader + 6292 );
     530                 :            }
     531               2 :            break;
     532                 : 
     533                 :         case 7:
     534               2 :            if(bHaveCrownFuels) {
     535               2 :               poBand->SetDescription("Canopy base height");
     536                 : 
     537               2 :               nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4236);
     538               2 :               sprintf(szTemp, "%d", nTemp);
     539               2 :               poBand->SetMetadataItem( "CBH_UNIT", szTemp );
     540                 : 
     541               2 :               if ( nTemp == 1 )
     542               0 :                  poBand->SetMetadataItem( "CBH_UNIT_NAME", "Meters" );
     543               2 :               if ( nTemp == 2 )
     544               0 :                  poBand->SetMetadataItem( "CBH_UNIT_NAME", "Feet" );
     545               2 :               if ( nTemp == 3 )
     546               2 :                  poBand->SetMetadataItem( "CBH_UNIT_NAME", "Meters x 10" );
     547               2 :               if ( nTemp == 4 )
     548               0 :                  poBand->SetMetadataItem( "CBH_UNIT_NAME", "Feet x 10" );
     549                 : 
     550               2 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2516);
     551               2 :               sprintf(szTemp, "%d", nTemp);
     552               2 :               poBand->SetMetadataItem( "CBH_MIN", szTemp );
     553                 : 
     554               2 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2520);
     555               2 :               sprintf(szTemp, "%d", nTemp);
     556               2 :               poBand->SetMetadataItem( "CBH_MAX", szTemp );
     557                 : 
     558               2 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2524);
     559               2 :               sprintf(szTemp, "%d", nTemp);
     560               2 :               poBand->SetMetadataItem( "CBH_NUM_CLASSES", szTemp );
     561                 : 
     562               2 :               *(poDS->pachHeader + 5780 + 255) = '\0';
     563               2 :               poBand->SetMetadataItem( "CBH_FILE", poDS->pachHeader + 5780 );
     564                 :            }
     565                 :            else {
     566               0 :               poBand->SetDescription("Coarse woody debris");
     567                 : 
     568               0 :               nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4242);
     569               0 :               sprintf(szTemp, "%d", nTemp);
     570               0 :               poBand->SetMetadataItem( "CWD_OPTION", szTemp );
     571                 : 
     572                 :               //if ( nTemp == 1 )
     573                 :               //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
     574                 :               //if ( nTemp == 2 )
     575                 :               //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
     576                 : 
     577               0 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3752);
     578               0 :               sprintf(szTemp, "%d", nTemp);
     579               0 :               poBand->SetMetadataItem( "CWD_MIN", szTemp );
     580                 : 
     581               0 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3756);
     582               0 :               sprintf(szTemp, "%d", nTemp);
     583               0 :               poBand->SetMetadataItem( "CWD_MAX", szTemp );
     584                 : 
     585               0 :               nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3760);
     586               0 :               sprintf(szTemp, "%d", nTemp);
     587               0 :               poBand->SetMetadataItem( "CWD_NUM_CLASSES", szTemp );
     588                 : 
     589               0 :               *(poDS->pachHeader + 6548 + 255) = '\0';
     590               0 :               poBand->SetMetadataItem( "CWD_FILE", poDS->pachHeader + 6548 );
     591                 :            }
     592               2 :            break;
     593                 : 
     594                 :         case 8:
     595               2 :            poBand->SetDescription("Canopy bulk density");
     596                 : 
     597               2 :            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4238);
     598               2 :            sprintf(szTemp, "%d", nTemp);
     599               2 :            poBand->SetMetadataItem( "CBD_UNIT", szTemp );
     600                 : 
     601               2 :            if ( nTemp == 1 )
     602               0 :               poBand->SetMetadataItem( "CBD_UNIT_NAME", "kg/m^3" );
     603               2 :            if ( nTemp == 2 )
     604               0 :               poBand->SetMetadataItem( "CBD_UNIT_NAME", "lb/ft^3" );
     605               2 :            if ( nTemp == 3 )
     606               2 :               poBand->SetMetadataItem( "CBD_UNIT_NAME", "kg/m^3 x 100" );
     607               2 :            if ( nTemp == 4 )
     608               0 :               poBand->SetMetadataItem( "CBD_UNIT_NAME", "lb/ft^3 x 1000" );
     609                 : 
     610               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2928);
     611               2 :            sprintf(szTemp, "%d", nTemp);
     612               2 :            poBand->SetMetadataItem( "CBD_MIN", szTemp );
     613                 : 
     614               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2932);
     615               2 :            sprintf(szTemp, "%d", nTemp);
     616               2 :            poBand->SetMetadataItem( "CBD_MAX", szTemp );
     617                 : 
     618               2 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2936);
     619               2 :            sprintf(szTemp, "%d", nTemp);
     620               2 :            poBand->SetMetadataItem( "CBD_NUM_CLASSES", szTemp );
     621                 : 
     622               2 :            *(poDS->pachHeader + 6036 + 255) = '\0';
     623               2 :            poBand->SetMetadataItem( "CBD_FILE", poDS->pachHeader + 6036 );
     624                 : 
     625               2 :            break;
     626                 : 
     627                 :         case 9:
     628               0 :            poBand->SetDescription("Duff");
     629                 : 
     630               0 :            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4240);
     631               0 :            sprintf(szTemp, "%d", nTemp);
     632               0 :            poBand->SetMetadataItem( "DUFF_UNIT", szTemp );
     633                 : 
     634               0 :            if ( nTemp == 1 )
     635               0 :               poBand->SetMetadataItem( "DUFF_UNIT_NAME", "Mg/ha" );
     636               0 :            if ( nTemp == 2 )
     637               0 :               poBand->SetMetadataItem( "DUFF_UNIT_NAME", "t/ac" );
     638                 : 
     639               0 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3340);
     640               0 :            sprintf(szTemp, "%d", nTemp);
     641               0 :            poBand->SetMetadataItem( "DUFF_MIN", szTemp );
     642                 : 
     643               0 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3344);
     644               0 :            sprintf(szTemp, "%d", nTemp);
     645               0 :            poBand->SetMetadataItem( "DUFF_MAX", szTemp );
     646                 : 
     647               0 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3348);
     648               0 :            sprintf(szTemp, "%d", nTemp);
     649               0 :            poBand->SetMetadataItem( "DUFF_NUM_CLASSES", szTemp );
     650                 : 
     651               0 :            *(poDS->pachHeader + 6292 + 255) = '\0';
     652               0 :            poBand->SetMetadataItem( "DUFF_FILE", poDS->pachHeader + 6292 );
     653                 : 
     654               0 :            break;
     655                 : 
     656                 :         case 10:
     657               0 :            poBand->SetDescription("Coarse woody debris");
     658                 : 
     659               0 :            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4242);
     660               0 :            sprintf(szTemp, "%d", nTemp);
     661               0 :            poBand->SetMetadataItem( "CWD_OPTION", szTemp );
     662                 : 
     663                 :            //if ( nTemp == 1 )
     664                 :            //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
     665                 :            //if ( nTemp == 2 )
     666                 :            //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
     667                 : 
     668               0 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3752);
     669               0 :            sprintf(szTemp, "%d", nTemp);
     670               0 :            poBand->SetMetadataItem( "CWD_MIN", szTemp );
     671                 : 
     672               0 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3756);
     673               0 :            sprintf(szTemp, "%d", nTemp);
     674               0 :            poBand->SetMetadataItem( "CWD_MAX", szTemp );
     675                 : 
     676               0 :            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3760);
     677               0 :            sprintf(szTemp, "%d", nTemp);
     678               0 :            poBand->SetMetadataItem( "CWD_NUM_CLASSES", szTemp );
     679                 : 
     680               0 :            *(poDS->pachHeader + 6548 + 255) = '\0';
     681               0 :            poBand->SetMetadataItem( "CWD_FILE", poDS->pachHeader + 6548 );
     682                 : 
     683                 :            break;
     684                 :         }
     685                 :    }
     686                 :    
     687                 : /* -------------------------------------------------------------------- */
     688                 : /*      Try to read projection file.                                    */
     689                 : /* -------------------------------------------------------------------- */
     690                 :     char        *pszDirname, *pszBasename;
     691                 :     VSIStatBufL   sStatBuf;
     692                 : 
     693               2 :     pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     694               2 :     pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
     695                 : 
     696               2 :     poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
     697               2 :     int nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
     698                 : 
     699               3 :     if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename))
     700                 :     {
     701               1 :         poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "PRJ" );
     702               1 :         nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
     703                 :     }
     704                 : 
     705               2 :     if( nRet == 0 )
     706                 :     {
     707               1 :         OGRSpatialReference     oSRS;
     708                 : 
     709               1 :         char** papszPrj = CSLLoad( poDS->osPrjFilename );
     710                 : 
     711                 :         CPLDebug( "LCP", "Loaded SRS from %s", 
     712               1 :                   poDS->osPrjFilename.c_str() );
     713                 : 
     714               1 :         if( oSRS.importFromESRI( papszPrj ) == OGRERR_NONE )
     715                 :         {
     716               1 :             oSRS.exportToWkt( &(poDS->pszProjection) );
     717                 :         }
     718                 :         
     719               1 :         CSLDestroy(papszPrj);
     720                 :     }
     721                 : 
     722               2 :     CPLFree( pszDirname );
     723               2 :     CPLFree( pszBasename );
     724                 : 
     725                 : /* -------------------------------------------------------------------- */
     726                 : /*      Initialize any PAM information.                                 */
     727                 : /* -------------------------------------------------------------------- */
     728               2 :     poDS->SetDescription( poOpenInfo->pszFilename );
     729               2 :     poDS->TryLoadXML();
     730                 : 
     731                 : /* -------------------------------------------------------------------- */
     732                 : /*      Check for external overviews.                                   */
     733                 : /* -------------------------------------------------------------------- */
     734               2 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
     735                 : 
     736               2 :     CPLFree(pszList);
     737                 : 
     738               2 :     return( poDS );
     739                 : }
     740                 :  
     741                 : /************************************************************************/
     742                 : /*                          GetProjectionRef()                          */
     743                 : /************************************************************************/
     744                 :  
     745               1 : const char *LCPDataset::GetProjectionRef()
     746                 : 
     747                 : {
     748               1 :     return pszProjection;
     749                 : }
     750                 : 
     751                 : /************************************************************************/
     752                 : /*                         GDALRegister_LCP()                           */
     753                 : /************************************************************************/
     754                 : 
     755             582 : void GDALRegister_LCP()
     756                 : 
     757                 : {
     758                 :     GDALDriver  *poDriver;
     759                 : 
     760             582 :     if( GDALGetDriverByName( "LCP" ) == NULL )
     761                 :     {
     762             561 :         poDriver = new GDALDriver();
     763                 : 
     764             561 :         poDriver->SetDescription( "LCP" );
     765                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     766             561 :                                    "FARSITE v.4 Landscape File (.lcp)" );
     767             561 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "lcp" );
     768                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     769             561 :                                    "frmt_lcp.html" );
     770                 : 
     771             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     772                 : 
     773             561 :         poDriver->pfnOpen = LCPDataset::Open;
     774             561 :         poDriver->pfnIdentify = LCPDataset::Identify;
     775                 : 
     776             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     777                 :     }
     778             582 : }

Generated by: LCOV version 1.7