bool LevellerDataset::make_local_coordsys(const char* pszName, const char* pszUnits) { OGRSpatialReference sr; sr.SetLocalCS(pszName); double d; return ( this->convert_measure(1.0, d, pszUnits) && OGRERR_NONE == sr.SetLinearUnits(pszUnits, d) && OGRERR_NONE == sr.exportToWkt(&m_pszProjection) ); }
GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Verify that this is some form of binterr file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->nHeaderBytes < 256) return NULL; if( !STARTS_WITH((const char *) poOpenInfo->pabyHeader, "binterr") ) return NULL; /* -------------------------------------------------------------------- */ /* Create the dataset. */ /* -------------------------------------------------------------------- */ BTDataset *poDS = new BTDataset(); memcpy( poDS->abyHeader, poOpenInfo->pabyHeader, 256 ); /* -------------------------------------------------------------------- */ /* Get the version. */ /* -------------------------------------------------------------------- */ char szVersion[4] = {}; strncpy( szVersion, (char *) (poDS->abyHeader + 7), 3 ); szVersion[3] = '\0'; poDS->nVersionCode = static_cast<int>(CPLAtof(szVersion) * 10); /* -------------------------------------------------------------------- */ /* Extract core header information, being careful about the */ /* version. */ /* -------------------------------------------------------------------- */ GInt32 nIntTemp = 0; memcpy( &nIntTemp, poDS->abyHeader + 10, 4 ); poDS->nRasterXSize = CPL_LSBWORD32( nIntTemp ); memcpy( &nIntTemp, poDS->abyHeader + 14, 4 ); poDS->nRasterYSize = CPL_LSBWORD32( nIntTemp ); if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ) { delete poDS; return NULL; } GInt16 nDataSize = 0; memcpy( &nDataSize, poDS->abyHeader+18, 2 ); nDataSize = CPL_LSBWORD16( nDataSize ); GDALDataType eType = GDT_Unknown; if( poDS->abyHeader[20] != 0 && nDataSize == 4 ) eType = GDT_Float32; else if( poDS->abyHeader[20] == 0 && nDataSize == 4 ) eType = GDT_Int32; else if( poDS->abyHeader[20] == 0 && nDataSize == 2 ) eType = GDT_Int16; else { CPLError( CE_Failure, CPLE_AppDefined, ".bt file data type unknown, got datasize=%d.", nDataSize ); delete poDS; return NULL; } /* rcg, apr 7/06: read offset 62 for vert. units. If zero, assume 1.0 as per spec. */ memcpy( &poDS->m_fVscale, poDS->abyHeader + 62, 4 ); CPL_LSBPTR32(&poDS->m_fVscale); if(poDS->m_fVscale == 0.0f) poDS->m_fVscale = 1.0f; /* -------------------------------------------------------------------- */ /* Try to read a .prj file if it is indicated. */ /* -------------------------------------------------------------------- */ OGRSpatialReference oSRS; if( poDS->nVersionCode >= 12 && poDS->abyHeader[60] != 0 ) { const char *pszPrjFile = CPLResetExtension( poOpenInfo->pszFilename, "prj" ); VSILFILE *fp = VSIFOpenL( pszPrjFile, "rt" ); if( fp != NULL ) { const int nBufMax = 10000; char *pszBuffer = static_cast<char *>(CPLMalloc(nBufMax)); const int nBytes = static_cast<int>(VSIFReadL( pszBuffer, 1, nBufMax-1, fp )); CPL_IGNORE_RET_VAL(VSIFCloseL( fp )); pszBuffer[nBytes] = '\0'; char *pszBufPtr = pszBuffer; if( oSRS.importFromWkt( &pszBufPtr ) != OGRERR_NONE ) { CPLError( CE_Warning, CPLE_AppDefined, "Unable to parse .prj file, " "coordinate system missing." ); } CPLFree( pszBuffer ); } } /* -------------------------------------------------------------------- */ /* If we didn't find a .prj file, try to use internal info. */ /* -------------------------------------------------------------------- */ if( oSRS.GetRoot() == NULL ) { GInt16 nUTMZone = 0; memcpy( &nUTMZone, poDS->abyHeader + 24, 2 ); nUTMZone = CPL_LSBWORD16( nUTMZone ); GInt16 nDatum = 0; memcpy( &nDatum, poDS->abyHeader + 26, 2 ); nDatum = CPL_LSBWORD16( nDatum ); GInt16 nHUnits = 0; memcpy( &nHUnits, poDS->abyHeader + 22, 2 ); nHUnits = CPL_LSBWORD16( nHUnits ); if( nUTMZone != 0 ) oSRS.SetUTM( std::abs(static_cast<int>(nUTMZone)), nUTMZone > 0 ); else if( nHUnits != 0 ) oSRS.SetLocalCS( "Unknown" ); if( nHUnits == 1 ) oSRS.SetLinearUnits( SRS_UL_METER, 1.0 ); else if( nHUnits == 2 ) oSRS.SetLinearUnits( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) ); else if( nHUnits == 3 ) oSRS.SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) ); // Translate some of the more obvious old USGS datum codes if( nDatum == 0 ) nDatum = 6201; else if( nDatum == 1 ) nDatum = 6209; else if( nDatum == 2 ) nDatum = 6210; else if( nDatum == 3 ) nDatum = 6202; else if( nDatum == 4 ) nDatum = 6203; else if( nDatum == 6 ) nDatum = 6222; else if( nDatum == 7 ) nDatum = 6230; else if( nDatum == 13 ) nDatum = 6267; else if( nDatum == 14 ) nDatum = 6269; else if( nDatum == 17 ) nDatum = 6277; else if( nDatum == 19 ) nDatum = 6284; else if( nDatum == 21 ) nDatum = 6301; else if( nDatum == 22 ) nDatum = 6322; else if( nDatum == 23 ) nDatum = 6326; if( !oSRS.IsLocal() ) { if( nDatum >= 6000 ) { char szName[32]; snprintf( szName, sizeof(szName), "EPSG:%d", nDatum-2000 ); oSRS.SetWellKnownGeogCS( szName ); } else oSRS.SetWellKnownGeogCS( "WGS84" ); } } /* -------------------------------------------------------------------- */ /* Convert coordinate system back to WKT. */ /* -------------------------------------------------------------------- */ if( oSRS.GetRoot() != NULL ) oSRS.exportToWkt( &poDS->pszProjection ); /* -------------------------------------------------------------------- */ /* Get georeferencing bounds. */ /* -------------------------------------------------------------------- */ if( poDS->nVersionCode >= 11 ) { double dfLeft = 0.0; memcpy( &dfLeft, poDS->abyHeader + 28, 8 ); CPL_LSBPTR64( &dfLeft ); double dfRight = 0.0; memcpy( &dfRight, poDS->abyHeader + 36, 8 ); CPL_LSBPTR64( &dfRight ); double dfBottom = 0.0; memcpy( &dfBottom, poDS->abyHeader + 44, 8 ); CPL_LSBPTR64( &dfBottom ); double dfTop = 0.0; memcpy( &dfTop, poDS->abyHeader + 52, 8 ); CPL_LSBPTR64( &dfTop ); poDS->adfGeoTransform[0] = dfLeft; poDS->adfGeoTransform[1] = (dfRight - dfLeft) / poDS->nRasterXSize; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = dfTop; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = (dfBottom - dfTop) / poDS->nRasterYSize; poDS->bGeoTransformValid = TRUE; } /* -------------------------------------------------------------------- */ /* Re-open the file with the desired access. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" ); else poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( poDS->fpImage == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to re-open %s within BT driver.\n", poOpenInfo->pszFilename ); delete poDS; return NULL; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Create band information objects */ /* -------------------------------------------------------------------- */ poDS->SetBand( 1, new BTRasterBand( poDS, poDS->fpImage, eType ) ); #ifdef notdef poDS->bGeoTransformValid = GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", poDS->adfGeoTransform ); #endif /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo ) { if( poOpenInfo->nHeaderBytes < 1024) return NULL; if( !EQUALN((const char *) poOpenInfo->pabyHeader + 52, "ACQUISITION DATE =", 18) && !EQUALN((const char *) poOpenInfo->pabyHeader + 36, "ACQUISITION DATE =", 18) ) return NULL; /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ FASTDataset *poDS = new FASTDataset(); poDS->fpHeader = VSIFOpenL(poOpenInfo->pszFilename, "rb"); if (poDS->fpHeader == NULL) { delete poDS; return NULL; } poDS->pszFilename = poOpenInfo->pszFilename; poDS->pszDirname = CPLStrdup( CPLGetDirname( poOpenInfo->pszFilename ) ); /* -------------------------------------------------------------------- */ /* Read the administrative record. */ /* -------------------------------------------------------------------- */ char *pszHeader = static_cast<char *>( CPLMalloc( ADM_HEADER_SIZE + 1 ) ); size_t nBytesRead = 0; if( VSIFSeekL( poDS->fpHeader, 0, SEEK_SET ) >= 0 ) nBytesRead = VSIFReadL( pszHeader, 1, ADM_HEADER_SIZE, poDS->fpHeader ); if ( nBytesRead < ADM_MIN_HEADER_SIZE ) { CPLDebug( "FAST", "Header file too short. Reading failed" ); CPLFree(pszHeader); delete poDS; return NULL; } pszHeader[nBytesRead] = '\0'; // Read acquisition date char *pszTemp = GetValue( pszHeader, ACQUISITION_DATE, ACQUISITION_DATE_SIZE, TRUE ); if (pszTemp == NULL) { CPLDebug( "FAST", "Cannot get ACQUISITION_DATE, using empty value." ); pszTemp = CPLStrdup(""); } poDS->SetMetadataItem( "ACQUISITION_DATE", pszTemp ); CPLFree( pszTemp ); // Read satellite name (will read the first one only) pszTemp = GetValue( pszHeader, SATELLITE_NAME, SATELLITE_NAME_SIZE, TRUE ); if (pszTemp == NULL) { CPLDebug( "FAST", "Cannot get SATELLITE_NAME, using empty value." ); pszTemp = CPLStrdup( "" ); } poDS->SetMetadataItem( "SATELLITE", pszTemp ); if ( STARTS_WITH_CI(pszTemp, "LANDSAT") ) poDS->iSatellite = LANDSAT; // TODO(schwehr): Was this a bug that both are IRS? // else if ( STARTS_WITH_CI(pszTemp, "IRS") ) // poDS->iSatellite = IRS; else poDS->iSatellite = IRS; // TODO(schwehr): Should this be FAST_UNKNOWN? CPLFree( pszTemp ); // Read sensor name (will read the first one only) pszTemp = GetValue( pszHeader, SENSOR_NAME, SENSOR_NAME_SIZE, TRUE ); if (pszTemp == NULL) { CPLDebug( "FAST", "Cannot get SENSOR_NAME, using empty value." ); pszTemp = CPLStrdup(""); } poDS->SetMetadataItem( "SENSOR", pszTemp ); CPLFree( pszTemp ); // Read filenames poDS->nBands = 0; if (strstr( pszHeader, FILENAME ) == NULL) { if (strstr(pszHeader, "GENERATING AGENCY =EUROMAP")) { // If we don't find the FILENAME field, let's try with the Euromap // PAN / LISS3 / WIFS IRS filename convention. if ((EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS 1C") || EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS 1D")) && (EQUAL(poDS->GetMetadataItem("SENSOR"), "PAN") || EQUAL(poDS->GetMetadataItem("SENSOR"), "LISS3") || EQUAL(poDS->GetMetadataItem("SENSOR"), "WIFS"))) { poDS->TryEuromap_IRS_1C_1D_ChannelNameConvention(); } else if (EQUAL(poDS->GetMetadataItem("SATELLITE"), "CARTOSAT-1") && (EQUAL(poDS->GetMetadataItem("SENSOR"), "FORE") || EQUAL(poDS->GetMetadataItem("SENSOR"), "AFT"))) { // See appendix F in // http://www.euromap.de/download/p5fast_20050301.pdf const CPLString osSuffix = CPLGetExtension( poDS->pszFilename ); const char *papszBasenames[] = { "BANDF", "bandf", "BANDA", "banda" }; for ( int i = 0; i < 4; i++ ) { const CPLString osChannelFilename = CPLFormFilename( poDS->pszDirname, papszBasenames[i], osSuffix ); if( poDS->OpenChannel( osChannelFilename, 0 ) ) { poDS->nBands = 1; break; } } } else if( EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS P6") ) { // If BANDS_PRESENT="2345", the file bands are "BAND2.DAT", // "BAND3.DAT", etc. pszTemp = GetValue( pszHeader, BANDS_PRESENT, BANDS_PRESENT_SIZE, TRUE ); if (pszTemp) { for( int i=0; pszTemp[i] != '\0'; i++ ) { if( pszTemp[i] >= '2' && pszTemp[i] <= '5' ) { if( poDS->FOpenChannel( poDS->pszFilename, poDS->nBands, pszTemp[i] - '0')) poDS->nBands++; } } CPLFree( pszTemp ); } } } } // If the previous lookup for band files didn't success, fallback to the // standard way of finding them, either by the FILENAME field, either with // the usual patterns like bandX.dat, etc. if( !poDS->nBands ) { pszTemp = pszHeader; for ( int i = 0; i < 7; i++ ) { char *pszFilename = NULL ; if ( pszTemp ) pszTemp = strstr( pszTemp, FILENAME ); if ( pszTemp ) { // Skip the parameter name pszTemp += strlen(FILENAME); // Skip whitespaces and equal signs while ( *pszTemp == ' ' ) pszTemp++; while ( *pszTemp == '=' ) pszTemp++; pszFilename = CPLScanString( pszTemp, FILENAME_SIZE, TRUE, FALSE ); } else pszTemp = NULL; if ( poDS->FOpenChannel( pszFilename, poDS->nBands, poDS->nBands + 1 ) ) poDS->nBands++; if ( pszFilename ) CPLFree( pszFilename ); } } if ( !poDS->nBands ) { CPLError( CE_Failure, CPLE_NotSupported, "Failed to find and open band data files." ); CPLFree(pszHeader); delete poDS; return NULL; } // Read number of pixels/lines and bit depth pszTemp = GetValue( pszHeader, PIXELS, PIXELS_SIZE, FALSE ); if ( pszTemp ) { poDS->nRasterXSize = atoi( pszTemp ); CPLFree( pszTemp ); } else { CPLDebug( "FAST", "Failed to find number of pixels in line." ); CPLFree(pszHeader); delete poDS; return NULL; } pszTemp = GetValue( pszHeader, LINES1, LINES_SIZE, FALSE ); if ( !pszTemp ) pszTemp = GetValue( pszHeader, LINES2, LINES_SIZE, FALSE ); if ( pszTemp ) { poDS->nRasterYSize = atoi( pszTemp ); CPLFree( pszTemp ); } else { CPLDebug( "FAST", "Failed to find number of lines in raster." ); CPLFree(pszHeader); delete poDS; return NULL; } if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) { CPLFree(pszHeader); delete poDS; return NULL; } pszTemp = GetValue( pszHeader, BITS_PER_PIXEL, BITS_PER_PIXEL_SIZE, FALSE ); if ( pszTemp ) { switch( atoi(pszTemp) ) { case 8: default: poDS->eDataType = GDT_Byte; break; // For a strange reason, some Euromap products declare 10 bits // output, but are 16 bits. case 10: case 16: poDS->eDataType = GDT_UInt16; break; } CPLFree( pszTemp ); } else { poDS->eDataType = GDT_Byte; } /* -------------------------------------------------------------------- */ /* Read radiometric record. */ /* -------------------------------------------------------------------- */ const char *pszFirst = NULL; const char *pszSecond = NULL; // Read gains and biases. This is a trick! pszTemp = strstr( pszHeader, "BIASES" );// It may be "BIASES AND GAINS" // or "GAINS AND BIASES" const char* pszGains = strstr( pszHeader, "GAINS" ); if( pszTemp == NULL || pszGains == NULL ) { CPLDebug( "FAST", "No BIASES and/or GAINS" ); CPLFree( pszHeader ); delete poDS; return NULL; } if ( pszTemp > pszGains ) { pszFirst = "GAIN%d"; pszSecond = "BIAS%d"; } else { pszFirst = "BIAS%d"; pszSecond = "GAIN%d"; } // Now search for the first number occurrence after that string. for ( int i = 1; i <= poDS->nBands; i++ ) { char *pszValue = NULL; size_t nValueLen = VALUE_SIZE; pszTemp = strpbrk( pszTemp, "-.0123456789" ); if ( pszTemp ) { nValueLen = strspn( pszTemp, "+-.0123456789" ); pszValue = CPLScanString( pszTemp, static_cast<int>(nValueLen), TRUE, TRUE ); poDS->SetMetadataItem( CPLSPrintf(pszFirst, i ), pszValue ); CPLFree( pszValue ); } pszTemp += nValueLen; pszTemp = strpbrk( pszTemp, "-.0123456789" ); if ( pszTemp ) { nValueLen = strspn( pszTemp, "+-.0123456789" ); pszValue = CPLScanString( pszTemp, static_cast<int>(nValueLen), TRUE, TRUE ); poDS->SetMetadataItem( CPLSPrintf(pszSecond, i ), pszValue ); CPLFree( pszValue ); } pszTemp += nValueLen; } /* -------------------------------------------------------------------- */ /* Read geometric record. */ /* -------------------------------------------------------------------- */ // Coordinates of pixel's centers double dfULX = 0.0; double dfULY = 0.0; double dfURX = 0.0; double dfURY = 0.0; double dfLLX = 0.0; double dfLLY = 0.0; double dfLRX = 0.0; double dfLRY = 0.0; // Read projection name pszTemp = GetValue( pszHeader, PROJECTION_NAME, PROJECTION_NAME_SIZE, FALSE ); long iProjSys = 0; if ( pszTemp && !EQUAL( pszTemp, "" ) ) iProjSys = USGSMnemonicToCode( pszTemp ); else iProjSys = 1L; // UTM by default CPLFree( pszTemp ); // Read ellipsoid name pszTemp = GetValue( pszHeader, ELLIPSOID_NAME, ELLIPSOID_NAME_SIZE, FALSE ); long iDatum = 0; // Clarke, 1866 (NAD1927) by default. if ( pszTemp && !EQUAL( pszTemp, "" ) ) iDatum = USGSEllipsoidToCode( pszTemp ); CPLFree( pszTemp ); // Read zone number. pszTemp = GetValue( pszHeader, ZONE_NUMBER, ZONE_NUMBER_SIZE, FALSE ); long iZone = 0; if ( pszTemp && !EQUAL( pszTemp, "" ) ) iZone = atoi( pszTemp ); CPLFree( pszTemp ); // Read 15 USGS projection parameters double adfProjParms[15] = { 0.0 }; pszTemp = strstr( pszHeader, USGS_PARAMETERS ); if ( pszTemp && !EQUAL( pszTemp, "" ) ) { pszTemp += strlen( USGS_PARAMETERS ); for ( int i = 0; i < 15; i++ ) { pszTemp = strpbrk( pszTemp, "-.0123456789" ); if ( pszTemp ) adfProjParms[i] = CPLScanDouble( pszTemp, VALUE_SIZE ); pszTemp = strpbrk( pszTemp, " \t" ); } } // Coordinates should follow the word "PROJECTION", otherwise we can // be confused by other occurrences of the corner keywords. char *pszGeomRecord = strstr( pszHeader, "PROJECTION" ); // Read corner coordinates pszTemp = strstr( pszGeomRecord, CORNER_UPPER_LEFT ); if ( pszTemp && !EQUAL( pszTemp, "" ) ) { pszTemp += strlen( CORNER_UPPER_LEFT ) + 28; dfULX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE ); pszTemp += CORNER_VALUE_SIZE + 1; dfULY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE ); } pszTemp = strstr( pszGeomRecord, CORNER_UPPER_RIGHT ); if ( pszTemp && !EQUAL( pszTemp, "" ) ) { pszTemp += strlen( CORNER_UPPER_RIGHT ) + 28; dfURX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE ); pszTemp += CORNER_VALUE_SIZE + 1; dfURY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE ); } pszTemp = strstr( pszGeomRecord, CORNER_LOWER_LEFT ); if ( pszTemp && !EQUAL( pszTemp, "" ) ) { pszTemp += strlen( CORNER_LOWER_LEFT ) + 28; dfLLX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE ); pszTemp += CORNER_VALUE_SIZE + 1; dfLLY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE ); } pszTemp = strstr( pszGeomRecord, CORNER_LOWER_RIGHT ); if ( pszTemp && !EQUAL( pszTemp, "" ) ) { pszTemp += strlen( CORNER_LOWER_RIGHT ) + 28; dfLRX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE ); pszTemp += CORNER_VALUE_SIZE + 1; dfLRY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE ); } if ( dfULX != 0.0 && dfULY != 0.0 && dfURX != 0.0 && dfURY != 0.0 && dfLLX != 0.0 && dfLLY != 0.0 && dfLRX != 0.0 && dfLRY != 0.0 ) { // Strip out zone number from the easting values, if either if ( dfULX >= 1000000.0 ) dfULX -= static_cast<double>( iZone ) * 1000000.0; if ( dfURX >= 1000000.0 ) dfURX -= static_cast<double>( iZone ) * 1000000.0; if ( dfLLX >= 1000000.0 ) dfLLX -= static_cast<double>( iZone ) * 1000000.0; if ( dfLRX >= 1000000.0 ) dfLRX -= static_cast<double>( iZone ) * 1000000.0; // In EOSAT FAST Rev C, the angles are in decimal degrees // otherwise they are in packed DMS format. const int bAnglesInPackedDMSFormat = strstr( pszHeader, "REV C" ) == NULL; // Create projection definition OGRSpatialReference oSRS; OGRErr eErr = oSRS.importFromUSGS( iProjSys, iZone, adfProjParms, iDatum, bAnglesInPackedDMSFormat ); if ( eErr != OGRERR_NONE ) CPLDebug( "FAST", "Import projection from USGS failed: %d", eErr ); oSRS.SetLinearUnits( SRS_UL_METER, 1.0 ); // Read datum name pszTemp = GetValue( pszHeader, DATUM_NAME, DATUM_NAME_SIZE, FALSE ); if ( pszTemp ) { if ( EQUAL( pszTemp, "WGS84" ) ) oSRS.SetWellKnownGeogCS( "WGS84" ); else if ( EQUAL( pszTemp, "NAD27" ) ) oSRS.SetWellKnownGeogCS( "NAD27" ); else if ( EQUAL( pszTemp, "NAD83" ) ) oSRS.SetWellKnownGeogCS( "NAD83" ); CPLFree( pszTemp ); } else { // Reasonable fallback oSRS.SetWellKnownGeogCS( "WGS84" ); } if ( poDS->pszProjection ) CPLFree( poDS->pszProjection ); eErr = oSRS.exportToWkt( &poDS->pszProjection ); if ( eErr != OGRERR_NONE ) CPLDebug("FAST", "Export projection to WKT USGS failed: %d", eErr); // Generate GCPs GDAL_GCP *pasGCPList = static_cast<GDAL_GCP *>( CPLCalloc( sizeof( GDAL_GCP ), 4 ) ); GDALInitGCPs( 4, pasGCPList ); CPLFree(pasGCPList[0].pszId); CPLFree(pasGCPList[1].pszId); CPLFree(pasGCPList[2].pszId); CPLFree(pasGCPList[3].pszId); /* Let's order the GCP in TL, TR, BR, BL order to benefit from the */ /* GDALGCPsToGeoTransform optimization */ pasGCPList[0].pszId = CPLStrdup("UPPER_LEFT"); pasGCPList[0].dfGCPX = dfULX; pasGCPList[0].dfGCPY = dfULY; pasGCPList[0].dfGCPZ = 0.0; pasGCPList[0].dfGCPPixel = 0.5; pasGCPList[0].dfGCPLine = 0.5; pasGCPList[1].pszId = CPLStrdup("UPPER_RIGHT"); pasGCPList[1].dfGCPX = dfURX; pasGCPList[1].dfGCPY = dfURY; pasGCPList[1].dfGCPZ = 0.0; pasGCPList[1].dfGCPPixel = poDS->nRasterXSize-0.5; pasGCPList[1].dfGCPLine = 0.5; pasGCPList[2].pszId = CPLStrdup("LOWER_RIGHT"); pasGCPList[2].dfGCPX = dfLRX; pasGCPList[2].dfGCPY = dfLRY; pasGCPList[2].dfGCPZ = 0.0; pasGCPList[2].dfGCPPixel = poDS->nRasterXSize-0.5; pasGCPList[2].dfGCPLine = poDS->nRasterYSize-0.5; pasGCPList[3].pszId = CPLStrdup("LOWER_LEFT"); pasGCPList[3].dfGCPX = dfLLX; pasGCPList[3].dfGCPY = dfLLY; pasGCPList[3].dfGCPZ = 0.0; pasGCPList[3].dfGCPPixel = 0.5; pasGCPList[3].dfGCPLine = poDS->nRasterYSize-0.5; // Calculate transformation matrix, if accurate const bool transform_ok = CPL_TO_BOOL( GDALGCPsToGeoTransform( 4, pasGCPList, poDS->adfGeoTransform, 0 ) ); if( !transform_ok ) { poDS->adfGeoTransform[0] = 0.0; poDS->adfGeoTransform[1] = 1.0; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = 0.0; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = 1.0; if ( poDS->pszProjection ) CPLFree( poDS->pszProjection ); poDS->pszProjection = CPLStrdup(""); } GDALDeinitGCPs(4, pasGCPList); CPLFree(pasGCPList); } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ const int nPixelOffset = GDALGetDataTypeSize(poDS->eDataType) / 8; const int nLineOffset = poDS->nRasterXSize * nPixelOffset; for( int i = 1; i <= poDS->nBands; i++ ) { poDS->SetBand( i, new FASTRasterBand( poDS, i, poDS->fpChannels[i - 1], 0, nPixelOffset, nLineOffset, poDS->eDataType, TRUE)); } CPLFree( pszHeader ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); // opens overviews. poDS->oOvManager.Initialize(poDS, poDS->pszFilename); /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { delete poDS; CPLError( CE_Failure, CPLE_NotSupported, "The FAST driver does not support update access to existing" " datasets." ); return NULL; } return poDS; }
int TerragenDataset::LoadFromFile() { GUInt16 nSize, xpts=0, ypts=0; m_dSCAL = 30.0; m_nDataOffset = 0; if(0 != VSIFSeekL(m_fp, 16, SEEK_SET)) return 0; char szTag[4]; if(!this->read_next_tag(szTag) || !tag_is(szTag, "SIZE")) return 0; if(!this->get(nSize) || !this->skip(2)) return 0; // Set dimensions to SIZE chunk. If we don't // encounter XPTS/YPTS chunks, we can assume // the terrain to be square. xpts = ypts = nSize+1; while(this->read_next_tag(szTag)) { if(this->tag_is(szTag, "XPTS")) { this->get(xpts); if(xpts < nSize || !this->skip(2)) return 0; continue; } if(this->tag_is(szTag, "YPTS")) { this->get(ypts); if(ypts < nSize || !this->skip(2)) return 0; continue; } if(this->tag_is(szTag, "SCAL")) { float sc[3]; this->get(sc[0]); this->get(sc[1]); this->get(sc[2]); m_dSCAL = sc[1]; continue; } if(this->tag_is(szTag, "CRAD")) { if(!this->skip(sizeof(float))) return 0; continue; } if(this->tag_is(szTag, "CRVM")) { if(!this->skip(sizeof(GUInt32))) return 0; continue; } if(this->tag_is(szTag, "ALTW")) { this->get(m_nHeightScale); this->get(m_nBaseHeight); m_nDataOffset = VSIFTellL(m_fp); if(!this->skip(xpts * ypts * sizeof(GInt16))) return 0; continue; } if(this->tag_is(szTag, "EOF ")) { break; } } if(xpts == 0 || ypts == 0 || m_nDataOffset == 0) return 0; nRasterXSize = xpts; nRasterYSize = ypts; // todo: sanity check: do we have enough pixels? // Cache realworld scaling and offset. m_dScale = m_dSCAL / 65536 * m_nHeightScale; m_dOffset = m_dSCAL * m_nBaseHeight; strcpy(m_szUnits, "m"); // Make our projection to have origin at the // NW corner, and groundscale to match elev scale // (i.e., uniform voxels). m_adfTransform[0] = 0.0; m_adfTransform[1] = m_dSCAL; m_adfTransform[2] = 0.0; m_adfTransform[3] = 0.0; m_adfTransform[4] = 0.0; m_adfTransform[5] = m_dSCAL; /* -------------------------------------------------------------------- */ /* Set projection. */ /* -------------------------------------------------------------------- */ // Terragen files as of Apr 2006 are partially georeferenced, // we can declare a local coordsys that uses meters. OGRSpatialReference sr; sr.SetLocalCS("Terragen world space"); if(OGRERR_NONE != sr.SetLinearUnits("m", 1.0)) return 0; if(OGRERR_NONE != sr.exportToWkt(&m_pszProjection)) return 0; return TRUE; }
rspfString rspfOgcWktTranslator::fromOssimKwl(const rspfKeywordlist &kwl, const char *prefix)const { rspfString projType = kwl.find(rspfKeywordNames::TYPE_KW); rspfString datumType = kwl.find(rspfKeywordNames::DATUM_KW); rspfString wktString; OGRSpatialReference oSRS; if(projType == "") { return wktString; } rspfString zone = kwl.find(prefix, rspfKeywordNames::ZONE_KW); rspfString hemisphere = kwl.find(prefix, rspfKeywordNames::HEMISPHERE_KW); rspfString parallel1 = kwl.find(prefix, rspfKeywordNames::STD_PARALLEL_1_KW); rspfString parallel2 = kwl.find(prefix, rspfKeywordNames::STD_PARALLEL_2_KW); rspfString originLat = kwl.find(prefix, rspfKeywordNames::ORIGIN_LATITUDE_KW); rspfString centralMeridian = kwl.find(prefix, rspfKeywordNames::CENTRAL_MERIDIAN_KW); rspfString scale = kwl.find(prefix, rspfKeywordNames::SCALE_FACTOR_KW); rspfString pcsCode = kwl.find(prefix, rspfKeywordNames::PCS_CODE_KW); rspfDpt falseEastingNorthing; falseEastingNorthing.x = 0.0; falseEastingNorthing.y = 0.0; const char *lookup = kwl.find(prefix, rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW); if (lookup) { rspfUnitType units = static_cast<rspfUnitType>(rspfUnitTypeLut::instance()-> getEntryNumber(lookup)); lookup = kwl.find(prefix, rspfKeywordNames::FALSE_EASTING_NORTHING_KW); if (lookup) { rspfDpt eastingNorthing; eastingNorthing.toPoint(std::string(lookup)); switch (units) { case RSPF_METERS: { falseEastingNorthing = eastingNorthing; break; } case RSPF_FEET: case RSPF_US_SURVEY_FEET: { rspfUnitConversionTool ut; ut.setValue(eastingNorthing.x, units); falseEastingNorthing.x = ut.getValue(RSPF_METERS); ut.setValue(eastingNorthing.y, units); falseEastingNorthing.y = ut.getValue(RSPF_METERS); break; } default: { rspfNotify(rspfNotifyLevel_WARN) << "rspfOgcWktTranslator::fromOssimKwl WARNING!" << "Unhandled unit type for " << rspfKeywordNames::FALSE_EASTING_NORTHING_UNITS_KW << ": " << ( rspfUnitTypeLut::instance()-> getEntryString(units).c_str() ) << endl; break; } } // End of switch (units) } // End of if (FALSE_EASTING_NORTHING_KW) } // End of if (FALSE_EASTING_NORTHING_UNITS_KW) else { lookup = kwl.find(prefix, rspfKeywordNames::FALSE_EASTING_KW); if(lookup) { falseEastingNorthing.x = fabs(rspfString(lookup).toFloat64()); } lookup = kwl.find(prefix, rspfKeywordNames::FALSE_NORTHING_KW); if(lookup) { falseEastingNorthing.y = fabs(rspfString(lookup).toFloat64()); } } oSRS.SetLinearUnits("Meter", 1.0); int pcsCodeVal = (pcsCode.empty() == false) ? pcsCode.toInt() : EPSG_CODE_MAX; if(pcsCodeVal < EPSG_CODE_MAX) { rspfEpsgProjectionDatabase* proj_db = rspfEpsgProjectionDatabase::instance(); rspfString pcsCodeName = proj_db->findProjectionName(pcsCodeVal); if ( pcsCodeName.contains("HARN") && pcsCodeName.contains("_Feet") ) { rspfString feetStr("_Feet"); rspfString newPcsCodeName( pcsCodeName.before(feetStr).c_str() ); rspfString epsg_spec = proj_db->findProjectionCode(newPcsCodeName); rspf_uint32 new_code = epsg_spec.after(":").toUInt32(); if (new_code) pcsCodeVal = new_code; } oSRS.importFromEPSG( pcsCodeVal ); } else if(projType == "rspfUtmProjection") { #if 0 hemisphere = hemisphere.trim().upcase(); if(hemisphere != "") { oSRS.SetUTM(zone.toLong(), hemisphere != "S"); } else { oSRS.SetUTM(zone.toLong(), true); } #else short gcs = USER_DEFINED; if (datumType == "WGE") gcs = GCS_WGS_84; else if (datumType == "WGD") gcs = GCS_WGS_72; else if (datumType == "NAR-C") gcs = GCS_NAD83; else if (datumType == "NAR") gcs = GCS_NAD83; else if (datumType == "NAS-C") gcs = GCS_NAD27; else if (datumType == "NAS") gcs = GCS_NAD27; else if (datumType == "ADI-M") gcs = GCS_Adindan; else if (datumType == "ARF-M") gcs = GCS_Arc_1950; else if (datumType == "ARS-M") gcs = GCS_Arc_1960; else if (datumType == "EUR-7" || datumType == "EUR-M") gcs = GCS_ED50; else if ((datumType == "OGB-7") || (datumType == "OGB-M") || (datumType == "OGB-A") || (datumType == "OGB-B") || (datumType == "OGB-C") || (datumType == "OGB-D")) gcs = GCS_OSGB_1936; else if (datumType == "TOY-M") gcs = GCS_Tokyo; else { if(traceDebug()) { rspfNotify(rspfNotifyLevel_DEBUG) << "DATUM = " << datumType << " tag not written " << std::endl << "Please let us know so we can add it" << std::endl; } } int mapZone = zone.toInt(); hemisphere = hemisphere.trim().upcase(); bool bDoImportFromEPSG = false; switch ( gcs ) { case GCS_WGS_84: { if (hemisphere == "N") // Northern hemisphere. { pcsCodeVal = 32600 + mapZone; } else // Southern hemisphere. { pcsCodeVal = 32700 + mapZone; } bDoImportFromEPSG = true; break; } case GCS_WGS_72: { if (hemisphere == "N") // Northern hemisphere. { pcsCodeVal = 32200 + mapZone; } else // Southern hemisphere. { pcsCodeVal = 32300 + mapZone; } bDoImportFromEPSG = true; break; } case GCS_NAD27: { if (hemisphere == "N") // Northern hemisphere. { pcsCodeVal = 26700 + mapZone; } else // Southern hemisphere. { pcsCodeVal = 32000 + mapZone; } bDoImportFromEPSG = true; break; } case GCS_NAD83: { if (hemisphere == "N") // Northern hemisphere. { pcsCodeVal = 26900 + mapZone; } else // Southern hemisphere. { pcsCodeVal = 32100 + mapZone; } bDoImportFromEPSG = true; break; } default: { if (mapZone > 0) // Northern hemisphere. { pcsCodeVal = 16000 + mapZone; } else if (mapZone < 0) // Southern hemisphere. { hemisphere = "S"; pcsCodeVal = 16100 + abs(mapZone); } break; } } // End of "switch ( gcs )" if ( bDoImportFromEPSG == true ) oSRS.importFromEPSG( pcsCodeVal ); else { if(hemisphere != "") { oSRS.SetUTM(zone.toLong(), hemisphere != "S"); } else { oSRS.SetUTM(zone.toLong(), true); } } #endif } else if(projType == "rspfLlxyProjection") { OGRSpatialReference oGeogCS; oGeogCS.SetEquirectangular(0.0, 0.0, 0.0, 0.0); oGeogCS.SetAngularUnits(SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV)); oSRS.CopyGeogCSFrom( &oGeogCS ); } else if(projType == "rspfEquDistCylProjection") { OGRSpatialReference oGeogCS; oGeogCS.SetEquirectangular(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); oGeogCS.SetAngularUnits(SRS_UA_DEGREE, atof(SRS_UA_DEGREE_CONV)); oSRS.CopyGeogCSFrom( &oGeogCS ); } else if(projType == "rspfSinusoidalProjection") { oSRS.SetSinusoidal(centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfCylEquAreaProjection") { oSRS.SetCEA(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfCassiniProjection") { oSRS.SetCS(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfAlbersProjection") { oSRS.SetACEA(parallel1.toDouble(), parallel2.toDouble(), originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfAzimEquDistProjection") { oSRS.SetAE(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfEckert4Projection") { oSRS.SetEckertIV(centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfEckert6Projection") { oSRS.SetEckertVI(centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfGnomonicProjection") { oSRS.SetGnomonic(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfLambertConformalConicProjection") { oSRS.SetLCC(parallel1.toDouble(), parallel2.toDouble(), originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfVanDerGrintenProjection") { oSRS.SetVDG(centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfMillerProjection") { oSRS.SetMC(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfMercatorProjection") { oSRS.SetMercator(originLat.toDouble(), centralMeridian.toDouble(), scale.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfMollweidProjection") { oSRS.SetMollweide(centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfNewZealandMapGridProjection") { oSRS.SetNZMG(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfOrthoGraphicProjection") { oSRS.SetOrthographic(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfPolarStereoProjection") { oSRS.SetPS(originLat.toDouble(), centralMeridian.toDouble(), scale.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfPolyconicProjectio") { oSRS.SetPolyconic(originLat.toDouble(), centralMeridian.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfStereographicProjection") { oSRS.SetStereographic(originLat.toDouble(), centralMeridian.toDouble(), scale.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else if(projType == "rspfTransMercatorProjection") { oSRS.SetTM(originLat.toDouble(), centralMeridian.toDouble(), scale.toDouble(), falseEastingNorthing.x, falseEastingNorthing.y); } else { cerr << "rspfOgcWktTranslator::fromOssimKwl:\n" << "Projection translation for " << projType << " not supported " << endl; } if(pcsCodeVal >= EPSG_CODE_MAX) { datumType = datumType.upcase(); if(datumType == "WGE") { oSRS.SetWellKnownGeogCS("WGS84"); } else if(datumType == "WGD") { oSRS.SetWellKnownGeogCS("WGS72"); } else if(datumType == "NAS-C") //1927 { oSRS.SetWellKnownGeogCS("NAD27"); } else if(datumType == "NAS") //1927 { oSRS.SetWellKnownGeogCS("NAD27"); } else if(datumType == "NAR-C") // 1983 { oSRS.SetWellKnownGeogCS("NAD83"); } else if(datumType == "NAR") // 1983 { oSRS.SetWellKnownGeogCS("NAD83"); } else if(datumType == "NTF") { oSRS.SetWellKnownGeogCS("EPSG:4275"); } else { cerr << "rspfOgcWktTranslator::fromOssimKwl: Datum translation for " << datumType <<" not supported" << endl; } } char* exportString = NULL; oSRS.exportToWkt(&exportString); if(exportString) { wktString = exportString; OGRFree(exportString); } return wktString; }