int USGSDEMDataset::LoadFromFile(VSILFILE *InDem) { // check for version of DEM format CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 864, 0)); // Read DEM into matrix const int nRow = ReadInt(InDem); const int nColumn = ReadInt(InDem); const bool bNewFormat = VSIFTellL(InDem) >= 1024 || nRow != 1 || nColumn != 1; if (bNewFormat) { CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 1024, 0)); // New Format int i = ReadInt(InDem); int j = ReadInt(InDem); if ( i != 1 || ( j != 1 && j != 0 ) ) // File OK? { CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 893, 0)); // Undocumented Format (39109h1.dem) i = ReadInt(InDem); j = ReadInt(InDem); if ( i != 1 || j != 1 ) // File OK? { CPLError( CE_Failure, CPLE_AppDefined, "Does not appear to be a USGS DEM file." ); return FALSE; } else nDataStartOffset = 893; } else nDataStartOffset = 1024; } else nDataStartOffset = 864; CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 156, 0)); const int nCoordSystem = ReadInt(InDem); const int iUTMZone = ReadInt(InDem); CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 528, 0)); const int nGUnit = ReadInt(InDem); const int nVUnit = ReadInt(InDem); // Vertical Units in meters if (nVUnit==1) pszUnits = "ft"; else pszUnits = "m"; CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 816, 0)); const double dxdelta = DConvert(InDem, 12); const double dydelta = DConvert(InDem, 12); if( dydelta == 0 ) return FALSE; fVRes = DConvert(InDem, 12); /* -------------------------------------------------------------------- */ /* Should we treat this as floating point, or GInt16. */ /* -------------------------------------------------------------------- */ if (nVUnit==1 || fVRes < 1.0) eNaturalDataFormat = GDT_Float32; else eNaturalDataFormat = GDT_Int16; /* -------------------------------------------------------------------- */ /* Read four corner coordinates. */ /* -------------------------------------------------------------------- */ CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 546, 0)); DPoint2 corners[4]; // SW, NW, NE, SE for (int i = 0; i < 4; i++) { corners[i].x = DConvert(InDem, 24); corners[i].y = DConvert(InDem, 24); } // find absolute extents of raw vales DPoint2 extent_min, extent_max; extent_min.x = std::min(corners[0].x, corners[1].x); extent_max.x = std::max(corners[2].x, corners[3].x); extent_min.y = std::min(corners[0].y, corners[3].y); extent_max.y = std::max(corners[1].y, corners[2].y); /* dElevMin = */ DConvert(InDem, 48); /* dElevMax = */ DConvert(InDem, 48); CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 858, 0)); const int nProfiles = ReadInt(InDem); /* -------------------------------------------------------------------- */ /* Collect the spatial reference system. */ /* -------------------------------------------------------------------- */ OGRSpatialReference sr; bool bNAD83 = true; // OLD format header ends at byte 864 if (bNewFormat) { // year of data compilation CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 876, 0)); char szDateBuffer[5]; CPL_IGNORE_RET_VAL(VSIFReadL(szDateBuffer, 4, 1, InDem)); /* szDateBuffer[4] = 0; */ // Horizontal datum // 1=North American Datum 1927 (NAD 27) // 2=World Geodetic System 1972 (WGS 72) // 3=WGS 84 // 4=NAD 83 // 5=Old Hawaii Datum // 6=Puerto Rico Datum CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 890, 0)); char szHorzDatum[3]; CPL_IGNORE_RET_VAL(VSIFReadL( szHorzDatum, 1, 2, InDem )); szHorzDatum[2] = '\0'; const int datum = atoi(szHorzDatum); switch (datum) { case 1: sr.SetWellKnownGeogCS( "NAD27" ); bNAD83 = false; break; case 2: sr.SetWellKnownGeogCS( "WGS72" ); break; case 3: sr.SetWellKnownGeogCS( "WGS84" ); break; case 4: sr.SetWellKnownGeogCS( "NAD83" ); break; case -9: break; default: sr.SetWellKnownGeogCS( "NAD27" ); break; } } else { sr.SetWellKnownGeogCS( "NAD27" ); bNAD83 = false; } if (nCoordSystem == 1) // UTM { if( iUTMZone >= -60 && iUTMZone <= 60 ) { sr.SetUTM( abs(iUTMZone), iUTMZone >= 0 ); if( nGUnit == 1 ) { sr.SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) ); char szUTMName[128]; snprintf( szUTMName, sizeof(szUTMName), "UTM Zone %d, Northern Hemisphere, us-ft", iUTMZone ); sr.SetNode( "PROJCS", szUTMName ); } } } else if (nCoordSystem == 2) // state plane { if( nGUnit == 1 ) sr.SetStatePlane( iUTMZone, bNAD83, "Foot", CPLAtof(SRS_UL_US_FOOT_CONV) ); else sr.SetStatePlane( iUTMZone, bNAD83 ); } sr.exportToWkt( &pszProjection ); /* -------------------------------------------------------------------- */ /* For UTM we use the extents (really the UTM coordinates of */ /* the lat/long corners of the quad) to determine the size in */ /* pixels and lines, but we have to make the anchors be modulus */ /* the pixel size which what really gets used. */ /* -------------------------------------------------------------------- */ if (nCoordSystem == 1 // UTM || nCoordSystem == 2 // State Plane || nCoordSystem == -9999 ) // unknown { // expand extents modulus the pixel size. extent_min.y = floor(extent_min.y/dydelta) * dydelta; extent_max.y = ceil(extent_max.y/dydelta) * dydelta; // Forcibly compute X extents based on first profile and pixelsize. CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, nDataStartOffset, 0)); /* njunk = */ ReadInt(InDem); /* njunk = */ ReadInt(InDem); /* njunk = */ ReadInt(InDem); /* njunk = */ ReadInt(InDem); const double dxStart = DConvert(InDem, 24); nRasterYSize = static_cast<int>( ( extent_max.y - extent_min.y ) / dydelta + 1.5 ); nRasterXSize = nProfiles; adfGeoTransform[0] = dxStart - dxdelta/2.0; adfGeoTransform[1] = dxdelta; adfGeoTransform[2] = 0.0; adfGeoTransform[3] = extent_max.y + dydelta/2.0; adfGeoTransform[4] = 0.0; adfGeoTransform[5] = -dydelta; } /* -------------------------------------------------------------------- */ /* Geographic -- use corners directly. */ /* -------------------------------------------------------------------- */ else { nRasterYSize = static_cast<int>( ( extent_max.y - extent_min.y ) / dydelta + 1.5 ); nRasterXSize = nProfiles; // Translate extents from arc-seconds to decimal degrees. adfGeoTransform[0] = (extent_min.x - dxdelta/2.0) / 3600.0; adfGeoTransform[1] = dxdelta / 3600.0; adfGeoTransform[2] = 0.0; adfGeoTransform[3] = (extent_max.y + dydelta/2.0) / 3600.0; adfGeoTransform[4] = 0.0; adfGeoTransform[5] = (-dydelta) / 3600.0; } if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize)) { return FALSE; } return TRUE; }
int USGSDEMDataset::LoadFromFile(FILE *InDem) { int i, j; int nRow, nColumn; int nVUnit, nGUnit; double dxdelta, dydelta; double dElevMax, dElevMin; int bNewFormat; int nCoordSystem; int nProfiles; char szDateBuffer[5]; DPoint2 corners[4]; // SW, NW, NE, SE DPoint2 extent_min, extent_max; int iUTMZone; // check for version of DEM format VSIFSeek(InDem, 864, 0); // Read DEM into matrix fscanf(InDem, "%d", &nRow); fscanf(InDem, "%d", &nColumn); bNewFormat = ((nRow!=1)||(nColumn!=1)); if (bNewFormat) { VSIFSeek(InDem, 1024, 0); // New Format fscanf(InDem, "%d", &i); fscanf(InDem, "%d", &j); if ((i!=1)||(j!=1 && j != 0)) // File OK? { VSIFSeek(InDem, 893, 0); // Undocumented Format (39109h1.dem) fscanf(InDem, "%d", &i); fscanf(InDem, "%d", &j); if ((i!=1)||(j!=1)) // File OK? { CPLError( CE_Failure, CPLE_AppDefined, "Does not appear to be a USGS DEM file." ); return FALSE; } else nDataStartOffset = 893; } else nDataStartOffset = 1024; } else nDataStartOffset = 864; VSIFSeek(InDem, 156, 0); fscanf(InDem, "%d", &nCoordSystem); fscanf(InDem, "%d", &iUTMZone); VSIFSeek(InDem, 528, 0); fscanf(InDem, "%d", &nGUnit); fscanf(InDem, "%d", &nVUnit); // Vertical Units in meters if (nVUnit==1) pszUnits = "ft"; else pszUnits = "m"; VSIFSeek(InDem, 816, 0); dxdelta = DConvert(InDem, 12); dydelta = DConvert(InDem, 12); fVRes = DConvert(InDem, 12); /* -------------------------------------------------------------------- */ /* Should we treat this as floating point, or GInt16. */ /* -------------------------------------------------------------------- */ if (nVUnit==1 || fVRes < 1.0) eNaturalDataFormat = GDT_Float32; else eNaturalDataFormat = GDT_Int16; /* -------------------------------------------------------------------- */ /* Read four corner coordinates. */ /* -------------------------------------------------------------------- */ VSIFSeek(InDem, 546, 0); for (i = 0; i < 4; i++) { corners[i].x = DConvert(InDem, 24); corners[i].y = DConvert(InDem, 24); } // find absolute extents of raw vales extent_min.x = MIN(corners[0].x, corners[1].x); extent_max.x = MAX(corners[2].x, corners[3].x); extent_min.y = MIN(corners[0].y, corners[3].y); extent_max.y = MAX(corners[1].y, corners[2].y); dElevMin = DConvert(InDem, 48); dElevMax = DConvert(InDem, 48); VSIFSeek(InDem, 858, 0); fscanf(InDem, "%d", &nProfiles); /* -------------------------------------------------------------------- */ /* Collect the spatial reference system. */ /* -------------------------------------------------------------------- */ OGRSpatialReference sr; int bNAD83 =TRUE; // OLD format header ends at byte 864 if (bNewFormat) { char szHorzDatum[3]; // year of data compilation VSIFSeek(InDem, 876, 0); fread(szDateBuffer, 4, 1, InDem); szDateBuffer[4] = 0; // Horizontal datum // 1=North American Datum 1927 (NAD 27) // 2=World Geodetic System 1972 (WGS 72) // 3=WGS 84 // 4=NAD 83 // 5=Old Hawaii Datum // 6=Puerto Rico Datum int datum; VSIFSeek(InDem, 890, 0); VSIFRead( szHorzDatum, 1, 2, InDem ); szHorzDatum[2] = '\0'; datum = atoi(szHorzDatum); switch (datum) { case 1: sr.SetWellKnownGeogCS( "NAD27" ); bNAD83 = FALSE; break; case 2: sr.SetWellKnownGeogCS( "WGS72" ); break; case 3: sr.SetWellKnownGeogCS( "WGS84" ); break; case 4: sr.SetWellKnownGeogCS( "NAD83" ); break; case -9: break; default: sr.SetWellKnownGeogCS( "NAD27" ); break; } } else { sr.SetWellKnownGeogCS( "NAD27" ); bNAD83 = FALSE; } if (nCoordSystem == 1) // UTM sr.SetUTM( iUTMZone, TRUE ); else if (nCoordSystem == 2) // state plane { if( nGUnit == 1 ) sr.SetStatePlane( iUTMZone, bNAD83, "Foot", CPLAtof(SRS_UL_US_FOOT_CONV) ); else sr.SetStatePlane( iUTMZone, bNAD83 ); } sr.exportToWkt( &pszProjection ); /* -------------------------------------------------------------------- */ /* For UTM we use the extents (really the UTM coordinates of */ /* the lat/long corners of the quad) to determine the size in */ /* pixels and lines, but we have to make the anchors be modulus */ /* the pixel size which what really gets used. */ /* -------------------------------------------------------------------- */ if (nCoordSystem == 1 // UTM || nCoordSystem == 2 // State Plane || nCoordSystem == -9999 ) // unknown { int njunk; double dxStart; // expand extents modulus the pixel size. extent_min.y = floor(extent_min.y/dydelta) * dydelta; extent_max.y = ceil(extent_max.y/dydelta) * dydelta; // Forceably compute X extents based on first profile and pixelsize. VSIFSeek(InDem, nDataStartOffset, 0); fscanf(InDem, "%d", &njunk); fscanf(InDem, "%d", &njunk); fscanf(InDem, "%d", &njunk); fscanf(InDem, "%d", &njunk); dxStart = DConvert(InDem, 24); nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5); nRasterXSize = nProfiles; adfGeoTransform[0] = dxStart - dxdelta/2.0; adfGeoTransform[1] = dxdelta; adfGeoTransform[2] = 0.0; adfGeoTransform[3] = extent_max.y + dydelta/2.0; adfGeoTransform[4] = 0.0; adfGeoTransform[5] = -dydelta; } /* -------------------------------------------------------------------- */ /* Geographic -- use corners directly. */ /* -------------------------------------------------------------------- */ else { nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5); nRasterXSize = nProfiles; // Translate extents from arc-seconds to decimal degrees. adfGeoTransform[0] = (extent_min.x - dxdelta/2.0) / 3600.0; adfGeoTransform[1] = dxdelta / 3600.0; adfGeoTransform[2] = 0.0; adfGeoTransform[3] = (extent_max.y + dydelta/2.0) / 3600.0; adfGeoTransform[4] = 0.0; adfGeoTransform[5] = (-dydelta) / 3600.0; } if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize)) { return FALSE; } return TRUE; }