ultimatepp/bazaar/plugin/gdal/frmts/raw/snodasdataset.cpp
cxl 23ff1e7e82 .gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-12-07 13:36:24 +00:00

517 lines
19 KiB
C++

/******************************************************************************
* $Id: snodasdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
*
* Project: SNODAS driver
* Purpose: Implementation of SNODASDataset
* Author: Even Rouault, <even dot rouault at mines dash paris dot org>
*
******************************************************************************
* Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
#include "rawdataset.h"
#include "ogr_srs_api.h"
#include "cpl_string.h"
CPL_CVSID("$Id: snodasdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
// g++ -g -Wall -fPIC frmts/raw/snodasdataset.cpp -shared -o gdal_SNODAS.so -Iport -Igcore -Ifrmts/raw -Iogr -L. -lgdal
CPL_C_START
void GDALRegister_SNODAS(void);
CPL_C_END
/************************************************************************/
/* ==================================================================== */
/* SNODASDataset */
/* ==================================================================== */
/************************************************************************/
class SNODASRasterBand;
class SNODASDataset : public RawDataset
{
CPLString osDataFilename;
int bGotTransform;
double adfGeoTransform[6];
int bHasNoData;
double dfNoData;
int bHasMin;
double dfMin;
int bHasMax;
double dfMax;
friend class SNODASRasterBand;
public:
SNODASDataset();
~SNODASDataset();
virtual CPLErr GetGeoTransform( double * padfTransform );
virtual const char *GetProjectionRef(void);
virtual char **GetFileList();
static GDALDataset *Open( GDALOpenInfo * );
static int Identify( GDALOpenInfo * );
};
/************************************************************************/
/* ==================================================================== */
/* SNODASRasterBand */
/* ==================================================================== */
/************************************************************************/
class SNODASRasterBand : public RawRasterBand
{
public:
SNODASRasterBand(VSILFILE* fpRaw, int nXSize, int nYSize);
virtual double GetNoDataValue( int *pbSuccess = NULL );
virtual double GetMinimum( int *pbSuccess = NULL );
virtual double GetMaximum(int *pbSuccess = NULL );
};
/************************************************************************/
/* SNODASRasterBand() */
/************************************************************************/
SNODASRasterBand::SNODASRasterBand(VSILFILE* fpRaw,
int nXSize, int nYSize) :
RawRasterBand( fpRaw, 0, 2,
nXSize * 2, GDT_Int16,
!CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE)
{
}
/************************************************************************/
/* GetNoDataValue() */
/************************************************************************/
double SNODASRasterBand::GetNoDataValue( int *pbSuccess )
{
SNODASDataset* poGDS = (SNODASDataset*) poDS;
if (pbSuccess)
*pbSuccess = poGDS->bHasNoData;
if (poGDS->bHasNoData)
return poGDS->dfNoData;
else
return RawRasterBand::GetNoDataValue(pbSuccess);
}
/************************************************************************/
/* GetMinimum() */
/************************************************************************/
double SNODASRasterBand::GetMinimum( int *pbSuccess )
{
SNODASDataset* poGDS = (SNODASDataset*) poDS;
if (pbSuccess)
*pbSuccess = poGDS->bHasMin;
if (poGDS->bHasMin)
return poGDS->dfMin;
else
return RawRasterBand::GetMinimum(pbSuccess);
}
/************************************************************************/
/* GetMaximum() */
/************************************************************************/
double SNODASRasterBand::GetMaximum( int *pbSuccess )
{
SNODASDataset* poGDS = (SNODASDataset*) poDS;
if (pbSuccess)
*pbSuccess = poGDS->bHasMax;
if (poGDS->bHasMax)
return poGDS->dfMax;
else
return RawRasterBand::GetMaximum(pbSuccess);
}
/************************************************************************/
/* ==================================================================== */
/* SNODASDataset */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* SNODASDataset() */
/************************************************************************/
SNODASDataset::SNODASDataset()
{
bGotTransform = FALSE;
adfGeoTransform[0] = 0.0;
adfGeoTransform[1] = 1.0;
adfGeoTransform[2] = 0.0;
adfGeoTransform[3] = 0.0;
adfGeoTransform[4] = 0.0;
adfGeoTransform[5] = 1.0;
bHasNoData = FALSE;
dfNoData = 0.0;
bHasMin = FALSE;
dfMin = 0.0;
bHasMax = FALSE;
dfMax = 0.0;
}
/************************************************************************/
/* ~SNODASDataset() */
/************************************************************************/
SNODASDataset::~SNODASDataset()
{
FlushCache();
}
/************************************************************************/
/* GetProjectionRef() */
/************************************************************************/
const char *SNODASDataset::GetProjectionRef()
{
return SRS_WKT_WGS84;
}
/************************************************************************/
/* GetGeoTransform() */
/************************************************************************/
CPLErr SNODASDataset::GetGeoTransform( double * padfTransform )
{
if( bGotTransform )
{
memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
return CE_None;
}
else
{
return GDALPamDataset::GetGeoTransform( padfTransform );
}
}
/************************************************************************/
/* GetFileList() */
/************************************************************************/
char **SNODASDataset::GetFileList()
{
char **papszFileList = GDALPamDataset::GetFileList();
papszFileList = CSLAddString(papszFileList, osDataFilename);
return papszFileList;
}
/************************************************************************/
/* Identify() */
/************************************************************************/
int SNODASDataset::Identify( GDALOpenInfo * poOpenInfo )
{
if (poOpenInfo->nHeaderBytes == 0)
return FALSE;
return EQUALN((const char*)poOpenInfo->pabyHeader,
"Format version: NOHRSC GIS/RS raster file v1.1",
strlen("Format version: NOHRSC GIS/RS raster file v1.1"));
}
/************************************************************************/
/* Open() */
/************************************************************************/
GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
{
if( !Identify(poOpenInfo) )
return NULL;
VSILFILE *fp;
fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
if( fp == NULL )
{
return NULL;
}
const char * pszLine;
int nRows = -1, nCols = -1;
CPLString osDataFilename;
int bIsInteger = FALSE, bIs2Bytes = FALSE;
double dfNoData = 0;
int bHasNoData = FALSE;
double dfMin = 0;
int bHasMin = FALSE;
double dfMax = 0;
int bHasMax = FALSE;
double dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
int bHasMinX = FALSE, bHasMinY = FALSE, bHasMaxX = FALSE, bHasMaxY = FALSE;
int bNotProjected = FALSE, bIsWGS84 = FALSE;
CPLString osDescription, osDataUnits;
int nStartYear = -1, nStartMonth = -1, nStartDay = -1,
nStartHour = -1, nStartMinute = -1, nStartSecond = -1;
int nStopYear = -1, nStopMonth = -1, nStopDay = -1,
nStopHour = -1, nStopMinute = -1, nStopSecond = -1;
while( (pszLine = CPLReadLine2L( fp, 256, NULL )) != NULL )
{
char** papszTokens = CSLTokenizeStringComplex( pszLine, ":", TRUE, FALSE );
if( CSLCount( papszTokens ) != 2 )
{
CSLDestroy( papszTokens );
continue;
}
if( papszTokens[1][0] == ' ' )
memmove(papszTokens[1], papszTokens[1] + 1, strlen(papszTokens[1] + 1) + 1);
if( EQUAL(papszTokens[0],"Data file pathname") )
{
osDataFilename = papszTokens[1];
}
else if( EQUAL(papszTokens[0],"Description") )
{
osDescription = papszTokens[1];
}
else if( EQUAL(papszTokens[0],"Data units") )
{
osDataUnits= papszTokens[1];
}
else if( EQUAL(papszTokens[0],"Start year") )
nStartYear = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Start month") )
nStartMonth = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Start day") )
nStartDay = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Start hour") )
nStartHour = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Start minute") )
nStartMinute = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Start second") )
nStartSecond = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Stop year") )
nStopYear = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Stop month") )
nStopMonth = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Stop day") )
nStopDay = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Stop hour") )
nStopHour = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Stop minute") )
nStopMinute = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Stop second") )
nStopSecond = atoi(papszTokens[1]);
else if( EQUAL(papszTokens[0],"Number of columns") )
{
nCols = atoi(papszTokens[1]);
}
else if( EQUAL(papszTokens[0],"Number of rows") )
{
nRows = atoi(papszTokens[1]);
}
else if( EQUAL(papszTokens[0],"Data type"))
{
bIsInteger = EQUAL(papszTokens[1],"integer");
}
else if( EQUAL(papszTokens[0],"Data bytes per pixel"))
{
bIs2Bytes = EQUAL(papszTokens[1],"2");
}
else if( EQUAL(papszTokens[0],"Projected"))
{
bNotProjected = EQUAL(papszTokens[1],"no");
}
else if( EQUAL(papszTokens[0],"Horizontal datum"))
{
bIsWGS84 = EQUAL(papszTokens[1],"WGS84");
}
else if( EQUAL(papszTokens[0],"No data value"))
{
bHasNoData = TRUE;
dfNoData = CPLAtofM(papszTokens[1]);
}
else if( EQUAL(papszTokens[0],"Minimum data value"))
{
bHasMin = TRUE;
dfMin = CPLAtofM(papszTokens[1]);
}
else if( EQUAL(papszTokens[0],"Maximum data value"))
{
bHasMax = TRUE;
dfMax = CPLAtofM(papszTokens[1]);
}
else if( EQUAL(papszTokens[0],"Minimum x-axis coordinate") )
{
bHasMinX = TRUE;
dfMinX = CPLAtofM(papszTokens[1]);
}
else if( EQUAL(papszTokens[0],"Minimum y-axis coordinate") )
{
bHasMinY = TRUE;
dfMinY = CPLAtofM(papszTokens[1]);
}
else if( EQUAL(papszTokens[0],"Maximum x-axis coordinate") )
{
bHasMaxX = TRUE;
dfMaxX = CPLAtofM(papszTokens[1]);
}
else if( EQUAL(papszTokens[0],"Maximum y-axis coordinate") )
{
bHasMaxY = TRUE;
dfMaxY = CPLAtofM(papszTokens[1]);
}
CSLDestroy( papszTokens );
}
VSIFCloseL( fp );
/* -------------------------------------------------------------------- */
/* Did we get the required keywords? If not we return with */
/* this never having been considered to be a match. This isn't */
/* an error! */
/* -------------------------------------------------------------------- */
if( nRows == -1 || nCols == -1 || !bIsInteger || !bIs2Bytes )
return NULL;
if( !bNotProjected || !bIsWGS84 )
return NULL;
if( osDataFilename.size() == 0 )
return NULL;
if (!GDALCheckDatasetDimensions(nCols, nRows))
return NULL;
/* -------------------------------------------------------------------- */
/* Open target binary file. */
/* -------------------------------------------------------------------- */
const char* pszPath = CPLGetPath(poOpenInfo->pszFilename);
osDataFilename = CPLFormFilename(pszPath, osDataFilename, NULL);
VSILFILE* fpRaw = VSIFOpenL( osDataFilename, "rb" );
if( fpRaw == NULL )
return NULL;
/* -------------------------------------------------------------------- */
/* Create a corresponding GDALDataset. */
/* -------------------------------------------------------------------- */
SNODASDataset *poDS;
poDS = new SNODASDataset();
poDS->nRasterXSize = nCols;
poDS->nRasterYSize = nRows;
poDS->osDataFilename = osDataFilename;
poDS->bHasNoData = bHasNoData;
poDS->dfNoData = dfNoData;
poDS->bHasMin = bHasMin;
poDS->dfMin = dfMin;
poDS->bHasMax = bHasMax;
poDS->dfMax = dfMax;
if (bHasMinX && bHasMinY && bHasMaxX && bHasMaxY)
{
poDS->bGotTransform = TRUE;
poDS->adfGeoTransform[0] = dfMinX;
poDS->adfGeoTransform[1] = (dfMaxX - dfMinX) / nCols;
poDS->adfGeoTransform[2] = 0.0;
poDS->adfGeoTransform[3] = dfMaxY;
poDS->adfGeoTransform[4] = 0.0;
poDS->adfGeoTransform[5] = - (dfMaxY - dfMinY) / nRows;
}
if (osDescription.size())
poDS->SetMetadataItem("Description", osDescription);
if (osDataUnits.size())
poDS->SetMetadataItem("Data_Units", osDataUnits);
if (nStartYear != -1 && nStartMonth != -1 && nStartDay != -1 &&
nStartHour != -1 && nStartMinute != -1 && nStartSecond != -1)
poDS->SetMetadataItem("Start_Date",
CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
nStartYear, nStartMonth, nStartDay,
nStartHour, nStartMinute, nStartSecond));
if (nStopYear != -1 && nStopMonth != -1 && nStopDay != -1 &&
nStopHour != -1 && nStopMinute != -1 && nStopSecond != -1)
poDS->SetMetadataItem("Stop_Date",
CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
nStopYear, nStopMonth, nStopDay,
nStopHour, nStopMinute, nStopSecond));
/* -------------------------------------------------------------------- */
/* Create band information objects. */
/* -------------------------------------------------------------------- */
poDS->SetBand( 1, new SNODASRasterBand( fpRaw, nCols, nRows) );
/* -------------------------------------------------------------------- */
/* Initialize any PAM information. */
/* -------------------------------------------------------------------- */
poDS->SetDescription( poOpenInfo->pszFilename );
poDS->TryLoadXML();
/* -------------------------------------------------------------------- */
/* Check for overviews. */
/* -------------------------------------------------------------------- */
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
return( poDS );
}
/************************************************************************/
/* GDALRegister_SNODAS() */
/************************************************************************/
void GDALRegister_SNODAS()
{
GDALDriver *poDriver;
if( GDALGetDriverByName( "SNODAS" ) == NULL )
{
poDriver = new GDALDriver();
poDriver->SetDescription( "SNODAS" );
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
"Snow Data Assimilation System" );
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
"frmt_various.html#SNODAS" );
poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdr" );
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
poDriver->pfnOpen = SNODASDataset::Open;
poDriver->pfnIdentify = SNODASDataset::Identify;
GetGDALDriverManager()->RegisterDriver( poDriver );
}
}