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 *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )

{
    int         i;
    
/* -------------------------------------------------------------------- */
/*      Before trying SDTSOpen() we first verify that the first         */
/*      record is in fact a SDTS file descriptor record.                */
/* -------------------------------------------------------------------- */
    char        *pachLeader = (char *) poOpenInfo->pabyHeader;
    
    if( poOpenInfo->nHeaderBytes < 24 )
        return NULL;

    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( 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 = (GDALRasterBand **)
        VSICalloc(sizeof(GDALRasterBand *),poDS->nBands);

    for( 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") )
        oSRS.SetWellKnownGeogCS( "WGS84" );
    else
        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;

            while( (poRecord = oIDENFile.ReadRecord()) != NULL )
            {

                if( poRecord->GetStringSubfield( "IDEN", 0, "MODN", 0 ) == NULL )
                    continue;

                static const char* fields[][2] = { { "TITL", "TITLE" },
                                                   { "DAID", "DATASET_ID" },
                                                   { "DAST", "DATA_STRUCTURE" },
                                                   { "MPDT", "MAP_DATE" },
                                                   { "DCDT", "DATASET_CREATION_DATE" } };

                for (i = 0; i < (int)sizeof(fields) / (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();

    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;
}
Exemple #4
0
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;
}
static OGRErr importGeogCSFromXML(OGRSpatialReference *poSRS,
                                  CPLXMLNode *psCRS)

{
    const char *pszGeogName, *pszDatumName, *pszEllipsoidName, *pszPMName;
    double     dfSemiMajor, dfInvFlattening, dfPMOffset = 0.0;

/* -------------------------------------------------------------------- */
/*      Set the GEOGCS name from the srsName.                           */
/* -------------------------------------------------------------------- */
    pszGeogName =
        CPLGetXMLValue(psCRS, "srsName", "Unnamed GeogCS");

/* -------------------------------------------------------------------- */
/*      If we don't seem to have a detailed coordinate system           */
/*      definition, check if we can define based on an EPSG code.       */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psDatum;

    psDatum = CPLGetXMLNode(psCRS, "usesGeodeticDatum.GeodeticDatum");

    if (psDatum == NULL)
    {
        OGRSpatialReference oIdSRS;

        oIdSRS.SetLocalCS("dummy");
        importXMLAuthority(psCRS, &oIdSRS, "srsID", "LOCAL_CS");

        if (oIdSRS.GetAuthorityCode("LOCAL_CS") != NULL
            && oIdSRS.GetAuthorityName("LOCAL_CS") != NULL
            && EQUAL(oIdSRS.GetAuthorityName("LOCAL_CS"), "EPSG"))
        {
            return poSRS->importFromEPSG(
                atoi(oIdSRS.GetAuthorityCode("LOCAL_CS")));
        }
    }

/* -------------------------------------------------------------------- */
/*      Get datum name.                                                 */
/* -------------------------------------------------------------------- */
    pszDatumName =
        CPLGetXMLValue(psDatum, "datumName", "Unnamed Datum");

/* -------------------------------------------------------------------- */
/*      Get ellipsoid information.                                      */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psE;

    psE              = CPLGetXMLNode(psDatum, "usesEllipsoid.Ellipsoid");
    pszEllipsoidName =
        CPLGetXMLValue(psE, "ellipsoidName", "Unnamed Ellipsoid");

    dfSemiMajor = getNormalizedValue(psE, "semiMajorAxis", "Linear",
                                     SRS_WGS84_SEMIMAJOR);

    dfInvFlattening =
        getNormalizedValue(psE, "secondDefiningParameter.inverseFlattening",
                           "Unitless", 0.0);

    if (dfInvFlattening == 0.0)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Ellipsoid inverseFlattening corrupt or missing.");
        return OGRERR_CORRUPT_DATA;
    }

/* -------------------------------------------------------------------- */
/*      Get the prime meridian.                                         */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psPM;

    psPM = CPLGetXMLNode(psDatum, "usesPrimeMeridian.PrimeMeridian");
    if (psPM == NULL)
    {
        pszPMName  = "Greenwich";
        dfPMOffset = 0.0;
    }
    else
    {
        pszPMName = CPLGetXMLValue(psPM, "meridianName",
                                   "Unnamed Prime Meridian");
        dfPMOffset =
            getNormalizedValue(psPM, "greenwichLongitude.angle",
                               "Angular", 0.0);
    }

/* -------------------------------------------------------------------- */
/*      Set the geographic definition.                                  */
/* -------------------------------------------------------------------- */
    poSRS->SetGeogCS(pszGeogName, pszDatumName,
                     pszEllipsoidName, dfSemiMajor, dfInvFlattening,
                     pszPMName, dfPMOffset);

/* -------------------------------------------------------------------- */
/*      Look for angular units.  We don't check that all axes match     */
/*      at this time.                                                   */
/* -------------------------------------------------------------------- */
#ifdef notdef
    CPLXMLNode *psAxis;

    psAxis = CPLGetXMLNode(psGeo2DCRS,
                           "EllipsoidalCoordinateSystem.CoordinateAxis");
    importXMLUnits(psAxis, "AngularUnit", poSRS, "GEOGCS");
#endif

/* -------------------------------------------------------------------- */
/*      Can we set authorities for any of the levels?                   */
/* -------------------------------------------------------------------- */
    importXMLAuthority(psCRS, poSRS, "srsID", "GEOGCS");
    importXMLAuthority(psDatum, poSRS, "datumID", "GEOGCS|DATUM");
    importXMLAuthority(psE, poSRS, "ellipsoidID",
                       "GEOGCS|DATUM|SPHEROID");
    importXMLAuthority(psDatum, poSRS,
                       "usesPrimeMeridian.PrimeMeridian.meridianID",
                       "GEOGCS|PRIMEM");

    poSRS->Fixup();

    return OGRERR_NONE;
}