LCOV - code coverage report
Current view: directory - frmts/raw - lcpdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 383 277 72.3 %
Date: 2010-01-09 Functions: 9 8 88.9 %

       1                 : /******************************************************************************

       2                 :  * $Id: lcpdataset.cpp 18125 2009-11-28 11:07:24Z 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 18125 2009-11-28 11:07:24Z 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                 :     FILE    *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               4 : LCPDataset::~LCPDataset()

      85                 : 
      86                 : {
      87               2 :     FlushCache();

      88               2 :     if( fpImage != NULL )

      89               2 :         VSIFCloseL( fpImage );

      90               2 :     CPLFree(pszProjection);

      91               4 : }

      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            8493 : int LCPDataset::Identify( GDALOpenInfo * poOpenInfo )

     130                 : 
     131                 : {
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      Verify that this is a FARSITE v.4 LCP file                      */
     134                 : /* -------------------------------------------------------------------- */
     135            8493 :     if( poOpenInfo->nHeaderBytes < 50 )

     136            8297 :         return FALSE;

     137                 : 
     138                 :     /* check if first three fields have valid data */
     139             196 :     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             194 :         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             766 : GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )

     172                 : 
     173                 : {
     174                 : /* -------------------------------------------------------------------- */
     175                 : /*      Verify that this is a FARSITE LCP file    */
     176                 : /* -------------------------------------------------------------------- */
     177             766 :     if( !Identify( poOpenInfo ) )

     178             764 :         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                 :     FILE        *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                 : #ifndef WIN32
     700               2 :     if( nRet != 0 )

     701                 :     {
     702               1 :         poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "PRJ" );

     703               1 :         nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );

     704                 :     }
     705                 : #endif
     706                 : 
     707               2 :     if( nRet == 0 )

     708                 :     {
     709               1 :         OGRSpatialReference     oSRS;

     710                 : 
     711               1 :         char** papszPrj = CSLLoad( poDS->osPrjFilename );

     712                 : 
     713                 :         CPLDebug( "LCP", "Loaded SRS from %s", 
     714               1 :                   poDS->osPrjFilename.c_str() );

     715                 : 
     716               1 :         if( oSRS.importFromESRI( papszPrj ) == OGRERR_NONE )

     717                 :         {
     718               1 :             oSRS.exportToWkt( &(poDS->pszProjection) );

     719                 :         }
     720                 :         
     721               1 :         CSLDestroy(papszPrj);

     722                 :     }
     723                 : 
     724               2 :     CPLFree( pszDirname );

     725               2 :     CPLFree( pszBasename );

     726                 : 
     727                 : /* -------------------------------------------------------------------- */
     728                 : /*      Initialize any PAM information.                                 */
     729                 : /* -------------------------------------------------------------------- */
     730               2 :     poDS->SetDescription( poOpenInfo->pszFilename );

     731               2 :     poDS->TryLoadXML();

     732                 : 
     733               2 :     CPLFree(pszList);

     734                 : 
     735               2 :     return( poDS );

     736                 : }
     737                 :  
     738                 : /************************************************************************/
     739                 : /*                          GetProjectionRef()                          */
     740                 : /************************************************************************/

     741                 :  
     742               1 : const char *LCPDataset::GetProjectionRef()

     743                 : 
     744                 : {
     745               1 :     return pszProjection;

     746                 : }
     747                 : 
     748                 : /************************************************************************/
     749                 : /*                         GDALRegister_LCP()                           */
     750                 : /************************************************************************/

     751                 : 
     752             338 : void GDALRegister_LCP()

     753                 : 
     754                 : {
     755                 :     GDALDriver  *poDriver;
     756                 : 
     757             338 :     if( GDALGetDriverByName( "LCP" ) == NULL )

     758                 :     {
     759             336 :         poDriver = new GDALDriver();

     760                 : 
     761             336 :         poDriver->SetDescription( "LCP" );

     762                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     763             336 :                                    "FARSITE v.4 Landscape File (.lcp)" );

     764             336 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "lcp" );

     765                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     766             336 :                                    "frmt_lcp.html" );

     767                 : 
     768             336 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );

     769                 : 
     770             336 :         poDriver->pfnOpen = LCPDataset::Open;

     771             336 :         poDriver->pfnIdentify = LCPDataset::Identify;

     772                 : 
     773             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );

     774                 :     }
     775             338 : }


Generated by: LCOV version 1.7