EVOLUTION-MANAGER
Edit File: sdtsdataset.cpp
/****************************************************************************** * * Project: SDTS Translator * Purpose: GDALDataset driver for SDTS Raster translator. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1999, Frank Warmerdam * Copyright (c) 2008-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 "gdal_frmts.h" #include "gdal_pam.h" #include "ogr_spatialref.h" #include "sdts_al.h" CPL_CVSID("$Id: sdtsdataset.cpp 36501 2016-11-25 14:09:24Z rouault $"); /** \file sdtsdataset.cpp exclude */ /************************************************************************/ /* ==================================================================== */ /* SDTSDataset */ /* ==================================================================== */ /************************************************************************/ class SDTSRasterBand; class SDTSDataset : public GDALPamDataset { friend class SDTSRasterBand; SDTSTransfer *poTransfer; SDTSRasterReader *poRL; char *pszProjection; public: SDTSDataset(); virtual ~SDTSDataset(); static GDALDataset *Open( GDALOpenInfo * ); virtual const char *GetProjectionRef(void) override; virtual CPLErr GetGeoTransform( double * ) override; }; class SDTSRasterBand : public GDALPamRasterBand { friend class SDTSDataset; SDTSRasterReader *poRL; public: SDTSRasterBand( SDTSDataset *, int, SDTSRasterReader * ); virtual CPLErr IReadBlock( int, int, void * ) override; virtual double GetNoDataValue( int *pbSuccess ) override; virtual const char *GetUnitType() override; }; /************************************************************************/ /* SDTSDataset() */ /************************************************************************/ SDTSDataset::SDTSDataset() : poTransfer( NULL ), poRL( NULL ), pszProjection( NULL ) { } /************************************************************************/ /* ~SDTSDataset() */ /************************************************************************/ SDTSDataset::~SDTSDataset() { FlushCache(); if( poTransfer != NULL ) delete poTransfer; if( poRL != NULL ) delete poRL; CPLFree( pszProjection ); } /************************************************************************/ /* Open() */ /************************************************************************/ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Before trying SDTSOpen() we first verify that the first */ /* record is in fact a SDTS file descriptor record. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->nHeaderBytes < 24 ) return NULL; char *pachLeader = reinterpret_cast<char *>( poOpenInfo->pabyHeader ); if( pachLeader[5] != '1' && pachLeader[5] != '2' && pachLeader[5] != '3' ) return NULL; if( pachLeader[6] != 'L' ) return NULL; if( pachLeader[8] != '1' && pachLeader[8] != ' ' ) return NULL; /* -------------------------------------------------------------------- */ /* Try opening the dataset. */ /* -------------------------------------------------------------------- */ SDTSTransfer *poTransfer = new SDTSTransfer; if( !poTransfer->Open( poOpenInfo->pszFilename ) ) { delete poTransfer; return NULL; } /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { delete poTransfer; CPLError( CE_Failure, CPLE_NotSupported, "The SDTS driver does not support update access to existing" " datasets.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Find the first raster layer. If there are none, abort */ /* returning an error. */ /* -------------------------------------------------------------------- */ SDTSRasterReader *poRL = NULL; for( int i = 0; i < poTransfer->GetLayerCount(); i++ ) { if( poTransfer->GetLayerType( i ) == SLTRaster ) { poRL = poTransfer->GetLayerRasterReader( i ); break; } } if( poRL == NULL ) { delete poTransfer; CPLError( CE_Warning, CPLE_AppDefined, "%s is an SDTS transfer, but has no raster cell layers.\n" "Perhaps it is a vector transfer?\n", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Initialize a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ SDTSDataset *poDS = new SDTSDataset(); poDS->poTransfer = poTransfer; poDS->poRL = poRL; /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = poRL->GetXSize(); poDS->nRasterYSize = poRL->GetYSize(); /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ poDS->nBands = 1; poDS->papoBands = reinterpret_cast<GDALRasterBand **>( VSICalloc( sizeof(GDALRasterBand *), poDS->nBands ) ); for( int i = 0; i < poDS->nBands; i++ ) poDS->SetBand( i+1, new SDTSRasterBand( poDS, i+1, poRL ) ); /* -------------------------------------------------------------------- */ /* Try to establish the projection string. For now we only */ /* support UTM and GEO. */ /* -------------------------------------------------------------------- */ OGRSpatialReference oSRS; SDTS_XREF *poXREF = poTransfer->GetXREF(); if( EQUAL(poXREF->pszSystemName,"UTM") ) { oSRS.SetUTM( poXREF->nZone ); } else if( EQUAL(poXREF->pszSystemName,"GEO") ) { /* we set datum later */ } else oSRS.SetLocalCS( poXREF->pszSystemName ); if( oSRS.IsLocal() ) /* don't try to set datum. */; else if( EQUAL(poXREF->pszDatum,"NAS") ) oSRS.SetWellKnownGeogCS( "NAD27" ); else if( EQUAL(poXREF->pszDatum, "NAX") ) oSRS.SetWellKnownGeogCS( "NAD83" ); else if( EQUAL(poXREF->pszDatum, "WGC") ) oSRS.SetWellKnownGeogCS( "WGS72" ); else /* if( EQUAL(poXREF->pszDatum, "WGE") ) or default */ oSRS.SetWellKnownGeogCS( "WGS84" ); oSRS.Fixup(); poDS->pszProjection = NULL; if( oSRS.exportToWkt( &poDS->pszProjection ) != OGRERR_NONE ) poDS->pszProjection = CPLStrdup(""); /* -------------------------------------------------------------------- */ /* Get metadata from the IDEN file. */ /* -------------------------------------------------------------------- */ const char* pszIDENFilePath = poTransfer->GetCATD()->GetModuleFilePath("IDEN"); if (pszIDENFilePath) { DDFModule oIDENFile; if( oIDENFile.Open( pszIDENFilePath ) ) { DDFRecord* poRecord = NULL; while( (poRecord = oIDENFile.ReadRecord()) != NULL ) { if( poRecord->GetStringSubfield( "IDEN", 0, "MODN", 0 ) == NULL ) continue; static const char* const fields[][2] = { { "TITL", "TITLE" }, { "DAID", "DATASET_ID" }, { "DAST", "DATA_STRUCTURE" }, { "MPDT", "MAP_DATE" }, { "DCDT", "DATASET_CREATION_DATE" } }; for ( int i = 0; i < static_cast<int>( sizeof(fields) ) / static_cast<int>( sizeof(fields[0] ) ); i++) { const char* pszFieldValue = poRecord->GetStringSubfield( "IDEN", 0, fields[i][0], 0 ); if ( pszFieldValue ) poDS->SetMetadataItem(fields[i][1], pszFieldValue); } break; } } } /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for external overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() ); return poDS; } /************************************************************************/ /* GetGeoTransform() */ /************************************************************************/ CPLErr SDTSDataset::GetGeoTransform( double * padfTransform ) { if( poRL->GetTransform( padfTransform ) ) return CE_None; return CE_Failure; } /************************************************************************/ /* GetProjectionRef() */ /************************************************************************/ const char *SDTSDataset::GetProjectionRef() { return pszProjection; } /************************************************************************/ /* ==================================================================== */ /* SDTSRasterBand */ /* ==================================================================== */ /************************************************************************/ /************************************************************************/ /* SDTSRasterBand() */ /************************************************************************/ SDTSRasterBand::SDTSRasterBand( SDTSDataset *poDSIn, int nBandIn, SDTSRasterReader * poRLIn ) : poRL(poRLIn) { poDS = poDSIn; nBand = nBandIn; if( poRL->GetRasterType() == SDTS_RT_INT16 ) eDataType = GDT_Int16; else eDataType = GDT_Float32; nBlockXSize = poRL->GetBlockXSize(); nBlockYSize = poRL->GetBlockYSize(); } /************************************************************************/ /* IReadBlock() */ /************************************************************************/ CPLErr SDTSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage ) { if( poRL->GetBlock( nBlockXOff, nBlockYOff, pImage ) ) return CE_None; return CE_Failure; } /************************************************************************/ /* GetNoDataValue() */ /************************************************************************/ double SDTSRasterBand::GetNoDataValue( int *pbSuccess ) { if( pbSuccess != NULL ) *pbSuccess = TRUE; return -32766.0; } /************************************************************************/ /* GetUnitType() */ /************************************************************************/ const char *SDTSRasterBand::GetUnitType() { if( EQUAL(poRL->szUNITS,"FEET") ) return "ft"; else if( STARTS_WITH_CI(poRL->szUNITS, "MET") ) return "m"; return poRL->szUNITS; } /************************************************************************/ /* GDALRegister_SDTS() */ /************************************************************************/ void GDALRegister_SDTS() { if( GDALGetDriverByName( "SDTS" ) != NULL ) return; GDALDriver *poDriver = new GDALDriver(); poDriver->SetDescription( "SDTS" ); poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" ); poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SDTS Raster" ); poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#SDTS" ); poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ddf" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); poDriver->pfnOpen = SDTSDataset::Open; GetGDALDriverManager()->RegisterDriver( poDriver ); }