OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS,
                                const char *pszStatement,
                                OGRGeometry *poSpatialFilter,
                                const char *pszDialect )
{
    char* pszTmpDBName = (char*) CPLMalloc(256);
    sprintf(pszTmpDBName, "/vsimem/ogr2sqlite/temp_%p.db", pszTmpDBName);

    OGRSQLiteDataSource* poSQLiteDS = NULL;
    int nRet;
    int bSpatialiteDB = FALSE;

    CPLString osOldVal;
    const char* pszOldVal = CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", NULL);
    if( pszOldVal != NULL )
    {
        osOldVal = pszOldVal;
        pszOldVal = osOldVal.c_str();
    }

/* -------------------------------------------------------------------- */
/*      Create in-memory sqlite/spatialite DB                           */
/* -------------------------------------------------------------------- */

#ifdef HAVE_SPATIALITE

/* -------------------------------------------------------------------- */
/*      Creating an empty spatialite DB (with spatial_ref_sys populated */
/*      has a non-neglectable cost. So at the first attempt, let's make */
/*      one and cache it for later use.                                 */
/* -------------------------------------------------------------------- */
#if 1
    static vsi_l_offset nEmptyDBSize = 0;
    static GByte* pabyEmptyDB = NULL;
    {
        static void* hMutex = NULL;
        CPLMutexHolder oMutexHolder(&hMutex);
        static int bTried = FALSE;
        if( !bTried &&
            CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) )
        {
            bTried = TRUE;
            char* pszCachedFilename = (char*) CPLMalloc(256);
            sprintf(pszCachedFilename, "/vsimem/ogr2sqlite/reference_%p.db",pszCachedFilename);
            char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
            OGRSQLiteDataSource* poCachedDS = new OGRSQLiteDataSource();
            nRet = poCachedDS->Create( pszCachedFilename, papszOptions );
            CSLDestroy(papszOptions);
            papszOptions = NULL;
            delete poCachedDS;
            if( nRet )
                /* Note: the reference file keeps the ownership of the data, so that */
                /* it gets released with VSICleanupFileManager() */
                pabyEmptyDB = VSIGetMemFileBuffer( pszCachedFilename, &nEmptyDBSize, FALSE );
            CPLFree( pszCachedFilename );
        }
    }

    /* The following configuration option is usefull mostly for debugging/testing */
    if( pabyEmptyDB != NULL && CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) )
    {
        GByte* pabyEmptyDBClone = (GByte*)VSIMalloc(nEmptyDBSize);
        if( pabyEmptyDBClone == NULL )
        {
            CPLFree(pszTmpDBName);
            return NULL;
        }
        memcpy(pabyEmptyDBClone, pabyEmptyDB, nEmptyDBSize);
        VSIFCloseL(VSIFileFromMemBuffer( pszTmpDBName, pabyEmptyDBClone, nEmptyDBSize, TRUE ));

        poSQLiteDS = new OGRSQLiteDataSource();
        CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
        nRet = poSQLiteDS->Open( pszTmpDBName, TRUE );
        CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
        if( !nRet )
        {
            /* should not happen really ! */
            delete poSQLiteDS;
            VSIUnlink(pszTmpDBName);
            CPLFree(pszTmpDBName);
            return NULL;
        }
        bSpatialiteDB = TRUE;
    }
#else
    /* No caching version */
    poSQLiteDS = new OGRSQLiteDataSource();
    char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
    CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
    nRet = poSQLiteDS->Create( pszTmpDBName, papszOptions );
    CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
    CSLDestroy(papszOptions);
    papszOptions = NULL;
    if( nRet )
    {
        bSpatialiteDB = TRUE;
    }
#endif

    else
    {
        delete poSQLiteDS;
        poSQLiteDS = NULL;
#else // HAVE_SPATIALITE
    if( TRUE )
    {
#endif // HAVE_SPATIALITE
        poSQLiteDS = new OGRSQLiteDataSource();
        CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
        nRet = poSQLiteDS->Create( pszTmpDBName, NULL );
        CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
        if( !nRet )
        {
            delete poSQLiteDS;
            VSIUnlink(pszTmpDBName);
            CPLFree(pszTmpDBName);
            return NULL;
        }
    }

/* -------------------------------------------------------------------- */
/*      Attach the Virtual Table OGR2SQLITE module to it.               */
/* -------------------------------------------------------------------- */
    OGR2SQLITEModule* poModule = OGR2SQLITE_Setup(poDS, poSQLiteDS);
    sqlite3* hDB = poSQLiteDS->GetDB();

/* -------------------------------------------------------------------- */
/*      Analysze the statement to determine which tables will be used.  */
/* -------------------------------------------------------------------- */
    std::set<LayerDesc> oSetLayers;
    std::set<CPLString> oSetSpatialIndex;
    CPLString osModifiedSQL;
    OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers,
                                     oSetSpatialIndex, osModifiedSQL);
    std::set<LayerDesc>::iterator oIter = oSetLayers.begin();

    if( strcmp(pszStatement, osModifiedSQL.c_str()) != 0 )
        CPLDebug("OGR", "Modified SQL: %s", osModifiedSQL.c_str());
    pszStatement = osModifiedSQL.c_str(); /* do not use it anymore */

    int bFoundOGRStyle = ( osModifiedSQL.ifind("OGR_STYLE") != std::string::npos );

/* -------------------------------------------------------------------- */
/*      For each of those tables, create a Virtual Table.               */
/* -------------------------------------------------------------------- */
    for(; oIter != oSetLayers.end(); ++oIter)
    {
        const LayerDesc& oLayerDesc = *oIter;
        /*CPLDebug("OGR", "Layer desc : %s, %s, %s, %s",
                 oLayerDesc.osOriginalStr.c_str(),
                 oLayerDesc.osSubstitutedName.c_str(),
                 oLayerDesc.osDSName.c_str(),
                 oLayerDesc.osLayerName.c_str());*/

        CPLString osSQL;
        OGRLayer* poLayer = NULL;
        CPLString osTableName;
        int nExtraDS;
        if( oLayerDesc.osDSName.size() == 0 )
        {
            poLayer = poDS->GetLayerByName(oLayerDesc.osLayerName);
            /* Might be a false positive (unlikely) */
            if( poLayer == NULL )
                continue;

            osTableName = oLayerDesc.osLayerName;

            nExtraDS = -1;

            osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)",
                         OGRSQLiteEscapeName(osTableName).c_str(),
                         nExtraDS,
                         OGRSQLiteEscape(osTableName).c_str(),
                         bFoundOGRStyle);
        }
        else
        {
            OGRDataSource* poOtherDS = (OGRDataSource* )
                OGROpen(oLayerDesc.osDSName, FALSE, NULL);
            if( poOtherDS == NULL )
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Cannot open datasource '%s'",
                         oLayerDesc.osDSName.c_str() );
                delete poSQLiteDS;
                VSIUnlink(pszTmpDBName);
                CPLFree(pszTmpDBName);
                return NULL;
            }
            
            poLayer = poOtherDS->GetLayerByName(oLayerDesc.osLayerName);
            if( poLayer == NULL )
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Cannot find layer '%s' in '%s'",
                         oLayerDesc.osLayerName.c_str(),
                         oLayerDesc.osDSName.c_str() );
                delete poOtherDS;
                delete poSQLiteDS;
                VSIUnlink(pszTmpDBName);
                CPLFree(pszTmpDBName);
                return NULL;
            }

            osTableName = oLayerDesc.osSubstitutedName;

            nExtraDS = OGR2SQLITE_AddExtraDS(poModule, poOtherDS);

            osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)",
                         OGRSQLiteEscapeName(osTableName).c_str(),
                         nExtraDS,
                         OGRSQLiteEscape(oLayerDesc.osLayerName).c_str(),
                         bFoundOGRStyle);
        }

        char* pszErrMsg = NULL;
        int rc = sqlite3_exec( hDB, osSQL.c_str(),
                               NULL, NULL, &pszErrMsg );
        if( rc != SQLITE_OK )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Cannot create virtual table for layer '%s' : %s",
                     osTableName.c_str(), pszErrMsg);
            sqlite3_free(pszErrMsg);
            continue;
        }

        if( poLayer->GetGeomType() == wkbNone )
            continue;

        CPLString osGeomColRaw(OGR2SQLITE_GetNameForGeometryColumn(poLayer));
        const char* pszGeomColRaw = osGeomColRaw.c_str();

        CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw));
        const char* pszGeomColEscaped = osGeomColEscaped.c_str();

        CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName));
        const char* pszLayerNameEscaped = osLayerNameEscaped.c_str();

        CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s",
                        oLayerDesc.osLayerName.c_str(), pszGeomColRaw));
        CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw));

        /* Make sure that the SRS is injected in spatial_ref_sys */
        OGRSpatialReference* poSRS = poLayer->GetSpatialRef();
        int nSRSId = poSQLiteDS->GetUndefinedSRID();
        if( poSRS != NULL )
            nSRSId = poSQLiteDS->FetchSRSId(poSRS);

        int bCreateSpatialIndex = FALSE;
        if( !bSpatialiteDB )
        {
            osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                        "f_geometry_column, geometry_format, geometry_type, "
                        "coord_dimension, srid) "
                        "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)",
                        pszLayerNameEscaped,
                        pszGeomColEscaped,
                         (int) wkbFlatten(poLayer->GetGeomType()),
                        ( poLayer->GetGeomType() & wkb25DBit ) ? 3 : 2,
                        nSRSId);
        }
#ifdef HAVE_SPATIALITE
        else
        {
            /* We detect the need for creating a spatial index by 2 means : */

            /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */
            /*   table in the SQL --> old/traditionnal way of requesting spatial indices */
            /*   with spatialite. */

            std::set<LayerDesc>::iterator oIter2 = oSetLayers.begin();
            for(; oIter2 != oSetLayers.end(); ++oIter2)
            {
                const LayerDesc& oLayerDescIter = *oIter2;
                if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) )
                {
                     bCreateSpatialIndex = TRUE;
                     break;
                }
            }

            /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */
            if( !bCreateSpatialIndex )
            {
                std::set<CPLString>::iterator oIter3 = oSetSpatialIndex.begin();
                for(; oIter3 != oSetSpatialIndex.end(); ++oIter3)
                {
                    const CPLString& osNameIter = *oIter3;
                    if( EQUAL(osNameIter, oLayerDesc.osLayerName) )
                    {
                        bCreateSpatialIndex = TRUE;
                        break;
                    }
                }
            }

            if( poSQLiteDS->HasSpatialite4Layout() )
            {
                int nGeomType = poLayer->GetGeomType();
                int nCoordDimension = 2;
                if( nGeomType & wkb25DBit )
                {
                    nGeomType += 1000;
                    nCoordDimension = 3;
                }

                osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                            "f_geometry_column, geometry_type, coord_dimension, "
                            "srid, spatial_index_enabled) "
                            "VALUES ('%s',Lower('%s'),%d ,%d ,%d, %d)",
                            pszLayerNameEscaped,
                            pszGeomColEscaped, nGeomType,
                            nCoordDimension,
                            nSRSId, bCreateSpatialIndex );
            }
            else
            {
                const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType());
                if (pszGeometryType[0] == '\0')
                    pszGeometryType = "GEOMETRY";

                osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                            "f_geometry_column, type, coord_dimension, "
                            "srid, spatial_index_enabled) "
                            "VALUES ('%s','%s','%s','%s',%d, %d)",
                            pszLayerNameEscaped,
                            pszGeomColEscaped, pszGeometryType,
                            ( poLayer->GetGeomType() & wkb25DBit ) ? "XYZ" : "XY",
                            nSRSId, bCreateSpatialIndex );
            }
        }
#endif // HAVE_SPATIALITE
        sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );

#ifdef HAVE_SPATIALITE
/* -------------------------------------------------------------------- */
/*      Should we create a spatial index ?.                             */
/* -------------------------------------------------------------------- */
        if( !bSpatialiteDB || !bCreateSpatialIndex )
            continue;

        CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str());

        /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */
#ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING "
                     "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)",
                     osIdxNameEscaped.c_str(),
                     nExtraDS,
                     OGRSQLiteEscape(oLayerDesc.osLayerName).c_str());

        rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
        if( rc != SQLITE_OK )
        {
            CPLDebug("SQLITE",
                     "Error occured during spatial index creation : %s",
                     sqlite3_errmsg(hDB));
        }
#else //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
        rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL );

        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" "
                     "USING rtree(pkid, xmin, xmax, ymin, ymax)",
                      osIdxNameEscaped.c_str());

        if( rc == SQLITE_OK )
            rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );

        sqlite3_stmt *hStmt = NULL;
        if( rc == SQLITE_OK )
        {
            const char* pszInsertInto = CPLSPrintf(
                "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) "
                "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str());
            rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL);
        }

        OGRFeature* poFeature;
        OGREnvelope sEnvelope;
        OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer);
        poLayer->ResetReading();

        while( rc == SQLITE_OK &&
               (poFeature = poLayer->GetNextFeature()) != NULL )
        {
            OGRGeometry* poGeom = poFeature->GetGeometryRef();
            if( poGeom != NULL && !poGeom->IsEmpty() )
            {
                poGeom->getEnvelope(&sEnvelope);
                sqlite3_bind_int64(hStmt, 1,
                                   (sqlite3_int64) poFeature->GetFID() );
                sqlite3_bind_double(hStmt, 2, sEnvelope.MinX);
                sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX);
                sqlite3_bind_double(hStmt, 4, sEnvelope.MinY);
                sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY);
                rc = sqlite3_step(hStmt);
                if( rc == SQLITE_OK || rc == SQLITE_DONE )
                    rc = sqlite3_reset(hStmt);
            }
            delete poFeature;
        }

        poLayer->SetIgnoredFields(NULL);

        sqlite3_finalize(hStmt);

        if( rc == SQLITE_OK )
            rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL );
        else
        {
            CPLDebug("SQLITE",
                     "Error occured during spatial index creation : %s",
                     sqlite3_errmsg(hDB));
            rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL );
        }
#endif //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX

#endif // HAVE_SPATIALITE

    }

/* -------------------------------------------------------------------- */
/*      Reload, so that virtual tables are recognized                   */
/* -------------------------------------------------------------------- */
    poSQLiteDS->ReloadLayers();

/* -------------------------------------------------------------------- */
/*      Prepare the statement.                                          */
/* -------------------------------------------------------------------- */
    /* This will speed-up layer creation */
    /* ORDER BY are costly to evaluate and are not necessary to establish */
    /* the layer definition. */
    int bUseStatementForGetNextFeature = TRUE;
    int bEmptyLayer = FALSE;

    sqlite3_stmt *hSQLStmt = NULL;
    int rc = sqlite3_prepare( hDB,
                              pszStatement, strlen(pszStatement),
                              &hSQLStmt, NULL );

    if( rc != SQLITE_OK )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
                pszStatement, sqlite3_errmsg(hDB) );

        if( hSQLStmt != NULL )
        {
            sqlite3_finalize( hSQLStmt );
        }

        delete poSQLiteDS;
        VSIUnlink(pszTmpDBName);
        CPLFree(pszTmpDBName);

        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Do we get a resultset?                                          */
/* -------------------------------------------------------------------- */
    rc = sqlite3_step( hSQLStmt );
    if( rc != SQLITE_ROW )
    {
        if ( rc != SQLITE_DONE )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                  "In ExecuteSQL(): sqlite3_step(%s):\n  %s",
                  pszStatement, sqlite3_errmsg(hDB) );

            sqlite3_finalize( hSQLStmt );

            delete poSQLiteDS;
            VSIUnlink(pszTmpDBName);
            CPLFree(pszTmpDBName);

            return NULL;
        }

        if( !EQUALN(pszStatement, "SELECT ", 7) )
        {

            sqlite3_finalize( hSQLStmt );

            delete poSQLiteDS;
            VSIUnlink(pszTmpDBName);
            CPLFree(pszTmpDBName);

            return NULL;
        }

        bUseStatementForGetNextFeature = FALSE;
        bEmptyLayer = TRUE;
    }

/* -------------------------------------------------------------------- */
/*      Create layer.                                                   */
/* -------------------------------------------------------------------- */
    OGRSQLiteSelectLayer *poLayer = NULL;

    poLayer = new OGRSQLiteExecuteSQLLayer( pszTmpDBName,
                                            poSQLiteDS, pszStatement, hSQLStmt,
                                            bUseStatementForGetNextFeature, bEmptyLayer );

    if( poSpatialFilter != NULL )
        poLayer->SetSpatialFilter( poSpatialFilter );

    return poLayer;
}

/************************************************************************/
/*                   OGRSQLiteGetReferencedLayers()                     */
/************************************************************************/

std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char* pszStatement)
{
/* -------------------------------------------------------------------- */
/*      Analysze the statement to determine which tables will be used.  */
/* -------------------------------------------------------------------- */
    std::set<LayerDesc> oSetLayers;
    std::set<CPLString> oSetSpatialIndex;
    CPLString osModifiedSQL;
    OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers,
                                     oSetSpatialIndex, osModifiedSQL);

    return oSetLayers;
}
int OGRGFTResultLayer::RunSQL()
{
    CPLString osChangedSQL(osSQL);
    int bHasSetLimit = FALSE;
    OGRGFTTableLayer* poTableLayer = NULL;
    OGRFeatureDefn* poTableDefn = NULL;
    CPLString osTableId;
    if (STARTS_WITH_CI(osSQL.c_str(), "SELECT"))
    {
        size_t nPosFROM = osSQL.ifind(" FROM ");
        if (nPosFROM == std::string::npos)
        {
            CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed. Missing FROM in SELECT");
            return FALSE;
        }
        CPLString osReminder;
        nPosFROM += 6;
        osTableId = OGRGFTExtractTableID(osSQL.c_str() + nPosFROM, osReminder);

        poTableLayer = (OGRGFTTableLayer*) poDS->GetLayerByName(osTableId);
        if (poTableLayer != NULL)
            poTableDefn = poTableLayer->GetLayerDefn();

        if (poTableLayer != NULL &&
            poTableLayer->GetTableId().size() &&
            !EQUAL(osTableId, poTableLayer->GetTableId()))
        {
            osChangedSQL = osSQL;
            osChangedSQL.resize(nPosFROM);
            osChangedSQL += poTableLayer->GetTableId();
            osChangedSQL += osReminder;
            osSQL = osChangedSQL;
            CPLDebug("GFT", "Patching table name (%s) to table id (%s)",
                     osTableId.c_str(), poTableLayer->GetTableId().c_str());
        }

        int nFeaturesToFetch = GetFeaturesToFetch();
        if (osSQL.ifind(" OFFSET ") == std::string::npos &&
            osSQL.ifind(" LIMIT ") == std::string::npos &&
            nFeaturesToFetch > 0)
        {
            osChangedSQL += CPLSPrintf(" LIMIT %d", nFeaturesToFetch);
            bHasSetLimit = TRUE;
        }
    }
    else
    {
        bGotAllRows = bEOF = TRUE;
        poFeatureDefn->SetGeomType( wkbNone );
    }

    CPLHTTPResult * psResult = poDS->RunSQL(osChangedSQL);

    if (psResult == NULL)
        return FALSE;

    char* pszLine = (char*) psResult->pabyData;
    if (pszLine == NULL ||
        psResult->pszErrBuf != NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed");
        CPLHTTPDestroyResult(psResult);
        return FALSE;
    }

    if (STARTS_WITH_CI(osSQL.c_str(), "SELECT") ||
        EQUAL(osSQL.c_str(), "SHOW TABLES") ||
        STARTS_WITH_CI(osSQL.c_str(), "DESCRIBE"))
    {
        ParseCSVResponse(pszLine, aosRows);
        if (aosRows.size() > 0)
        {
            char** papszTokens = OGRGFTCSVSplitLine(aosRows[0], ',');
            for(int i=0;papszTokens && papszTokens[i];i++)
            {
                CPLString osLaunderedColName(LaunderColName(papszTokens[i]));
                int iIndex = (poTableDefn) ? poTableDefn->GetFieldIndex(osLaunderedColName) : -1;
                if (iIndex >= 0)
                {
                    poFeatureDefn->AddFieldDefn(poTableDefn->GetFieldDefn(iIndex));
                    if (iIndex == poTableLayer->GetGeometryFieldIndex())
                        iGeometryField = i;
                    if (iIndex == poTableLayer->GetLatitudeFieldIndex())
                        iLatitudeField = i;
                    if (iIndex == poTableLayer->GetLongitudeFieldIndex())
                        iLongitudeField = i;
                }
                else
                {
                    OGRFieldType eType = OFTString;
                    if (EQUAL(osLaunderedColName, "COUNT()"))
                        eType = OFTInteger;
                    OGRFieldDefn oFieldDefn(osLaunderedColName, eType);
                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
                }
            }
            CSLDestroy(papszTokens);

            aosRows.erase(aosRows.begin());
        }

        if (iLatitudeField >= 0 && iLongitudeField >= 0)
        {
            iGeometryField = iLatitudeField;
            poFeatureDefn->SetGeomType( wkbPoint );
        }

        if (bHasSetLimit)
            bGotAllRows = bEOF = (int)aosRows.size() < GetFeaturesToFetch();
        else
            bGotAllRows = bEOF = TRUE;
    }

    SetGeomFieldName();

    CPLHTTPDestroyResult(psResult);

    return TRUE;
}
VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archiveFilename, 
                                                               const char* fileInArchiveName)
{
    VSIArchiveReader* poReader = CreateReader(archiveFilename);

    if (poReader == NULL)
    {
        return NULL;
    }

    if (fileInArchiveName == NULL || strlen(fileInArchiveName) == 0)
    {
        if (poReader->GotoFirstFile() == FALSE)
        {
            delete(poReader);
            return NULL;
        }

        /* Skip optionnal leading subdir */
        CPLString osFileName = poReader->GetFileName();
        const char* fileName = osFileName.c_str();
        if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
        {
            if (poReader->GotoNextFile() == FALSE)
            {
                delete(poReader);
                return NULL;
            }
        }

        if (poReader->GotoNextFile())
        {
            CPLString msg;
            msg.Printf("Support only 1 file in archive file %s when no explicit in-archive filename is specified",
                       archiveFilename);
            const VSIArchiveContent* content = GetContentOfArchive(archiveFilename, poReader);
            if (content)
            {
                int i;
                msg += "\nYou could try one of the following :\n";
                for(i=0;i<content->nEntries;i++)
                {
                    msg += CPLString().Printf("  %s/%s/%s\n", GetPrefix(), archiveFilename, content->entries[i].fileName);
                }
            }

            CPLError(CE_Failure, CPLE_NotSupported, "%s", msg.c_str());

            delete(poReader);
            return NULL;
        }
    }
    else
    {
        const VSIArchiveEntry* archiveEntry = NULL;
        if (FindFileInArchive(archiveFilename, fileInArchiveName, &archiveEntry) == FALSE ||
            archiveEntry->bIsDir)
        {
            delete(poReader);
            return NULL;
        }
        if (!poReader->GotoFileOffset(archiveEntry->file_pos))
        {
            delete poReader;
            return NULL;
        }
    }
    return poReader;
}
Exemple #4
0
    unsigned int ISIS2Dataset::WriteFormatting(VSILFILE *fpLabel, CPLString data)

    {
        int ret = VSIFPrintfL(fpLabel,"%s\n", data.c_str());
        return ret;
    }
Exemple #5
0
GDALDataset *ISIS2Dataset::Create(const char* pszFilename,
                                  int nXSize, int nYSize, int nBands,
                                  GDALDataType eType, char** papszParmList) {

    /* Verify settings. In Isis 2 core pixel values can be represented in
     * three different ways : 1, 2 4, or 8 Bytes */
    if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_Float32
        && eType != GDT_UInt16 && eType != GDT_Float64 ){
        CPLError(CE_Failure, CPLE_AppDefined,
                 "The ISIS2 driver does not supporting creating files of type %s.",
                 GDALGetDataTypeName( eType ) );
        return NULL;
    }

    /*  (SAMPLE, LINE, BAND) - Band Sequential (BSQ) - default choice
        (SAMPLE, BAND, LINE) - Band Interleaved by Line (BIL)
        (BAND, SAMPLE, LINE) - Band Interleaved by Pixel (BIP) */
    const char *pszInterleaving = "(SAMPLE,LINE,BAND)";
    const char *pszInterleavingParam = CSLFetchNameValue( papszParmList, "INTERLEAVE" );
    if ( pszInterleavingParam ) {
        if ( EQUALN( pszInterleavingParam, "bip", 3 ) )
            pszInterleaving = "(BAND,SAMPLE,LINE)";
        else if ( EQUALN( pszInterleavingParam, "bil", 3 ) )
            pszInterleaving = "(SAMPLE,BAND,LINE)";
        else
            pszInterleaving = "(SAMPLE,LINE,BAND)";
    }

    /* default labeling method is attached */
    bool bAttachedLabelingMethod = true;
    /* check if labeling method is set : check the all three first chars */
    const char *pszLabelingMethod = CSLFetchNameValue( papszParmList, "LABELING_METHOD" );
    if ( pszLabelingMethod ){
        if ( EQUALN( pszLabelingMethod, "detached", 3 ) ){
            bAttachedLabelingMethod = false;
        }
        if ( EQUALN( pszLabelingMethod, "attached", 3 ) ){
            bAttachedLabelingMethod = true;
        }
    }

    /*  set the label and data files */
    CPLString osLabelFile, osRasterFile, osOutFile;
    if( bAttachedLabelingMethod ) {
        osLabelFile = "";
        osRasterFile = pszFilename;
        osOutFile = osRasterFile;
    }
    else
    {
        CPLString sExtension = "cub";
        const char* pszExtension = CSLFetchNameValue( papszParmList, "IMAGE_EXTENSION" );
        if( pszExtension ){
            sExtension = pszExtension;
        }

        if( EQUAL(CPLGetExtension( pszFilename ), sExtension) )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "IMAGE_EXTENSION (%s) cannot match LABEL file extension.",
                      sExtension.c_str() );
            return NULL;
        }

        osLabelFile = pszFilename;
        osRasterFile = CPLResetExtension( osLabelFile, sExtension );
        osOutFile = osLabelFile;
    }

    const char *pszObject = CSLFetchNameValue( papszParmList, "OBJECT" );
    CPLString sObject = "QUBE"; // default choice
    if (pszObject) {
        if ( EQUAL( pszObject, "IMAGE") ){
            sObject = "IMAGE";
        }
        if ( EQUAL( pszObject, "SPECTRAL_QUBE")){
            sObject = "SPECTRAL_QUBE";
        }
    }

    GUIntBig iRecords = ISIS2Dataset::RecordSizeCalculation(nXSize, nYSize, nBands, eType);
    GUIntBig iLabelRecords(2);

    CPLDebug("ISIS2","irecord = %i",static_cast<int>(iRecords));

    if( bAttachedLabelingMethod ) 
    {
        ISIS2Dataset::WriteLabel(osRasterFile, "", sObject, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords, true);
    }
    else
    {
        ISIS2Dataset::WriteLabel(osLabelFile, osRasterFile, sObject, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords);
    }

    if( !ISIS2Dataset::WriteRaster(osRasterFile, bAttachedLabelingMethod, 
                                   iRecords, iLabelRecords, eType, 
                                   pszInterleaving) )
        return NULL;

    return (GDALDataset *) GDALOpen( osOutFile, GA_Update );
}
Exemple #6
0
char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )

{
    CPLString osExpr;

/* -------------------------------------------------------------------- */
/*      Handle constants.                                               */
/* -------------------------------------------------------------------- */
    if( eNodeType == SNT_CONSTANT )
    {
        if( is_null )
            return CPLStrdup("NULL");

        if( field_type == SWQ_INTEGER || field_type == SWQ_INTEGER64 ||
            field_type == SWQ_BOOLEAN )
            osExpr.Printf( CPL_FRMT_GIB, int_value );
        else if( field_type == SWQ_FLOAT )
        {
            osExpr.Printf( "%.15g", float_value );
            // Make sure this is interpreted as a floating point value
            // and not as an integer later.
            if( strchr(osExpr, '.') == nullptr && strchr(osExpr, 'e') == nullptr &&
                strchr(osExpr, 'E') == nullptr )
                osExpr += '.';
        }
        else
        {
            osExpr = Quote( string_value );
        }

        return CPLStrdup(osExpr);
    }

/* -------------------------------------------------------------------- */
/*      Handle columns.                                                 */
/* -------------------------------------------------------------------- */
    if( eNodeType == SNT_COLUMN )
    {
        if( field_list == nullptr )
        {
            if( table_name )
                osExpr.Printf(
                    "%s.%s",
                    QuoteIfNecessary(table_name, chColumnQuote).c_str(),
                    QuoteIfNecessary(string_value, chColumnQuote).c_str() );
            else
                osExpr.Printf(
                    "%s",
                    QuoteIfNecessary(string_value, chColumnQuote).c_str() );
        }
        else if( field_index != -1
            && table_index < field_list->table_count
            && table_index > 0 )
        {
            // We deliberately browse through the list starting from the end
            // This is for the case where the FID column exists both as
            // FID and then real_fid_name. We want real_fid_name to be used
            for( int i = field_list->count - 1; i >= 0; i-- )
            {
                if( field_list->table_ids[i] == table_index &&
                    field_list->ids[i] == field_index )
                {
                    osExpr.Printf( "%s.%s",
                                   QuoteIfNecessary(field_list->table_defs[table_index].table_name, chColumnQuote).c_str(),
                                   QuoteIfNecessary(field_list->names[i], chColumnQuote).c_str() );
                    break;
                }
            }
        }
        else if( field_index != -1 )
        {
            // We deliberately browse through the list starting from the end
            // This is for the case where the FID column exists both as
            // FID and then real_fid_name. We want real_fid_name to be used
            for( int i = field_list->count - 1; i >= 0; i-- )
            {
                if( field_list->table_ids[i] == table_index &&
                    field_list->ids[i] == field_index )
                {
                    osExpr.Printf( "%s", QuoteIfNecessary(field_list->names[i], chColumnQuote).c_str() );
                    break;
                }
            }
        }

        if( osExpr.empty() )
        {
            return CPLStrdup(CPLSPrintf("%c%c", chColumnQuote, chColumnQuote));
        }

        // The string is just alphanum and not a reserved SQL keyword,
        // no needs to quote and escape.
        return CPLStrdup(osExpr.c_str());
    }

/* -------------------------------------------------------------------- */
/*      Operation - start by unparsing all the subexpressions.          */
/* -------------------------------------------------------------------- */
    std::vector<char*> apszSubExpr;

    for( int i = 0; i < nSubExprCount; i++ )
        apszSubExpr.push_back( papoSubExpr[i]->Unparse(field_list, chColumnQuote) );

    osExpr = UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);

/* -------------------------------------------------------------------- */
/*      cleanup subexpressions.                                         */
/* -------------------------------------------------------------------- */
    for( int i = 0; i < nSubExprCount; i++ )
        CPLFree( apszSubExpr[i] );

    return CPLStrdup( osExpr.c_str() );
}
Exemple #7
0
int main( int argc, char ** argv )

{
    const char         *pszLocX = NULL, *pszLocY = NULL;
    const char         *pszSrcFilename = NULL;
    const char         *pszSourceSRS = NULL;
    std::vector<int>   anBandList;
    bool               bAsXML = false, bLIFOnly = false;
    bool               bQuiet = false, bValOnly = false;

    GDALAllRegister();
    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

/* -------------------------------------------------------------------- */
/*      Parse arguments.                                                */
/* -------------------------------------------------------------------- */
    int i;

    for( i = 1; i < argc; i++ )
    {
        if( EQUAL(argv[i], "--utility_version") )
        {
            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            return 0;
        }
        else if( EQUAL(argv[i],"-b") && i < argc-1 )
        {
            anBandList.push_back( atoi(argv[++i]) );
        }
        else if( EQUAL(argv[i],"-l_srs") && i < argc-1 )
        {
            pszSourceSRS = SanitizeSRS(argv[++i]);
        }
        else if( EQUAL(argv[i],"-geoloc") )
        {
            pszSourceSRS = "-geoloc";
        }
        else if( EQUAL(argv[i],"-wgs84") )
        {
            pszSourceSRS = SanitizeSRS("WGS84");
        }
        else if( EQUAL(argv[i],"-xml") )
        {
            bAsXML = true;
        }
        else if( EQUAL(argv[i],"-lifonly") )
        {
            bLIFOnly = true;
            bQuiet = true;
        }
        else if( EQUAL(argv[i],"-valonly") )
        {
            bValOnly = true;
            bQuiet = true;
        }
        else if( argv[i][0] == '-' && !isdigit(argv[i][1]) )
            Usage();

        else if( pszSrcFilename == NULL )
            pszSrcFilename = argv[i];

        else if( pszLocX == NULL )
            pszLocX = argv[i];

        else if( pszLocY == NULL )
            pszLocY = argv[i];

        else
            Usage();
    }

    if( pszSrcFilename == NULL || (pszLocX != NULL && pszLocY == NULL) )
        Usage();

/* -------------------------------------------------------------------- */
/*      Open source file.                                               */
/* -------------------------------------------------------------------- */
    GDALDatasetH hSrcDS = NULL;

    hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
    if( hSrcDS == NULL )
        exit( 1 );

/* -------------------------------------------------------------------- */
/*      Setup coordinate transformation, if required                    */
/* -------------------------------------------------------------------- */
    OGRSpatialReferenceH hSrcSRS = NULL, hTrgSRS = NULL;
    OGRCoordinateTransformationH hCT = NULL;
    if( pszSourceSRS != NULL && !EQUAL(pszSourceSRS,"-geoloc") )
    {

        hSrcSRS = OSRNewSpatialReference( pszSourceSRS );
        hTrgSRS = OSRNewSpatialReference( GDALGetProjectionRef( hSrcDS ) );

        hCT = OCTNewCoordinateTransformation( hSrcSRS, hTrgSRS );
        if( hCT == NULL )
            exit( 1 );
    }

/* -------------------------------------------------------------------- */
/*      If no bands were requested, we will query them all.             */
/* -------------------------------------------------------------------- */
    if( anBandList.size() == 0 )
    {
        for( i = 0; i < GDALGetRasterCount( hSrcDS ); i++ )
            anBandList.push_back( i+1 );
    }
    
/* -------------------------------------------------------------------- */
/*      Turn the location into a pixel and line location.               */
/* -------------------------------------------------------------------- */
    int inputAvailable = 1;
    double dfGeoX;
    double dfGeoY;
    CPLString osXML;

    if( pszLocX == NULL && pszLocY == NULL )
    {
        if (fscanf(stdin, "%lf %lf", &dfGeoX, &dfGeoY) != 2)
        {
            inputAvailable = 0;
        }
    }
    else
    {
        dfGeoX = CPLAtof(pszLocX);
        dfGeoY = CPLAtof(pszLocY);
    }

    while (inputAvailable)
    {
        int iPixel, iLine;

        if (hCT)
        {
            if( !OCTTransform( hCT, 1, &dfGeoX, &dfGeoY, NULL ) )
                exit( 1 );
        }
    
        if( pszSourceSRS != NULL )
        {
            double adfGeoTransform[6], adfInvGeoTransform[6];
    
            if( GDALGetGeoTransform( hSrcDS, adfGeoTransform ) != CE_None )
                exit( 1 );
    
            GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform );
    
            iPixel = (int) floor(
                adfInvGeoTransform[0] 
                + adfInvGeoTransform[1] * dfGeoX
                + adfInvGeoTransform[2] * dfGeoY );
            iLine = (int) floor(
                adfInvGeoTransform[3] 
                + adfInvGeoTransform[4] * dfGeoX
                + adfInvGeoTransform[5] * dfGeoY );
        }
        else
        {
            iPixel = (int) floor(dfGeoX);
            iLine  = (int) floor(dfGeoY);
        }

    /* -------------------------------------------------------------------- */
    /*      Prepare report.                                                 */
    /* -------------------------------------------------------------------- */
        CPLString osLine;
    
        if( bAsXML )
        {
            osLine.Printf( "<Report pixel=\"%d\" line=\"%d\">", 
                          iPixel, iLine );
            osXML += osLine;
        }
        else if( !bQuiet )
        {
            printf( "Report:\n" );
            printf( "  Location: (%dP,%dL)\n", iPixel, iLine );
        }

        int bPixelReport = TRUE;

        if( iPixel < 0 || iLine < 0 
            || iPixel >= GDALGetRasterXSize( hSrcDS )
            || iLine  >= GDALGetRasterYSize( hSrcDS ) )
        {
            if( bAsXML )
                osXML += "<Alert>Location is off this file! No further details to report.</Alert>";
            else if( bValOnly )
                printf("\n");
            else if( !bQuiet )
                printf( "\nLocation is off this file! No further details to report.\n");
            bPixelReport = FALSE;
        }
        
    /* -------------------------------------------------------------------- */
    /*      Process each band.                                              */
    /* -------------------------------------------------------------------- */
        for( i = 0; bPixelReport && i < (int) anBandList.size(); i++ )
        {
            GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, anBandList[i] );
            if (hBand == NULL)
                continue;
    
            if( bAsXML )
            {
                osLine.Printf( "<BandReport band=\"%d\">", anBandList[i] );
                osXML += osLine;
            }
            else if( !bQuiet )
            {
                printf( "  Band %d:\n", anBandList[i] );
            }
    
    /* -------------------------------------------------------------------- */
    /*      Request location info for this location.  It is possible        */
    /*      only the VRT driver actually supports this.                     */
    /* -------------------------------------------------------------------- */
            CPLString osItem;
            
            osItem.Printf( "Pixel_%d_%d", iPixel, iLine );
            
            const char *pszLI = GDALGetMetadataItem( hBand, osItem, "LocationInfo");
    
            if( pszLI != NULL )
            {
                if( bAsXML )
                    osXML += pszLI;
                else if( !bQuiet )
                    printf( "    %s\n", pszLI );
                else if( bLIFOnly )
                {
                    /* Extract all files, if any. */
                 
                    CPLXMLNode *psRoot = CPLParseXMLString( pszLI );
                    
                    if( psRoot != NULL 
                        && psRoot->psChild != NULL
                        && psRoot->eType == CXT_Element
                        && EQUAL(psRoot->pszValue,"LocationInfo") )
                    {
                        CPLXMLNode *psNode;
    
                        for( psNode = psRoot->psChild;
                             psNode != NULL;
                             psNode = psNode->psNext )
                        {
                            if( psNode->eType == CXT_Element
                                && EQUAL(psNode->pszValue,"File") 
                                && psNode->psChild != NULL )
                            {
                                char* pszUnescaped = CPLUnescapeString(
                                    psNode->psChild->pszValue, NULL, CPLES_XML);
                                printf( "%s\n", pszUnescaped );
                                CPLFree(pszUnescaped);
                            }
                        }
                    }
                    CPLDestroyXMLNode( psRoot );
                }
            }
    
    /* -------------------------------------------------------------------- */
    /*      Report the pixel value of this band.                            */
    /* -------------------------------------------------------------------- */
            double adfPixel[2];
    
            if( GDALRasterIO( hBand, GF_Read, iPixel, iLine, 1, 1, 
                              adfPixel, 1, 1, GDT_CFloat64, 0, 0) == CE_None )
            {
                CPLString osValue;
    
                if( GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ) )
                    osValue.Printf( "%.15g+%.15gi", adfPixel[0], adfPixel[1] );
                else
                    osValue.Printf( "%.15g", adfPixel[0] );
    
                if( bAsXML )
                {
                    osXML += "<Value>";
                    osXML += osValue;
                    osXML += "</Value>";
                }
                else if( !bQuiet )
                    printf( "    Value: %s\n", osValue.c_str() );
                else if( bValOnly )
                    printf( "%s\n", osValue.c_str() );
    
                // Report unscaled if we have scale/offset values.
                int bSuccess;
                
                double dfOffset = GDALGetRasterOffset( hBand, &bSuccess );
                double dfScale  = GDALGetRasterScale( hBand, &bSuccess );
    
                if( dfOffset != 0.0 || dfScale != 1.0 )
                {
                    adfPixel[0] = adfPixel[0] * dfScale + dfOffset;
                    adfPixel[1] = adfPixel[1] * dfScale + dfOffset;
    
                    if( GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ) )
                        osValue.Printf( "%.15g+%.15gi", adfPixel[0], adfPixel[1] );
                    else
                        osValue.Printf( "%.15g", adfPixel[0] );
    
                    if( bAsXML )
                    {
                        osXML += "<DescaledValue>";
                        osXML += osValue;
                        osXML += "</DescaledValue>";
                    }
                    else if( !bQuiet )
                        printf( "    Descaled Value: %s\n", osValue.c_str() );
                }
            }
    
            if( bAsXML )
                osXML += "</BandReport>";
        }

        osXML += "</Report>";
    
        if( (pszLocX != NULL && pszLocY != NULL)  ||
            (fscanf(stdin, "%lf %lf", &dfGeoX, &dfGeoY) != 2) )
        {
            inputAvailable = 0;
        }
            
    }

/* -------------------------------------------------------------------- */
/*      Finalize xml report and print.                                  */
/* -------------------------------------------------------------------- */
    if( bAsXML )
    {
        CPLXMLNode *psRoot;
        char *pszFormattedXML;


        psRoot = CPLParseXMLString( osXML );
        pszFormattedXML = CPLSerializeXMLTree( psRoot );
        CPLDestroyXMLNode( psRoot );

        printf( "%s", pszFormattedXML );
        CPLFree( pszFormattedXML );
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    if (hCT) {
        OSRDestroySpatialReference( hSrcSRS );
        OSRDestroySpatialReference( hTrgSRS );
        OCTDestroyCoordinateTransformation( hCT );
    }

    if (hSrcDS)
        GDALClose(hSrcDS);

    GDALDumpOpenDatasets( stderr );
    GDALDestroyDriverManager();

    CSLDestroy( argv );

    return 0;
}
int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )

{
    GDALJP2Box oBox( fpVSIL );
    int iBox = 0;

    oBox.ReadFirst(); 

    while( strlen(oBox.GetType()) > 0 )
    {
/* -------------------------------------------------------------------- */
/*      Collect geotiff box.                                            */
/* -------------------------------------------------------------------- */
        if( EQUAL(oBox.GetType(),"uuid") 
            && memcmp( oBox.GetUUID(), msi_uuid2, 16 ) == 0 )
        {
	    nGeoTIFFSize = (int) oBox.GetDataLength();
            pabyGeoTIFFData = oBox.ReadBoxData();
        }

/* -------------------------------------------------------------------- */
/*      Collect MSIG box.                                               */
/* -------------------------------------------------------------------- */
        if( EQUAL(oBox.GetType(),"uuid") 
            && memcmp( oBox.GetUUID(), msig_uuid, 16 ) == 0 )
        {
	    nMSIGSize = (int) oBox.GetDataLength();
            pabyMSIGData = oBox.ReadBoxData();

            if( nMSIGSize < 70 
                || memcmp( pabyMSIGData, "MSIG/", 5 ) != 0 )
            {
                CPLFree( pabyMSIGData );
                pabyMSIGData = NULL;
                nMSIGSize = 0;
            }
        }

/* -------------------------------------------------------------------- */
/*      Process asoc box looking for Labelled GML data.                 */
/* -------------------------------------------------------------------- */
        if( EQUAL(oBox.GetType(),"asoc") )
        {
            GDALJP2Box oSubBox( fpVSIL );

            oSubBox.ReadFirstChild( &oBox );
            if( EQUAL(oSubBox.GetType(),"lbl ") )
            {
                char *pszLabel = (char *) oSubBox.ReadBoxData();
                if( EQUAL(pszLabel,"gml.data") )
                {
                    CollectGMLData( &oBox );
                }
                CPLFree( pszLabel );
            }
        }

/* -------------------------------------------------------------------- */
/*      Process simple xml boxes.                                       */
/* -------------------------------------------------------------------- */
        if( EQUAL(oBox.GetType(),"xml ") )
        {
            CPLString osBoxName;
            char *pszXML = (char *) oBox.ReadBoxData();

            osBoxName.Printf( "BOX_%d", iBox++ );
            
            papszGMLMetadata = CSLSetNameValue( papszGMLMetadata, 
                                                osBoxName, pszXML );
            CPLFree( pszXML );
        }

/* -------------------------------------------------------------------- */
/*      Check for a resd box in jp2h.                                   */
/* -------------------------------------------------------------------- */
        if( EQUAL(oBox.GetType(),"jp2h") )
        {
            GDALJP2Box oSubBox( fpVSIL );

            for( oSubBox.ReadFirstChild( &oBox );
                 strlen(oSubBox.GetType()) > 0;
                 oSubBox.ReadNextChild( &oBox ) )
            {
                if( EQUAL(oSubBox.GetType(),"res ") )
                {
                    GDALJP2Box oResBox( fpVSIL );

                    oResBox.ReadFirstChild( &oSubBox );
                    
                    // we will use either the resd or resc box, which ever
                    // happens to be first.  Should we prefer resd?
                    if( oResBox.GetDataLength() == 10 )
                    {
                        unsigned char *pabyResData = oResBox.ReadBoxData();
                        int nVertNum, nVertDen, nVertExp;
                        int nHorzNum, nHorzDen, nHorzExp;
                        
                        nVertNum = pabyResData[0] * 256 + pabyResData[1];
                        nVertDen = pabyResData[2] * 256 + pabyResData[3];
                        nHorzNum = pabyResData[4] * 256 + pabyResData[5];
                        nHorzDen = pabyResData[6] * 256 + pabyResData[7];
                        nVertExp = pabyResData[8];
                        nHorzExp = pabyResData[9];
                        
                        // compute in pixels/cm 
                        double dfVertRes = 
                            (nVertNum/(double)nVertDen) * pow(10.0,nVertExp)/100;
                        double dfHorzRes = 
                            (nHorzNum/(double)nHorzDen) * pow(10.0,nHorzExp)/100;
                        CPLString osFormatter;

                        papszGMLMetadata = CSLSetNameValue( 
                            papszGMLMetadata, 
                            "TIFFTAG_XRESOLUTION",
                            osFormatter.Printf("%g",dfHorzRes) );
                        
                        papszGMLMetadata = CSLSetNameValue( 
                            papszGMLMetadata, 
                            "TIFFTAG_YRESOLUTION",
                            osFormatter.Printf("%g",dfVertRes) );
                        papszGMLMetadata = CSLSetNameValue( 
                            papszGMLMetadata, 
                            "TIFFTAG_RESOLUTIONUNIT", 
                            "3 (pixels/cm)" );
                        
                        CPLFree( pabyResData );
                    }
                }
            }
        }

        oBox.ReadNext();
    }
    
    return TRUE;
}
GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )

{
/* -------------------------------------------------------------------- */
/*      This is a backdoor to let us embed a literal gmljp2 chunk       */
/*      supplied by the user as an external file.  This is mostly       */
/*      for preparing test files with exotic contents.                  */
/* -------------------------------------------------------------------- */
    if( CPLGetConfigOption( "GMLJP2OVERRIDE", NULL ) != NULL )
    {
        VSILFILE *fp = VSIFOpenL( CPLGetConfigOption( "GMLJP2OVERRIDE",""), "r" );
        char *pszGML = NULL;

        if( fp == NULL )
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "Unable to open GMLJP2OVERRIDE file." );
            return NULL;
        }
        
        VSIFSeekL( fp, 0, SEEK_END );
        int nLength = (int) VSIFTellL( fp );
        pszGML = (char *) CPLCalloc(1,nLength+1);
        VSIFSeekL( fp, 0, SEEK_SET );
        VSIFReadL( pszGML, 1, nLength, fp );
        VSIFCloseL( fp );

        GDALJP2Box *apoGMLBoxes[2];

        apoGMLBoxes[0] = GDALJP2Box::CreateLblBox( "gml.data" );
        apoGMLBoxes[1] = 
            GDALJP2Box::CreateLabelledXMLAssoc( "gml.root-instance", 
                                                pszGML );

        GDALJP2Box *poGMLData = GDALJP2Box::CreateAsocBox( 2, apoGMLBoxes);
        
        delete apoGMLBoxes[0];
        delete apoGMLBoxes[1];

        CPLFree( pszGML );
        
        return poGMLData;
    }

/* -------------------------------------------------------------------- */
/*      Try do determine a PCS or GCS code we can use.                  */
/* -------------------------------------------------------------------- */
    OGRSpatialReference oSRS;
    char *pszWKTCopy = (char *) pszProjection;
    int nEPSGCode = 0;
    char szSRSName[100];
    int  bNeedAxisFlip = FALSE;

    if( oSRS.importFromWkt( &pszWKTCopy ) != OGRERR_NONE )
        return NULL;

    if( oSRS.IsProjected() )
    {
        const char *pszAuthName = oSRS.GetAuthorityName( "PROJCS" );

        if( pszAuthName != NULL && EQUAL(pszAuthName,"epsg") )
        {
            nEPSGCode = atoi(oSRS.GetAuthorityCode( "PROJCS" ));
        }
    }
    else if( oSRS.IsGeographic() )
    {
        const char *pszAuthName = oSRS.GetAuthorityName( "GEOGCS" );

        if( pszAuthName != NULL && EQUAL(pszAuthName,"epsg") )
        {
            nEPSGCode = atoi(oSRS.GetAuthorityCode( "GEOGCS" ));
            bNeedAxisFlip = TRUE;
        }
    }

    if( nEPSGCode != 0 )
        sprintf( szSRSName, "urn:ogc:def:crs:EPSG::%d", nEPSGCode );
    else
        strcpy( szSRSName, 
                "gmljp2://xml/CRSDictionary.gml#ogrcrs1" );

/* -------------------------------------------------------------------- */
/*      Prepare coverage origin and offset vectors.  Take axis          */
/*      order into account if needed.                                   */
/* -------------------------------------------------------------------- */
    double adfOrigin[2];
    double adfXVector[2];
    double adfYVector[2];
    
    adfOrigin[0] = adfGeoTransform[0] + adfGeoTransform[1] * 0.5
        + adfGeoTransform[4] * 0.5;
    adfOrigin[1] = adfGeoTransform[3] + adfGeoTransform[2] * 0.5
        + adfGeoTransform[5] * 0.5;
    adfXVector[0] = adfGeoTransform[1];
    adfXVector[1] = adfGeoTransform[2];
        
    adfYVector[0] = adfGeoTransform[4];
    adfYVector[1] = adfGeoTransform[5];
    
    if( bNeedAxisFlip
        && CSLTestBoolean( CPLGetConfigOption( "GDAL_IGNORE_AXIS_ORIENTATION",
                                               "FALSE" ) ) )
    {
        bNeedAxisFlip = FALSE;
        CPLDebug( "GMLJP2", "Supressed axis flipping on write based on GDAL_IGNORE_AXIS_ORIENTATION." );
    }

    if( bNeedAxisFlip )
    {
        double dfTemp;
        
        CPLDebug( "GMLJP2", "Flipping GML coverage axis order." );
        
        dfTemp = adfOrigin[0];
        adfOrigin[0] = adfOrigin[1];
        adfOrigin[1] = dfTemp;

        dfTemp = adfXVector[0];
        adfXVector[0] = adfXVector[1];
        adfXVector[1] = dfTemp;

        dfTemp = adfYVector[0];
        adfYVector[0] = adfYVector[1];
        adfYVector[1] = dfTemp;
    }

/* -------------------------------------------------------------------- */
/*      For now we hardcode for a minimal instance format.              */
/* -------------------------------------------------------------------- */
    CPLString osDoc;

    osDoc.Printf( 
"<gml:FeatureCollection\n"
"   xmlns:gml=\"http://www.opengis.net/gml\"\n"
"   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
"   xsi:schemaLocation=\"http://www.opengeospatial.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlJP2Profile/1.0.0/gmlJP2Profile.xsd\">\n"
"  <gml:boundedBy>\n"
"    <gml:Null>withheld</gml:Null>\n"
"  </gml:boundedBy>\n"
"  <gml:featureMember>\n"
"    <gml:FeatureCollection>\n"
"      <gml:featureMember>\n"
"        <gml:RectifiedGridCoverage dimension=\"2\" gml:id=\"RGC0001\">\n"
"          <gml:rectifiedGridDomain>\n"
"            <gml:RectifiedGrid dimension=\"2\">\n"
"              <gml:limits>\n"
"                <gml:GridEnvelope>\n"
"                  <gml:low>0 0</gml:low>\n"
"                  <gml:high>%d %d</gml:high>\n"
"                </gml:GridEnvelope>\n"
"              </gml:limits>\n"
"              <gml:axisName>x</gml:axisName>\n"
"              <gml:axisName>y</gml:axisName>\n"
"              <gml:origin>\n"
"                <gml:Point gml:id=\"P0001\" srsName=\"%s\">\n"
"                  <gml:pos>%.15g %.15g</gml:pos>\n"
"                </gml:Point>\n"
"              </gml:origin>\n"
"              <gml:offsetVector srsName=\"%s\">%.15g %.15g</gml:offsetVector>\n"
"              <gml:offsetVector srsName=\"%s\">%.15g %.15g</gml:offsetVector>\n"
"            </gml:RectifiedGrid>\n"
"          </gml:rectifiedGridDomain>\n"
"          <gml:rangeSet>\n"
"            <gml:File>\n"
"              <gml:fileName>gmljp2://codestream/0</gml:fileName>\n"
"              <gml:fileStructure>Record Interleaved</gml:fileStructure>\n"
"            </gml:File>\n"
"          </gml:rangeSet>\n"
"        </gml:RectifiedGridCoverage>\n"
"      </gml:featureMember>\n"
"    </gml:FeatureCollection>\n"
"  </gml:featureMember>\n"
"</gml:FeatureCollection>\n",
             nXSize-1, nYSize-1, szSRSName, adfOrigin[0], adfOrigin[1],
             szSRSName, adfXVector[0], adfXVector[1], 
             szSRSName, adfYVector[0], adfYVector[1] );

/* -------------------------------------------------------------------- */
/*      If we need a user defined CRSDictionary entry, prepare it       */
/*      here.                                                           */
/* -------------------------------------------------------------------- */
    CPLString osDictBox;

    if( nEPSGCode == 0 )
    {
        char *pszGMLDef = NULL;

        if( oSRS.exportToXML( &pszGMLDef, NULL ) == OGRERR_NONE )
        {
            osDictBox.Printf(  
"<gml:Dictionary gml:id=\"CRSU1\" \n"
"        xmlns:gml=\"http://www.opengis.net/gml\"\n"
"        xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
"        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
"  <gml:dictionaryEntry>\n"
"%s\n"
"  </gml:dictionaryEntry>\n"
"</gml:Dictionary>\n",
                     pszGMLDef );
        }
        CPLFree( pszGMLDef );
    }

/* -------------------------------------------------------------------- */
/*      Setup the gml.data label.                                       */
/* -------------------------------------------------------------------- */
    GDALJP2Box *apoGMLBoxes[5];
    int nGMLBoxes = 0;

    apoGMLBoxes[nGMLBoxes++] = GDALJP2Box::CreateLblBox( "gml.data" );

/* -------------------------------------------------------------------- */
/*      Setup gml.root-instance.                                        */
/* -------------------------------------------------------------------- */
    apoGMLBoxes[nGMLBoxes++] = 
        GDALJP2Box::CreateLabelledXMLAssoc( "gml.root-instance", osDoc );

/* -------------------------------------------------------------------- */
/*      Add optional dictionary.                                        */
/* -------------------------------------------------------------------- */
    if( strlen(osDictBox) > 0 )
        apoGMLBoxes[nGMLBoxes++] = 
            GDALJP2Box::CreateLabelledXMLAssoc( "CRSDictionary.gml",
                                                osDictBox );
        
/* -------------------------------------------------------------------- */
/*      Bundle gml.data boxes into an association.                      */
/* -------------------------------------------------------------------- */
    GDALJP2Box *poGMLData = GDALJP2Box::CreateAsocBox( nGMLBoxes, apoGMLBoxes);

/* -------------------------------------------------------------------- */
/*      Cleanup working boxes.                                          */
/* -------------------------------------------------------------------- */
    while( nGMLBoxes > 0 )
        delete apoGMLBoxes[--nGMLBoxes];

    return poGMLData;
}
int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
    papoBuiltGeometries = NULL;
    poFileadm = NULL;
    poBaseadm = NULL;
    char *pszPos;

    if ( bUpdate ) {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Update access not supported by the SOSI driver." );
        return FALSE;
    }

    /* Check that the file exists otherwise HO_TestSOSI() emits an error */
    VSIStatBuf sStat;
    if( VSIStat(pszFilename, &sStat) != 0 )
        return FALSE;

    pszName = CPLStrdup( pszFilename );
    /* We ignore any layer parameters for now. */
    pszPos = strchr(pszName, ',');
    if (pszPos != NULL) {
        pszPos[0] = '\0';
    }

    /* Confirm that we are dealing with a SOSI file. Used also by data
     * format auto-detection in some ogr utilities. */
    UT_INT64 nEnd = 0;
    int bIsSosi = HO_TestSOSI ( pszName, &nEnd );
    if ( bIsSosi == UT_FALSE ) {
        return FALSE; /* No error message: This is used by file format auto-detection */
    }

    short nStatus = 0, nDetStatus = 0; /* immediate status, detailed status */

    /* open index base and sosi file */
    poBaseadm = LC_OpenBase(LC_BASE);
    nStatus   = LC_OpenSos(pszName, LC_BASE_FRAMGR, LC_GML_IDX, LC_INGEN_STATUS,
                           &poFileadm, &nDetStatus);
    if ( nStatus == UT_FALSE ) {
        char *pszErrorMessage;
        LC_StrError(nDetStatus, &pszErrorMessage);
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "File %s could not be opened by SOSI Driver: %s", pszName, pszErrorMessage );
        return FALSE;
    }

    /* --------------------------------------------------------------------*
     *      Prefetch all the information needed to determine layers        *
     * 	    and prebuild LineString features for later assembly.           *
     * --------------------------------------------------------------------*/

    /* allocate room for one pointer per feature */
    nNumFeatures = poFileadm->lAntGr;
    void* mem = VSIMalloc2(nNumFeatures, sizeof(void*));
    if (mem == NULL) {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Memory allocation for SOSI features failed." );
        return FALSE;
    } else {
        papoBuiltGeometries = (OGRGeometry**)mem;
    }
    for (unsigned int i=0; i<nNumFeatures; i++) papoBuiltGeometries[i] = NULL;

    /* Various iterators and return values used to iterate through SOSI features */
    short          nName, nNumLines;
    long           nNumCoo;
    unsigned short nInfo;
    LC_SNR_ADM	   oSnradm;
    LC_BGR		   oNextSerial;
    LC_BGR		  *poNextSerial;
    poNextSerial =&oNextSerial;

    bool bPointLayer = FALSE; /* Initialize four layers for the different geometry types */
    bool bCurveLayer = FALSE;
    bool bPolyLayer  = FALSE;
    bool bTextLayer  = FALSE;
    poPolyHeaders  = new S2I();
    poPointHeaders = new S2I();
    poCurveHeaders = new S2I();
    poTextHeaders  = new S2I();

    LC_SBSn(&oSnradm, poFileadm, 0, nNumFeatures); /* Set FYBA search limits  */
    LC_InitNextBgr(poNextSerial);

    /* Prebuilding simple features and extracting layer information. */
    while (LC_NextBgr(poNextSerial,LC_FRAMGR)) {
        /* Fetch next group information */
        nName = LC_RxGr(poNextSerial, LES_OPTIMALT, &nNumLines, &nNumCoo, &nInfo);

        S2S oHeaders;
        S2S::iterator iHeaders;
        int iH;
        /* Extract all strings from group header. */
        for (short i=1; i<=nNumLines; i++) {
            char *pszLine = LC_GetGi(i);      /* Get one header line */
            if ((pszLine[0] == ':')||(pszLine[0] == '(')) continue;  /* If we have a continued REF line, skip it. */
            if (pszLine[0] == '!') continue;  /* If we have a comment line, skip it. */
            
            char *pszUTFLine = CPLRecode(pszLine, pszEncoding, CPL_ENC_UTF8); /* switch to UTF encoding here, if it is known. */
            char *pszUTFLineIter = pszUTFLine;
			
            while (pszUTFLineIter[0] == '.') pszUTFLineIter++; /* Skipping the dots at the beginning of a SOSI line */
            char *pszPos = strstr(pszUTFLineIter, " "); /* Split header and value */
            if (pszPos != NULL) {
                CPLString osKey = CPLString(std::string(pszUTFLineIter,pszPos)); /* FIXME: clean instantiation of CPLString? */
                CPLString osValue = CPLString(pszPos+1);
                
                oHeaders[osKey]=osValue;          /* Add to header map */
                switch (nName) {             /* Add to header list for the corresponding layer, if it is not */
                case L_FLATE: {            /* in there already */
                    if (poPolyHeaders->find(osKey) == poPolyHeaders->end()) {
                        iH = poPolyHeaders->size();
                        (*poPolyHeaders)[osKey] = iH;
                    }
                    break;
                }
                case L_KURVE: {
                    if (poCurveHeaders->find(osKey) == poCurveHeaders->end()) {
                        iH = poCurveHeaders->size();
                        (*poCurveHeaders)[osKey] = iH;
                    }
                    break;
                }
                case L_PUNKT: {
                    if (poPointHeaders->find(osKey) == poPointHeaders->end()) {
                        iH = poPointHeaders->size();
                        (*poPointHeaders)[osKey] = iH;
                    }
                    break;
                }
                case L_TEKST: {
                    if (poTextHeaders->find(osKey) == poTextHeaders->end()) {
                        iH = poTextHeaders->size();
                        (*poTextHeaders)[osKey] = iH;
                    }
                    break;
                }
                }
            }
            CPLFree(pszUTFLine);
        }

        /* Feature-specific tasks */
        switch (nName) {
        case L_PUNKT: {
            /* Pre-build a point feature. Activate point layer. */
            bPointLayer = TRUE;
            buildOGRPoint(oNextSerial.lNr);
            break;
        }
        case L_FLATE: {
            /* Activate polygon layer. */
            bPolyLayer = TRUE;
            /* cannot build geometries that reference others yet */
            break;
        }
        case L_KURVE: {
            /* Pre-build a line feature. Activate line/curve layer. */
            bCurveLayer = TRUE;
            buildOGRLineString(nNumCoo, oNextSerial.lNr);
            break;
        }
        case L_TEKST: {
            /* Pre-build a text line contour feature. Activate text layer. */
            /* Todo: observe only points 2ff if more than one point is given for follow mode */
            bTextLayer = TRUE;
            buildOGRMultiPoint(nNumCoo, oNextSerial.lNr);
            break;
        }
        case L_HODE: {
            /* Get SRS from SOSI header. */
            unsigned short nMask = LC_TR_ALLT;
            LC_TRANSPAR oTrans;
            if (LC_GetTransEx(&nMask,&oTrans) == UT_FALSE) {
                CPLError( CE_Failure, CPLE_OpenFailed, 
                          "TRANSPAR section not found - No reference system information available.");
                return NULL;
            }
            poSRS = new OGRSpatialReference();

            /* Get coordinate system from SOSI header. */
            int nEPSG = sosi2epsg(oTrans.sKoordsys);
            if (poSRS->importFromEPSG(nEPSG) != OGRERR_NONE) {
				CPLError( CE_Failure, CPLE_OpenFailed, 
                          "OGR could not load coordinate system definition EPSG:%i.", nEPSG);
                return NULL;
            }

            /* Get character encoding from SOSI header. */
            iHeaders = oHeaders.find("TEGNSETT");
            if (iHeaders != oHeaders.end()) {
                CPLString osLine = iHeaders->second;
                if (osLine.compare("ISO8859-1")==0) {
                    pszEncoding = CPL_ENC_ISO8859_1;
                } else if (osLine.compare("ISO8859-10")==0) {
                    pszEncoding = CPL_ENC_ISO8859_10;
                } else if (osLine.compare("UTF-8")==0) {
                    pszEncoding = CPL_ENC_UTF8;
                }
            }

            break;
        }
        default: {
            break;
        }
        }
    }

    /* -------------------------------------------------------------------- *
     *      Create a corresponding layers. One per geometry type            *
     * -------------------------------------------------------------------- */
    int nLayers = 0;
    if (bPolyLayer)  nLayers++;
    if (bCurveLayer) nLayers++;
    if (bPointLayer) nLayers++;
    if (bTextLayer) nLayers++;
    this->nLayers = nLayers;
    /* allocate some memory for up to three layers */
    papoLayers = (OGRSOSILayer **) VSIMalloc2(sizeof(void*), nLayers);

    /* Define each layer, using a proper feature definition, geometry type,
     * and adding every SOSI header encountered in the file as field. */
    S2I::iterator i;
    if (bPolyLayer) {
		OGRFeatureDefn *poFeatureDefn = defineLayer("polygons", wkbPolygon, poPolyHeaders);
        poFeatureDefn->Reference();
        papoLayers[--nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poPolyHeaders );
    } else {
        delete poPolyHeaders;
        poPolyHeaders = NULL;
    }
    if (bCurveLayer) {
        OGRFeatureDefn *poFeatureDefn = defineLayer("lines", wkbLineString, poCurveHeaders);
        poFeatureDefn->Reference();
        papoLayers[--nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poCurveHeaders );
    } else {
        delete poCurveHeaders;
        poCurveHeaders = NULL;
    }
    if (bPointLayer) {
        OGRFeatureDefn *poFeatureDefn = defineLayer("points", wkbPoint, poPointHeaders);
        poFeatureDefn->Reference();
        papoLayers[--nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poPointHeaders );
    } else {
        delete poPointHeaders;
        poPointHeaders = NULL;
    }
    if (bTextLayer) {
        OGRFeatureDefn *poFeatureDefn = defineLayer("text", wkbMultiPoint, poTextHeaders);
        poFeatureDefn->Reference();
        papoLayers[--nLayers] = new OGRSOSILayer( this, poFeatureDefn, poFileadm, poTextHeaders );
    } else {
        delete poTextHeaders;
        poTextHeaders = NULL;
    }
    return TRUE;
}
static CPLErr
BlendMaskGenerator( int nXOff, int nYOff, int nXSize, int nYSize, 
                    GByte *pabyPolyMask, float *pafValidityMask,
                    OGRGeometryH hPolygon, double dfBlendDist )

{
#ifndef HAVE_GEOS 
    CPLError( CE_Failure, CPLE_AppDefined, 
              "Blend distance support not available without the GEOS library.");
    return CE_Failure;

#else /* HAVE_GEOS */

/* -------------------------------------------------------------------- */
/*      Convert the polygon into a collection of lines so that we       */
/*      measure distance from the edge even on the inside.              */
/* -------------------------------------------------------------------- */
    OGRGeometry *poLines
        = OGRGeometryFactory::forceToMultiLineString( 
            ((OGRGeometry *) hPolygon)->clone() );

/* -------------------------------------------------------------------- */
/*      Prepare a clipping polygon a bit bigger than the area of        */
/*      interest in the hopes of simplifying the cutline down to        */
/*      stuff that will be relavent for this area of interest.          */
/* -------------------------------------------------------------------- */
    CPLString osClipRectWKT;

    osClipRectWKT.Printf( "POLYGON((%g %g,%g %g,%g %g,%g %g,%g %g))", 
                          nXOff - (dfBlendDist+1), 
                          nYOff - (dfBlendDist+1), 
                          nXOff + nXSize + (dfBlendDist+1), 
                          nYOff - (dfBlendDist+1), 
                          nXOff + nXSize + (dfBlendDist+1), 
                          nYOff + nYSize + (dfBlendDist+1), 
                          nXOff - (dfBlendDist+1), 
                          nYOff + nYSize + (dfBlendDist+1), 
                          nXOff - (dfBlendDist+1), 
                          nYOff - (dfBlendDist+1) );
    
    OGRPolygon *poClipRect = NULL;
    char *pszWKT = (char *) osClipRectWKT.c_str();
    
    OGRGeometryFactory::createFromWkt( &pszWKT, NULL, 
                                       (OGRGeometry**) (&poClipRect) );

    if( poClipRect )
    {
        OGRGeometry *poClippedLines = 
            poLines->Intersection( poClipRect );
        delete poLines;
        poLines = poClippedLines;
        delete poClipRect;
    }

/* -------------------------------------------------------------------- */
/*      Convert our polygon into GEOS format, and compute an            */
/*      envelope to accelerate later distance operations.               */
/* -------------------------------------------------------------------- */
    OGREnvelope sEnvelope;
    int iXMin, iYMin, iXMax, iYMax;
    GEOSGeom poGEOSPoly;

    poGEOSPoly = poLines->exportToGEOS();
    OGR_G_GetEnvelope( hPolygon, &sEnvelope );

    delete poLines;

    if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize 
        || sEnvelope.MaxY + dfBlendDist < nYOff 
        || sEnvelope.MinX - dfBlendDist > nXOff+nXSize
        || sEnvelope.MaxX + dfBlendDist < nXOff )
        return CE_None;
    
    iXMin = MAX(0,(int) floor(sEnvelope.MinX - dfBlendDist - nXOff));
    iXMax = MIN(nXSize, (int) ceil(sEnvelope.MaxX + dfBlendDist - nXOff));
    iYMin = MAX(0,(int) floor(sEnvelope.MinY - dfBlendDist - nYOff));
    iYMax = MIN(nYSize, (int) ceil(sEnvelope.MaxY + dfBlendDist - nYOff));

/* -------------------------------------------------------------------- */
/*      Loop over potential area within blend line distance,            */
/*      processing each pixel.                                          */
/* -------------------------------------------------------------------- */
    int iY, iX;
    double dfLastDist;
    
    for( iY = 0; iY < nYSize; iY++ )
    {
        dfLastDist = 0.0;

        for( iX = 0; iX < nXSize; iX++ )
        {
            if( iX < iXMin || iX >= iXMax
                || iY < iYMin || iY > iYMax
                || dfLastDist > dfBlendDist + 1.5 )
            {
                if( pabyPolyMask[iX + iY * nXSize] == 0 )
                    pafValidityMask[iX + iY * nXSize] = 0.0;

                dfLastDist -= 1.0;
                continue;
            }
            
            double dfDist, dfRatio;
            CPLString osPointWKT;
            GEOSGeom poGEOSPoint;

            osPointWKT.Printf( "POINT(%d.5 %d.5)", iX + nXOff, iY + nYOff );
            poGEOSPoint = GEOSGeomFromWKT( osPointWKT );

            GEOSDistance( poGEOSPoly, poGEOSPoint, &dfDist );
            GEOSGeom_destroy( poGEOSPoint );

            dfLastDist = dfDist;

            if( dfDist > dfBlendDist )
            {
                if( pabyPolyMask[iX + iY * nXSize] == 0 )
                    pafValidityMask[iX + iY * nXSize] = 0.0;

                continue;
            }

            if( pabyPolyMask[iX + iY * nXSize] == 0 )
            {
                /* outside */
                dfRatio = 0.5 - (dfDist / dfBlendDist) * 0.5;
            }
            else 
            {
                /* inside */
                dfRatio = 0.5 + (dfDist / dfBlendDist) * 0.5;
            }                

            pafValidityMask[iX + iY * nXSize] *= dfRatio;
        }
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    GEOSGeom_destroy( poGEOSPoly );

    return CE_None;

#endif /* HAVE_GEOS */
}
Exemple #12
0
void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid)
{
    int bRewriteGeogCitation = FALSE;
    char szName[256];
    CPLString osCitation;
    size_t n = 0;
    if( GTIFKeyGet( psGTIF, GeogCitationGeoKey, szName, 0, sizeof(szName) ) )
        n = strlen(szName);
    if (n == 0)
        return;

    if(!EQUALN(szName, "GCS Name = ", strlen("GCS Name = ")))
    {
        osCitation = "GCS Name = ";
        osCitation += szName;
    }
    else
    {
        osCitation = szName;
    }

    if(nDatum == KvUserDefined )
    {
        const char* datumName = poSRS->GetAttrValue( "DATUM" );
        if(datumName && strlen(datumName) > 0)
        {
            osCitation += "|Datum = ";
            osCitation += datumName;
            bRewriteGeogCitation = TRUE;
        }
    }
    if(nSpheroid == KvUserDefined )
    {
        const char* spheroidName = poSRS->GetAttrValue( "SPHEROID" );
        if(spheroidName && strlen(spheroidName) > 0)
        {
            osCitation += "|Ellipsoid = ";
            osCitation += spheroidName;
            bRewriteGeogCitation = TRUE;
        }
    }

    const char* primemName = poSRS->GetAttrValue( "PRIMEM" );
    if(primemName && strlen(primemName) > 0)
    {
        osCitation += "|Primem = ";
        osCitation += primemName;
        bRewriteGeogCitation = TRUE;

        double primemValue = poSRS->GetPrimeMeridian(NULL);
        if(angUnitName && !EQUAL(angUnitName, "Degree"))
        {
            double aUnit = poSRS->GetAngularUnits(NULL);
            primemValue *= aUnit;
        }
        GTIFKeySet( psGTIF, GeogPrimeMeridianLongGeoKey, TYPE_DOUBLE, 1, 
                    primemValue );
    } 
    if(angUnitName && strlen(angUnitName) > 0 && !EQUAL(angUnitName, "Degree"))
    {
        osCitation += "|AUnits = ";
        osCitation += angUnitName;
        bRewriteGeogCitation = TRUE;
    }

    if (osCitation[strlen(osCitation) - 1] != '|')
        osCitation += "|";

    if (bRewriteGeogCitation)
        GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );

    return;
}
Exemple #13
0
CPLErr SAGADataset::WriteHeader( CPLString osHDRFilename, GDALDataType eType,
                                 GInt16 nXSize, GInt16 nYSize,
                                 double dfMinX, double dfMinY,
                                 double dfCellsize, double dfNoData,
                                 double dfZFactor, bool bTopToBottom )

{
    FILE	*fp;

    fp = VSIFOpenL( osHDRFilename, "wt" );

    if( fp == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "Failed to write .sgrd file %s.", 
                  osHDRFilename.c_str() );
        return CE_Failure;
    }

    VSIFPrintfL( fp, "NAME\t= %s\n", CPLGetBasename( osHDRFilename ) );
    VSIFPrintfL( fp, "DESCRIPTION\t=\n" );
    VSIFPrintfL( fp, "UNIT\t=\n" );
    VSIFPrintfL( fp, "DATAFILE_OFFSET\t= 0\n" );
    
    if( eType == GDT_Int32 )
        VSIFPrintfL( fp, "DATAFORMAT\t= INTEGER\n" );
    else if( eType == GDT_UInt32 )
        VSIFPrintfL( fp, "DATAFORMAT\t= INTEGER_UNSIGNED\n" );
    else if( eType == GDT_Int16 )
        VSIFPrintfL( fp, "DATAFORMAT\t= SHORTINT\n" );
    else if( eType == GDT_UInt16 )
        VSIFPrintfL( fp, "DATAFORMAT\t= SHORTINT_UNSIGNED\n" );
    else if( eType == GDT_Byte )
        VSIFPrintfL( fp, "DATAFORMAT\t= BYTE_UNSIGNED\n" );
    else if( eType == GDT_Float32 )
        VSIFPrintfL( fp, "DATAFORMAT\t= FLOAT\n" );		
    else //if( eType == GDT_Float64 )
        VSIFPrintfL( fp, "DATAFORMAT\t= DOUBLE\n" );
#ifdef CPL_LSB
    VSIFPrintfL( fp, "BYTEORDER_BIG\t= FALSE\n" );
#else
    VSIFPrintfL( fp, "BYTEORDER_BIG\t= TRUE\n" );
#endif

    VSIFPrintfL( fp, "POSITION_XMIN\t= %.10f\n", dfMinX );
    VSIFPrintfL( fp, "POSITION_YMIN\t= %.10f\n", dfMinY );
    VSIFPrintfL( fp, "CELLCOUNT_X\t= %d\n", nXSize );
    VSIFPrintfL( fp, "CELLCOUNT_Y\t= %d\n", nYSize );
    VSIFPrintfL( fp, "CELLSIZE\t= %.10f\n", dfCellsize );
    VSIFPrintfL( fp, "Z_FACTOR\t= %f\n", dfZFactor );
    VSIFPrintfL( fp, "NODATA_VALUE\t= %f\n", dfNoData );
    if (bTopToBottom)
        VSIFPrintfL( fp, "TOPTOBOTTOM\t= TRUE\n" );
    else
        VSIFPrintfL( fp, "TOPTOBOTTOM\t= FALSE\n" );


    VSIFCloseL( fp );

    return CE_None;
}
int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
                                 CPL_UNUSED int bTestOpen )
{
    CPLAssert( nLayers == 0 );

/* -------------------------------------------------------------------- */
/*      If this is the name of an MDB file, then construct the          */
/*      appropriate connection string.  Otherwise clip of GEOMEDIA: to  */
/*      get the DSN.                                                    */
/*                                                                      */
/* -------------------------------------------------------------------- */
    char *pszDSN;
    if( EQUALN(pszNewName,"GEOMEDIA:",9) )
        pszDSN = CPLStrdup( pszNewName + 9 );
    else
    {
        const char *pszDSNStringTemplate = NULL;
        pszDSNStringTemplate = CPLGetConfigOption( "GEOMEDIA_DRIVER_TEMPLATE", "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s");
        if (!CheckDSNStringTemplate(pszDSNStringTemplate))
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Illegal value for GEOMEDIA_DRIVER_TEMPLATE option");
            return FALSE;
        }
        pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
        sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
    }

/* -------------------------------------------------------------------- */
/*      Initialize based on the DSN.                                    */
/* -------------------------------------------------------------------- */
    CPLDebug( "Geomedia", "EstablishSession(%s)", pszDSN );

    if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "Unable to initialize ODBC connection to DSN for %s,\n"
                  "%s", pszDSN, oSession.GetLastError() );
        CPLFree( pszDSN );
        return FALSE;
    }

    CPLFree( pszDSN );

    pszName = CPLStrdup( pszNewName );
    
    bDSUpdate = bUpdate;

/* -------------------------------------------------------------------- */
/*      Collect list of tables and their supporting info from           */
/*      GAliasTable.                                                    */
/* -------------------------------------------------------------------- */
    CPLString osGFeaturesTable = GetTableNameFromType("INGRFeatures");
    if (osGFeaturesTable.size() == 0)
        return FALSE;

    CPLString osGeometryProperties = GetTableNameFromType("INGRGeometryProperties");
    CPLString osGCoordSystemTable = GetTableNameFromType("GCoordSystemTable");

    std::vector<char **> apapszGeomColumns;
    {
        CPLODBCStatement oStmt( &oSession );
        oStmt.Appendf( "SELECT FeatureName, PrimaryGeometryFieldName FROM %s", osGFeaturesTable.c_str() );

        if( !oStmt.ExecuteSQL() )
        {
            CPLDebug( "GEOMEDIA",
                    "SELECT on %s fails, perhaps not a geomedia geodatabase?\n%s",
                    osGFeaturesTable.c_str(),
                    oSession.GetLastError() );
            return FALSE;
        }

        while( oStmt.Fetch() )
        {
            int i, iNew = apapszGeomColumns.size();
            char **papszRecord = NULL;
            for( i = 0; i < 2; i++ )
                papszRecord = CSLAddString( papszRecord,
                                            oStmt.GetColData(i) );
            apapszGeomColumns.resize(iNew+1);
            apapszGeomColumns[iNew] = papszRecord;
        }
    }

    std::vector<OGRSpatialReference*> apoSRS;
    if (osGeometryProperties.size() != 0 && osGCoordSystemTable.size() != 0)
    {
        std::vector<CPLString> aosGUID;
        {
            CPLODBCStatement oStmt( &oSession );
            oStmt.Appendf( "SELECT GCoordSystemGUID FROM %s", osGeometryProperties.c_str() );

            if( !oStmt.ExecuteSQL() )
            {
                CPLDebug( "GEOMEDIA",
                        "SELECT on %s fails, perhaps not a geomedia geodatabase?\n%s",
                        osGeometryProperties.c_str(),
                        oSession.GetLastError() );
                return FALSE;
            }

            while( oStmt.Fetch() )
            {
                aosGUID.push_back(oStmt.GetColData(0));
            }

            if (apapszGeomColumns.size() != aosGUID.size())
            {
                CPLDebug( "GEOMEDIA", "%s and %s don't have the same size",
                        osGFeaturesTable.c_str(), osGeometryProperties.c_str() );
                return FALSE;
            }
        }

        int i;
        for(i=0; i<(int)aosGUID.size();i++)
        {
            apoSRS.push_back(GetGeomediaSRS(osGCoordSystemTable, aosGUID[i]));
        }
    }

/* -------------------------------------------------------------------- */
/*      Create a layer for each spatial table.                          */
/* -------------------------------------------------------------------- */
    unsigned int iTable;

    papoLayers = (OGRGeomediaLayer **) CPLCalloc(apapszGeomColumns.size(),
                                             sizeof(void*));

    for( iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
    {
        char **papszRecord = apapszGeomColumns[iTable];
        OGRGeomediaTableLayer  *poLayer;

        poLayer = new OGRGeomediaTableLayer( this );

        if( poLayer->Initialize( papszRecord[0], papszRecord[1], (apoSRS.size()) ? apoSRS[iTable] : NULL )
            != CE_None )
        {
            delete poLayer;
        }
        else
        {
            papoLayers[nLayers++] = poLayer;
        }
        CSLDestroy(papszRecord);
    }

    return TRUE;
}
CPLString OGRSQLiteViewLayer::GetSpatialWhere(int iGeomCol,
                                              OGRGeometry* poFilterGeom)
{
    if (HasLayerDefnError() || poFeatureDefn == NULL ||
        iGeomCol < 0 || iGeomCol >= poFeatureDefn->GetGeomFieldCount())
        return "";

    if( poFilterGeom != NULL && bHasSpatialIndex )
    {
        OGREnvelope  sEnvelope;

        poFilterGeom->getEnvelope( &sEnvelope );

        /* We first check that the spatial index table exists */
        if (!bHasCheckedSpatialIndexTable)
        {
            bHasCheckedSpatialIndexTable = TRUE;
            char **papszResult;
            int nRowCount, nColCount;
            char *pszErrMsg = NULL;

            CPLString osSQL;
            osSQL.Printf("SELECT name FROM sqlite_master "
                        "WHERE name='idx_%s_%s'",
                        pszEscapedUnderlyingTableName,
                        OGRSQLiteEscape(osUnderlyingGeometryColumn).c_str());

            int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
                                        &papszResult, &nRowCount,
                                        &nColCount, &pszErrMsg );

            if( rc != SQLITE_OK )
            {
                CPLError( CE_Failure, CPLE_AppDefined, "Error: %s",
                        pszErrMsg );
                sqlite3_free( pszErrMsg );
                bHasSpatialIndex = FALSE;
            }
            else
            {
                if (nRowCount != 1)
                {
                    bHasSpatialIndex = FALSE;
                }

                sqlite3_free_table(papszResult);
            }
        }

        if (bHasSpatialIndex)
        {
            return FormatSpatialFilterFromRTree(poFilterGeom,
                CPLSPrintf("\"%s\"", OGRSQLiteEscapeName(pszFIDColumn).c_str()),
                pszEscapedUnderlyingTableName,
                OGRSQLiteEscape(osUnderlyingGeometryColumn).c_str());
        }
        else
        {
            CPLDebug("SQLITE", "Count not find idx_%s_%s layer. Disabling spatial index",
                     pszEscapedUnderlyingTableName, osUnderlyingGeometryColumn.c_str());
        }

    }

    if( poFilterGeom != NULL && poDS->IsSpatialiteLoaded() )
    {
        return FormatSpatialFilterFromMBR(poFilterGeom,
            OGRSQLiteEscapeName(poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef()).c_str());
    }

    return "";
}
Exemple #16
0
int ERSHdrNode::ParseChildren( VSILFILE * fp )

{
    while( true )
    {
/* -------------------------------------------------------------------- */
/*      Read the next line (or multi-line for bracketed value).         */
/* -------------------------------------------------------------------- */
        CPLString osLine;

        if( !ReadLine( fp, osLine ) )
            return FALSE;

/* -------------------------------------------------------------------- */
/*      Got a Name=Value.                                               */
/* -------------------------------------------------------------------- */
        size_t iOff;

        if( (iOff = osLine.find_first_of( '=' )) != std::string::npos )
        {
            CPLString osName = osLine.substr(0,iOff-1);
            osName.Trim();

            CPLString osValue = osLine.c_str() + iOff + 1;
            osValue.Trim();

            MakeSpace();
            papszItemName[nItemCount] = CPLStrdup(osName);
            papszItemValue[nItemCount] = CPLStrdup(osValue);
            papoItemChild[nItemCount] = NULL;

            nItemCount++;
        }

/* -------------------------------------------------------------------- */
/*      Got a Begin for an object.                                      */
/* -------------------------------------------------------------------- */
        else if( (iOff = osLine.ifind( " Begin" )) != std::string::npos )
        {
            CPLString osName = osLine.substr(0,iOff);
            osName.Trim();

            MakeSpace();
            papszItemName[nItemCount] = CPLStrdup(osName);
            papszItemValue[nItemCount] = NULL;
            papoItemChild[nItemCount] = new ERSHdrNode();

            nItemCount++;

            if( !papoItemChild[nItemCount-1]->ParseChildren( fp ) )
                return FALSE;
        }

/* -------------------------------------------------------------------- */
/*      Got an End for our object.  Well, at least we *assume* it       */
/*      must be for our object.                                         */
/* -------------------------------------------------------------------- */
        else if( osLine.ifind( " End" ) != std::string::npos )
        {
            return TRUE;
        }

/* -------------------------------------------------------------------- */
/*      Error?                                                          */
/* -------------------------------------------------------------------- */
        else if( osLine.Trim().length() > 0 )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Unexpected line parsing .ecw:\n%s",
                      osLine.c_str() );
            return FALSE;
        }
    }
}
int OGRGPSBabelDataSource::Open( const char * pszDatasourceName, int bUpdateIn)

{
    int bExplicitFeatures = FALSE;
    int bWaypoints = TRUE, bTracks = TRUE, bRoutes = TRUE;
    if (bUpdateIn)
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                    "OGR/GPSBabel driver does not support opening a file in update mode");
        return FALSE;
    }

    if (!EQUALN(pszDatasourceName, "GPSBABEL:", 9))
    {
        VSILFILE* fp = VSIFOpenL(pszDatasourceName, "rb");
        if (fp == NULL)
            return FALSE;

        char szHeader[1024 + 1];
        memset(szHeader, 0, 1024+1);
        VSIFReadL(szHeader, 1, 1024, fp);
        if (memcmp(szHeader, "MsRcd", 5) == 0)
            pszGPSBabelDriverName = CPLStrdup("mapsource");
        else if (memcmp(szHeader, "MsRcf", 5) == 0)
            pszGPSBabelDriverName = CPLStrdup("gdb");
        else if (strstr(szHeader, "<osm") != NULL)
            pszGPSBabelDriverName = CPLStrdup("osm");
        else if (strstr(szHeader, "$GPGSA") != NULL ||
                 strstr(szHeader, "$GPGGA") != NULL)
            pszGPSBabelDriverName = CPLStrdup("nmea");
        else if (EQUALN(szHeader, "OziExplorer",11))
            pszGPSBabelDriverName = CPLStrdup("ozi");
        else if (strstr(szHeader, "Grid") && strstr(szHeader, "Datum") && strstr(szHeader, "Header"))
            pszGPSBabelDriverName = CPLStrdup("garmin_txt");
        else if (szHeader[0] == 13 && szHeader[10] == 'M' && szHeader[11] == 'S' &&
                 (szHeader[12] >= '0' && szHeader[12] <= '9') &&
                 (szHeader[13] >= '0' && szHeader[13] <= '9') &&
                 szHeader[12] * 10 + szHeader[13] >= 30 &&
                 (szHeader[14] == 1 || szHeader[14] == 2) && szHeader[15] == 0 &&
                 szHeader[16] == 0 && szHeader[17] == 0)
            pszGPSBabelDriverName = CPLStrdup("mapsend");
        else if (strstr(szHeader, "$PMGNWPL") != NULL ||
                 strstr(szHeader, "$PMGNRTE") != NULL)
            pszGPSBabelDriverName = CPLStrdup("magellan");

        VSIFCloseL(fp);

        if (pszGPSBabelDriverName == NULL)
        {
            return FALSE;
        }

        pszFilename = CPLStrdup(pszDatasourceName);
    }

    pszName = CPLStrdup( pszDatasourceName );

    if (pszGPSBabelDriverName == NULL)
    {
        const char* pszSep = strchr(pszDatasourceName + 9, ':');
        if (pszSep == NULL)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                    "Wrong syntax. Expected GPSBabel:driver_name:file_name");
            return FALSE;
        }

        pszGPSBabelDriverName = CPLStrdup(pszDatasourceName + 9);
        *(strchr(pszGPSBabelDriverName, ':')) = '\0';

        /* A bit of validation to avoid command line injection */
        if (!IsValidDriverName(pszGPSBabelDriverName))
            return FALSE;

        /* Parse optionnal features= option */
        if (EQUALN(pszSep+1, "features=", 9))
        {
            const char* pszNextSep = strchr(pszSep+1, ':');
            if (pszNextSep == NULL)
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                        "Wrong syntax. Expected GPSBabel:driver_name[,options]*:[features=waypoints,tracks,routes:]file_name");
                return FALSE;
            }

            char* pszFeatures = CPLStrdup(pszSep+1+9);
            *strchr(pszFeatures, ':') = 0;
            char** papszTokens = CSLTokenizeString(pszFeatures);
            char** papszIter = papszTokens;
            int bErr = FALSE;
            bExplicitFeatures = TRUE;
            bWaypoints = bTracks = bRoutes = FALSE;
            while(papszIter && *papszIter)
            {
                if (EQUAL(*papszIter, "waypoints"))
                    bWaypoints = TRUE;
                else if (EQUAL(*papszIter, "tracks"))
                    bTracks = TRUE;
                else if (EQUAL(*papszIter, "routes"))
                    bRoutes = TRUE;
                else
                {
                    CPLError(CE_Failure, CPLE_AppDefined, "Wrong value for 'features' options");
                    bErr = TRUE;
                }
                papszIter ++;
            }
            CSLDestroy(papszTokens);
            CPLFree(pszFeatures);

            if (bErr)
                return FALSE;

            pszSep = pszNextSep;
        }

        pszFilename = CPLStrdup(pszSep+1);
    }

    const char* pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
    if (pszOptionUseTempFile && CSLTestBoolean(pszOptionUseTempFile))
        osTmpFileName = CPLGenerateTempFilename(NULL);
    else
        osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);

    int bRet = FALSE;
    if (IsSpecialFile(pszFilename))
    {
        /* Special file : don't try to open it */
        char** argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
                              bTracks, pszGPSBabelDriverName, pszFilename);
        VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");
        bRet = (CPLSpawn(argv, NULL, tmpfp, TRUE) == 0);
        VSIFCloseL(tmpfp);
        tmpfp = NULL;
        CSLDestroy(argv);
        argv = NULL;
    }
    else
    {
        VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
        if (fp == NULL)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                    "Cannot open file %s", pszFilename);
            return FALSE;
        }

        char** argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
                              bTracks, pszGPSBabelDriverName, "-");

        VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");

        CPLPushErrorHandler(CPLQuietErrorHandler);
        bRet = (CPLSpawn(argv, fp, tmpfp, TRUE) == 0);
        CPLPopErrorHandler();

        CSLDestroy(argv);
        argv = NULL;

        CPLErr nLastErrorType = CPLGetLastErrorType();
        int nLastErrorNo = CPLGetLastErrorNo();
        CPLString osLastErrorMsg = CPLGetLastErrorMsg();

        VSIFCloseL(tmpfp);
        tmpfp = NULL;

        VSIFCloseL(fp);
        fp = NULL;

        if (!bRet)
        {
            if (strstr(osLastErrorMsg.c_str(), "This format cannot be used in piped commands") == NULL)
            {
                CPLError(nLastErrorType, nLastErrorNo, "%s", osLastErrorMsg.c_str());
            }
            else
            {
                VSIStatBuf sStatBuf;
                if (VSIStat(pszFilename, &sStatBuf) != 0)
                {
                    CPLError(CE_Failure, CPLE_NotSupported,
                            "Driver %s only supports real (non virtual) files", pszGPSBabelDriverName);
                    return FALSE;
                }

                /* Try without piping in */
                argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
                              bTracks, pszGPSBabelDriverName, pszFilename);
                tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");
                bRet = (CPLSpawn(argv, NULL, tmpfp, TRUE) == 0);
                VSIFCloseL(tmpfp);
                tmpfp = NULL;

                CSLDestroy(argv);
                argv = NULL;
            }
        }
    }


    if (bRet)
    {
        poGPXDS = OGRSFDriverRegistrar::Open(osTmpFileName.c_str());
        if (poGPXDS)
        {
            OGRLayer* poLayer;

            if (bWaypoints)
            {
                poLayer = poGPXDS->GetLayerByName("waypoints");
                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
                    apoLayers[nLayers++] = poLayer;
            }

            if (bRoutes)
            {
                poLayer = poGPXDS->GetLayerByName("routes");
                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
                    apoLayers[nLayers++] = poLayer;
                poLayer = poGPXDS->GetLayerByName("route_points");
                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
                    apoLayers[nLayers++] = poLayer;
            }

            if (bTracks)
            {
                poLayer = poGPXDS->GetLayerByName("tracks");
                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
                    apoLayers[nLayers++] = poLayer;
                poLayer = poGPXDS->GetLayerByName("track_points");
                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
                    apoLayers[nLayers++] = poLayer;
            }
        }
    }

    return nLayers > 0;
}
OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
                                        char ** ppszDstText ) const

{
    char        **papszGeoms;
    int         iGeom, nCumulativeLength = 0;
    OGRErr      eErr;

    if( nCurveCount == 0 )
    {
        CPLString osEmpty;
        if( poGeom->getCoordinateDimension()  == 3 )
            osEmpty.Printf("%s Z EMPTY",poGeom->getGeometryName());
        else
            osEmpty.Printf("%s EMPTY",poGeom->getGeometryName());
        *ppszDstText = CPLStrdup(osEmpty);
        return OGRERR_NONE;
    }

/* -------------------------------------------------------------------- */
/*      Build a list of strings containing the stuff for each Geom.     */
/* -------------------------------------------------------------------- */
    papszGeoms = (char **) CPLCalloc(sizeof(char *),nCurveCount);

    for( iGeom = 0; iGeom < nCurveCount; iGeom++ )
    {
        eErr = papoCurves[iGeom]->exportToWkt( &(papszGeoms[iGeom]), wkbVariantIso );
        if( eErr != OGRERR_NONE )
            goto error;

        nCumulativeLength += strlen(papszGeoms[iGeom]);
    }
    
/* -------------------------------------------------------------------- */
/*      Allocate the right amount of space for the aggregated string    */
/* -------------------------------------------------------------------- */
    *ppszDstText = (char *) VSIMalloc(nCumulativeLength + nCurveCount +
                                    strlen(poGeom->getGeometryName()) + 10);

    if( *ppszDstText == NULL )
    {
        eErr = OGRERR_NOT_ENOUGH_MEMORY;
        goto error;
    }

/* -------------------------------------------------------------------- */
/*      Build up the string, freeing temporary strings as we go.        */
/* -------------------------------------------------------------------- */
    strcpy( *ppszDstText, poGeom->getGeometryName() );
    if( poGeom->getCoordinateDimension() == 3 )
        strcat( *ppszDstText, " Z" );
    strcat( *ppszDstText, " (" );
    nCumulativeLength = strlen(*ppszDstText);

    for( iGeom = 0; iGeom < nCurveCount; iGeom++ )
    {
        if( iGeom > 0 )
            (*ppszDstText)[nCumulativeLength++] = ',';

        /* We must strip the explicit "LINESTRING " prefix */
        int nSkip = 0;
        if( !papoCurves[iGeom]->IsEmpty() &&
            EQUALN(papszGeoms[iGeom], "LINESTRING ", strlen("LINESTRING ")) )
        {
            nSkip = strlen("LINESTRING ");
            if( EQUALN(papszGeoms[iGeom] + nSkip, "Z ", 2) )
                nSkip += 2;
        }

        int nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
        memcpy( *ppszDstText + nCumulativeLength, papszGeoms[iGeom] + nSkip, nGeomLength );
        nCumulativeLength += nGeomLength;
        VSIFree( papszGeoms[iGeom] );
    }

    (*ppszDstText)[nCumulativeLength++] = ')';
    (*ppszDstText)[nCumulativeLength] = '\0';

    CPLFree( papszGeoms );

    return OGRERR_NONE;

error:
    for( iGeom = 0; iGeom < nCurveCount; iGeom++ )
        CPLFree( papszGeoms[iGeom] );
    CPLFree( papszGeoms );
    return eErr;
}
Exemple #19
0
CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
{
    CPLString osExpr;

/* -------------------------------------------------------------------- */
/*      Put things together in a fashion depending on the operator.     */
/* -------------------------------------------------------------------- */
    const swq_operation *poOp =
        swq_op_registrar::GetOperator( static_cast<swq_op>(nOperation) );

    if( poOp == nullptr && nOperation != SWQ_CUSTOM_FUNC )
    {
        CPLAssert( false );
        return osExpr;
    }

    switch( nOperation )
    {
      // Binary infix operators.
      case SWQ_OR:
      case SWQ_AND:
      case SWQ_EQ:
      case SWQ_NE:
      case SWQ_GT:
      case SWQ_LT:
      case SWQ_GE:
      case SWQ_LE:
      case SWQ_LIKE:
      case SWQ_ADD:
      case SWQ_SUBTRACT:
      case SWQ_MULTIPLY:
      case SWQ_DIVIDE:
      case SWQ_MODULUS:
        CPLAssert( nSubExprCount >= 2 );
        if( papoSubExpr[0]->eNodeType == SNT_COLUMN ||
            papoSubExpr[0]->eNodeType == SNT_CONSTANT )
        {
            osExpr += apszSubExpr[0];
        }
        else
        {
            osExpr += "(";
            osExpr += apszSubExpr[0];
            osExpr += ")";
        }
        osExpr += " ";
        osExpr += poOp->pszName;
        osExpr += " ";
        if( papoSubExpr[1]->eNodeType == SNT_COLUMN ||
            papoSubExpr[1]->eNodeType == SNT_CONSTANT )
        {
            osExpr += apszSubExpr[1];
        }
        else
        {
            osExpr += "(";
            osExpr += apszSubExpr[1];
            osExpr += ")";
        }
        if( nOperation == SWQ_LIKE && nSubExprCount == 3 )
            osExpr += CPLSPrintf( " ESCAPE (%s)", apszSubExpr[2] );
        break;

      case SWQ_NOT:
        CPLAssert( nSubExprCount == 1 );
        osExpr.Printf( "NOT (%s)", apszSubExpr[0] );
        break;

      case SWQ_ISNULL:
        CPLAssert( nSubExprCount == 1 );
        osExpr.Printf( "%s IS NULL", apszSubExpr[0] );
        break;

      case SWQ_IN:
        osExpr.Printf( "%s IN (", apszSubExpr[0] );
        for( int i = 1; i < nSubExprCount; i++ )
        {
            if( i > 1 )
                osExpr += ",";
            osExpr += "(";
            osExpr += apszSubExpr[i];
            osExpr += ")";
        }
        osExpr += ")";
        break;

      case SWQ_BETWEEN:
        CPLAssert( nSubExprCount == 3 );
        osExpr.Printf( "%s %s (%s) AND (%s)",
                       apszSubExpr[0],
                       poOp->pszName,
                       apszSubExpr[1],
                       apszSubExpr[2] );
        break;

      case SWQ_CAST:
        osExpr = "CAST(";
        for( int i = 0; i < nSubExprCount; i++ )
        {
            if( i == 1 )
                osExpr += " AS ";
            else if( i > 2 )
                osExpr += ", ";

            const int nLen = static_cast<int>(strlen(apszSubExpr[i]));
            if( (i == 1 &&
                (apszSubExpr[i][0] == '\'' &&
                 nLen > 2 && apszSubExpr[i][nLen-1] == '\'')) ||
                (i == 2 && EQUAL(apszSubExpr[1], "'GEOMETRY")) )
            {
                apszSubExpr[i][nLen-1] = '\0';
                osExpr += apszSubExpr[i] + 1;
            }
            else
                osExpr += apszSubExpr[i];

            if( i == 1 && nSubExprCount > 2)
                osExpr += "(";
            else if( i > 1 && i == nSubExprCount - 1 )
                osExpr += ")";
        }
        osExpr += ")";
        break;

      default: // function style.
        if( nOperation != SWQ_CUSTOM_FUNC )
            osExpr.Printf( "%s(", poOp->pszName );
        else
            osExpr.Printf( "%s(", string_value );
        for( int i = 0; i < nSubExprCount; i++ )
        {
            if( i > 0 )
                osExpr += ",";
            osExpr += "(";
            osExpr += apszSubExpr[i];
            osExpr += ")";
        }
        osExpr += ")";
        break;
    }

    return osExpr;
}
CPLErr GeoRasterRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
{
    GeoRasterDataset* poGDS = (GeoRasterDataset*) poDS;

    if( ! poRAT )
    {
        return CE_Failure;
    }

    if( poDefaultRAT )
    {
        delete poDefaultRAT;
    }

    poDefaultRAT = poRAT->Clone();

    // ----------------------------------------------------------
    // Format Table description
    // ----------------------------------------------------------

    char szName[OWTEXT];
    char szDescription[OWTEXT];
    int  iCol = 0;

    strcpy( szDescription, "( ID NUMBER" );

    for( iCol = 0; iCol < poRAT->GetColumnCount(); iCol++ )
    {
        strcpy( szName, poRAT->GetNameOfCol( iCol ) );

    if( EQUAL( szName, "histogram" ) )
    {
        return CE_None;
    }

        strcpy( szDescription, CPLSPrintf( "%s, %s",
            szDescription, szName ) );

        if( poRAT->GetTypeOfCol( iCol ) == GFT_Integer )
        {
            strcpy( szDescription, CPLSPrintf( "%s NUMBER",
                szDescription ) );
        }
        if( poRAT->GetTypeOfCol( iCol ) == GFT_Real )
        {
            strcpy( szDescription, CPLSPrintf( "%s FLOAT",
                szDescription ) );
        }
        if( poRAT->GetTypeOfCol( iCol ) == GFT_String )
        {
            strcpy( szDescription, CPLSPrintf( "%s VARCHAR2(128)",
                szDescription ) );
        }
    }
    strcpy( szDescription, CPLSPrintf( "%s )", szDescription ) );

    // ----------------------------------------------------------
    // Create VAT named based on RDT and RID and Layer (nBand)
    // ----------------------------------------------------------

    if( ! pszVATName )
    {
        pszVATName = CPLStrdup( CPLSPrintf(
            "RAT_%s_%d_%d", 
            poGeoRaster->pszDataTable, 
            poGeoRaster->nRasterId,
            nBand ) );
    }

    // ----------------------------------------------------------
    // Create VAT table
    // ----------------------------------------------------------

    OWStatement* poStmt = poGeoRaster->poConnection->CreateStatement( CPLSPrintf(
        "DECLARE\n"
        "  TAB VARCHAR2(68)  := UPPER(:1);\n"
        "  CNT NUMBER        := 0;\n"
        "BEGIN\n"
        "  EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM USER_TABLES\n"
        "    WHERE TABLE_NAME = :1' INTO CNT USING TAB;\n"
        "\n"
        "  IF NOT CNT = 0 THEN\n"
        "    EXECUTE IMMEDIATE 'DROP TABLE '||TAB||' PURGE';\n"
        "  END IF;\n"
        "\n"
        "  EXECUTE IMMEDIATE 'CREATE TABLE '||TAB||' %s';\n"
        "END;", szDescription ) );

    poStmt->Bind( pszVATName );

    if( ! poStmt->Execute() )
    {
        delete poStmt;
        CPLError( CE_Failure, CPLE_AppDefined, "Create VAT Table Error!" );
        return CE_Failure;
    }

    delete poStmt;

    // ----------------------------------------------------------
    // Insert Data to VAT
    // ----------------------------------------------------------

    int iEntry       = 0;
    int nEntryCount  = poRAT->GetRowCount();
    int nColunsCount = poRAT->GetColumnCount();

    char szInsert[OWTEXT];

    CPLString osInserts = 
        "DECLARE\n"
        "  GR1  SDO_GEORASTER   := NULL;\n"
        "BEGIN\n";

    for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
    {
        szInsert[0] = '\0';

        strcat( szInsert, CPLSPrintf ( "  INSERT INTO %s VALUES (%d", 
            pszVATName, iEntry ) );

        for( iCol = 0; iCol < nColunsCount; iCol++ )
        {
            if( poRAT->GetTypeOfCol( iCol ) == GFT_String )
            {
                strcat( szInsert, CPLSPrintf ( ", '%s'", 
                    poRAT->GetValueAsString( iEntry, iCol ) ) );
            }
            if( poRAT->GetTypeOfCol( iCol ) == GFT_Integer ||
                poRAT->GetTypeOfCol( iCol ) == GFT_Real )
            {
                strcat( szInsert, CPLSPrintf ( ", %s", 
                    poRAT->GetValueAsString( iEntry, iCol ) ) );
            }
        }

        strcat( szInsert, ");\n" );
        osInserts += szInsert;
    }

    osInserts += CPLSPrintf(
        "  SELECT %s INTO GR1 FROM %s T WHERE\n"
        "    T.%s.RasterDataTable = '%s' AND\n"
        "    T.%s.RasterId = %d FOR UPDATE;\n"
        "  SDO_GEOR.setVAT(GR1, %d, '%s');\n"
        "  UPDATE %s T SET %s = GR1 WHERE\n"
        "    T.%s.RasterDataTable = '%s' AND\n"
        "    T.%s.RasterId = %d;\n"
        "END;",
        poGeoRaster->pszColumn, poGeoRaster->pszTable,
        poGeoRaster->pszColumn, poGeoRaster->pszDataTable,
        poGeoRaster->pszColumn, poGeoRaster->nRasterId,
        nBand, pszVATName,
        poGeoRaster->pszTable,  poGeoRaster->pszColumn,
        poGeoRaster->pszColumn, poGeoRaster->pszDataTable,
        poGeoRaster->pszColumn, poGeoRaster->nRasterId  );

    poStmt = poGeoRaster->poConnection->CreateStatement( osInserts.c_str() );

    if( ! poStmt->Execute() )
    {
        CPLError( CE_Failure, CPLE_AppDefined, "Insert/registering VAT Error!" );
        return CE_Failure;
    }

    delete poStmt;

    poGDS->poGeoRaster->SetVAT( nBand, pszVATName );

    return CE_None;
}
Exemple #21
0
int ISIS2Dataset::WriteLabel(
    CPLString osFilename, CPLString osRasterFile, CPLString sObjectTag,
    unsigned int nXSize, unsigned int nYSize, unsigned int nBands,
    GDALDataType eType,
    GUIntBig iRecords, const char * pszInterleaving,
    GUIntBig &iLabelRecords,
    CPL_UNUSED bool bRelaunch)
{
    CPLDebug("ISIS2", "Write Label filename = %s, rasterfile = %s",osFilename.c_str(),osRasterFile.c_str());
    bool bAttachedLabel = EQUAL(osRasterFile, "");

    VSILFILE *fpLabel = VSIFOpenL( osFilename, "w" );

    if( fpLabel == NULL ){
        CPLError( CE_Failure, CPLE_FileIO,
                  "Failed to create %s:\n%s",
                  osFilename.c_str(), VSIStrerror( errno ) );
        return FALSE;
    }

    unsigned int iLevel(0);
    unsigned int nWritingBytes(0);

    /* write common header */
    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "PDS_VERSION_ID", "PDS3" );
    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "");
    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "/* File identification and structure */");
    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "RECORD_TYPE", "FIXED_LENGTH" );
    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "RECORD_BYTES", CPLString().Printf("%d",RECORD_SIZE));
    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "FILE_RECORDS", CPLString().Printf(CPL_FRMT_GUIB,iRecords));
    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "LABEL_RECORDS", CPLString().Printf(CPL_FRMT_GUIB,iLabelRecords));
    if(!bAttachedLabel){
        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "FILE_NAME", CPLGetFilename(osRasterFile));
    }
    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "");

    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "/* Pointers to Data Objects */");

    if(bAttachedLabel){
        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, CPLString().Printf("^%s",sObjectTag.c_str()), CPLString().Printf(CPL_FRMT_GUIB,iLabelRecords+1));
    }else{
        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, CPLString().Printf("^%s",sObjectTag.c_str()), CPLString().Printf("(\"%s\",1)",CPLGetFilename(osRasterFile)));
    }

    if(EQUAL(sObjectTag, "QUBE")){
        ISIS2Dataset::WriteQUBE_Information(fpLabel, iLevel, nWritingBytes, nXSize, nYSize, nBands, eType, pszInterleaving);
    }

    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "END");

    // check if file record is correct
    unsigned int q = nWritingBytes/RECORD_SIZE;
    if( q <= iLabelRecords){
        // correct we add space after the label end for complete from iLabelRecords
        unsigned int nSpaceBytesToWrite = (unsigned int) (iLabelRecords * RECORD_SIZE - nWritingBytes);
        VSIFPrintfL(fpLabel,"%*c", nSpaceBytesToWrite, ' ');
    }else{
        iLabelRecords = q+1;
        ISIS2Dataset::WriteLabel(osFilename, osRasterFile, sObjectTag, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords);
    }
    VSIFCloseL( fpLabel );
  
    return TRUE;
}
Exemple #22
0
swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
                                 swq_expr_node **sub_node_values )

{
    swq_expr_node *poRetNode = NULL;
    swq_expr_node *poSrcNode = sub_node_values[0];

    switch( node->field_type )
    {
        case SWQ_INTEGER:
        {
            poRetNode = new swq_expr_node( 0 );

            switch( poSrcNode->field_type )
            {
                case SWQ_INTEGER:
                case SWQ_BOOLEAN:
                    poRetNode->int_value = poSrcNode->int_value;
                    break;

                case SWQ_FLOAT:
                    poRetNode->int_value = (int) poSrcNode->float_value;
                    break;

                default:
                    poRetNode->int_value = atoi(poSrcNode->string_value);
                    break;
            }
        }
        break;

        case SWQ_FLOAT:
        {
            poRetNode = new swq_expr_node( 0.0 );

            switch( poSrcNode->field_type )
            {
                case SWQ_INTEGER:
                case SWQ_BOOLEAN:
                    poRetNode->float_value = poSrcNode->int_value;
                    break;

                case SWQ_FLOAT:
                    poRetNode->float_value = poSrcNode->float_value;
                    break;

                default:
                    poRetNode->float_value = atof(poSrcNode->string_value);
                    break;
            }
        }
        break;

        // everything else is a string.
        default:
        {
            CPLString osRet;

            switch( poSrcNode->field_type )
            {
                case SWQ_INTEGER:
                case SWQ_BOOLEAN:
                    osRet.Printf( "%d", poSrcNode->int_value );
                    break;

                case SWQ_FLOAT:
                    osRet.Printf( "%.15g", poSrcNode->float_value );
                    break;

                default:
                    osRet = poSrcNode->string_value;
                    break;
            }
         
            if( node->nSubExprCount > 2 )
            {
                int nWidth;

                nWidth = sub_node_values[2]->int_value;
                if( nWidth > 0 && (int) strlen(osRet) > nWidth )
                    osRet.resize(nWidth);
            }

            poRetNode = new swq_expr_node( osRet.c_str() );
        }
    }

    return poRetNode;
}
Exemple #23
0
GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
{
/* -------------------------------------------------------------------- */
/*      Does this look like a CUBE or an IMAGE Primary Data Object?     */
/* -------------------------------------------------------------------- */
    if( !Identify( poOpenInfo ) )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Open the file using the large file API.                         */
/* -------------------------------------------------------------------- */
    VSILFILE *fpQube = VSIFOpenL( poOpenInfo->pszFilename, "rb" );

    if( fpQube == NULL )
        return NULL;

    ISIS2Dataset 	*poDS;

    poDS = new ISIS2Dataset();

    if( ! poDS->oKeywords.Ingest( fpQube, 0 ) )
    {
        VSIFCloseL( fpQube );
        delete poDS;
        return NULL;
    }
    
    VSIFCloseL( fpQube );

/* -------------------------------------------------------------------- */
/*	We assume the user is pointing to the label (ie. .lab) file.  	*/
/* -------------------------------------------------------------------- */
    // QUBE can be inline or detached and point to an image name
    // ^QUBE = 76
    // ^QUBE = ("ui31s015.img",6441<BYTES>) - has another label on the image
    // ^QUBE = "ui31s015.img" - which implies no label or skip value

    const char *pszQube = poDS->GetKeyword( "^QUBE" );
    GUIntBig nQube = 0;
    int bByteLocation = FALSE;
    CPLString osTargetFile = poOpenInfo->pszFilename;

    if( pszQube[0] == '"' )
    { 
        CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); 
        CPLString osFilename = pszQube;
        poDS->CleanString( osFilename ); 
        osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL ); 
        poDS->osExternalCube = osTargetFile;
    }
    else if( pszQube[0] == '(' ) 
    { 
        CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); 
        CPLString osFilename = poDS->GetKeywordSub("^QUBE",1,""); 
        poDS->CleanString( osFilename ); 
        osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL ); 
        poDS->osExternalCube = osTargetFile;

        nQube = atoi(poDS->GetKeywordSub("^QUBE",2,"1"));
        if( strstr(poDS->GetKeywordSub("^QUBE",2,"1"),"<BYTES>") != NULL )
            bByteLocation = true;
    } 
    else 
    { 
        nQube = atoi(pszQube);
        if( strstr(pszQube,"<BYTES>") != NULL )
            bByteLocation = true;
    }

/* -------------------------------------------------------------------- */
/*      Check if file an ISIS2 header file?  Read a few lines of text   */
/*      searching for something starting with nrows or ncols.           */
/* -------------------------------------------------------------------- */
    GDALDataType eDataType = GDT_Byte;
    OGRSpatialReference oSRS;

    //image parameters
    int	nRows, nCols, nBands = 1;
    GUIntBig nSkipBytes = 0;
    int itype;
    int  s_ix, s_iy, s_iz; // check SUFFIX_ITEMS params.
    int record_bytes;
    int	bNoDataSet = FALSE;
    char chByteOrder = 'M';  //default to MSB
 
    //Georef parameters
    double dfULXMap=0.5;
    double dfULYMap = 0.5;
    double dfXDim = 1.0;
    double dfYDim = 1.0;
    double dfNoData = 0.0;
    double xulcenter = 0.0;
    double yulcenter = 0.0;

    //projection parameters
    int	bProjectionSet = TRUE;
    double semi_major = 0.0;
    double semi_minor = 0.0;
    double iflattening = 0.0;
    double center_lat = 0.0;
    double center_lon = 0.0;
    double first_std_parallel = 0.0;
    double second_std_parallel = 0.0;
    VSILFILE	*fp;

    /* -------------------------------------------------------------------- */
    /*      Checks to see if this is valid ISIS2 cube                       */
    /*      SUFFIX_ITEM tag in .cub file should be (0,0,0); no side-planes  */
    /* -------------------------------------------------------------------- */
    s_ix = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 1 ));
    s_iy = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 2 ));
    s_iz = atoi(poDS->GetKeywordSub( "QUBE.SUFFIX_ITEMS", 3 ));
     
    if( s_ix != 0 || s_iy != 0 || s_iz != 0 ) 
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "*** ISIS 2 cube file has invalid SUFFIX_ITEMS parameters:\n"
                  "*** gdal isis2 driver requires (0, 0, 0), thus no sideplanes or backplanes\n"
                  "found: (%i, %i, %i)\n\n", s_ix, s_iy, s_iz );
        delete poDS;
        return NULL;
    } 

    /**************** end SUFFIX_ITEM check ***********************/
    
    
    /***********   Grab layout type (BSQ, BIP, BIL) ************/
    //  AXIS_NAME = (SAMPLE,LINE,BAND)
    /***********************************************************/
    const char *value;

    char szLayout[10] = "BSQ"; //default to band seq.
    value = poDS->GetKeyword( "QUBE.AXIS_NAME", "" );
    if (EQUAL(value,"(SAMPLE,LINE,BAND)") )
        strcpy(szLayout,"BSQ");
    else if (EQUAL(value,"(BAND,LINE,SAMPLE)") )
        strcpy(szLayout,"BIP");
    else if (EQUAL(value,"(SAMPLE,BAND,LINE)") || EQUAL(value,"") )
        strcpy(szLayout,"BSQ");
    else {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "%s layout not supported. Abort\n\n", value);
        delete poDS;
        return NULL;
    }

    /***********   Grab samples lines band ************/
    nCols = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",1));
    nRows = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",2));
    nBands = atoi(poDS->GetKeywordSub("QUBE.CORE_ITEMS",3));
    
    /***********   Grab Qube record bytes  **********/
    record_bytes = atoi(poDS->GetKeyword("RECORD_BYTES"));

    if (nQube > 0 && bByteLocation )
        nSkipBytes = (nQube - 1);
    else if( nQube > 0 )
        nSkipBytes = (nQube - 1) * record_bytes;     
    else
        nSkipBytes = 0;     
     
    /***********   Grab samples lines band ************/
    CPLString osCoreItemType = poDS->GetKeyword( "QUBE.CORE_ITEM_TYPE" );
    if( (EQUAL(osCoreItemType,"PC_INTEGER")) || 
        (EQUAL(osCoreItemType,"PC_UNSIGNED_INTEGER")) || 
        (EQUAL(osCoreItemType,"PC_REAL")) ) {
        chByteOrder = 'I';
    }
    
    /********   Grab format type - isis2 only supports 8,16,32 *******/
    itype = atoi(poDS->GetKeyword("QUBE.CORE_ITEM_BYTES",""));
    switch(itype) {
      case 1 :
        eDataType = GDT_Byte;
        dfNoData = NULL1;
        bNoDataSet = TRUE;
        break;
      case 2 :
        if( strstr(osCoreItemType,"UNSIGNED") != NULL )
        {
            dfNoData = 0;
            eDataType = GDT_UInt16;
        }
        else
        {
            dfNoData = NULL2;
            eDataType = GDT_Int16;
        }
        bNoDataSet = TRUE;
        break;
      case 4 :
        eDataType = GDT_Float32;
        dfNoData = NULL3;
        bNoDataSet = TRUE;
        break;
      case 8 :
        eDataType = GDT_Float64;
        dfNoData = NULL3;
        bNoDataSet = TRUE;
        break;
      default :
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Itype of %d is not supported in ISIS 2.",
                  itype); 
        delete poDS;
        return NULL;
    }

    /***********   Grab Cellsize ************/
    value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.MAP_SCALE");
    if (strlen(value) > 0 ) {
        dfXDim = (float) CPLAtof(value) * 1000.0; /* convert from km to m */
        dfYDim = (float) CPLAtof(value) * 1000.0 * -1;
    }
    
    /***********   Grab LINE_PROJECTION_OFFSET ************/
    value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.LINE_PROJECTION_OFFSET");
    if (strlen(value) > 0) {
        yulcenter = (float) CPLAtof(value);
        yulcenter = ((yulcenter) * dfYDim);
        dfULYMap = yulcenter - (dfYDim/2);
    }
     
    /***********   Grab SAMPLE_PROJECTION_OFFSET ************/
    value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.SAMPLE_PROJECTION_OFFSET");
    if( strlen(value) > 0 ) {
        xulcenter = (float) CPLAtof(value);
        xulcenter = ((xulcenter) * dfXDim);
        dfULXMap = xulcenter - (dfXDim/2);
    }
     
    /***********  Grab TARGET_NAME  ************/
    /**** This is the planets name i.e. MARS ***/
    CPLString target_name = poDS->GetKeyword("QUBE.TARGET_NAME");
     
    /***********   Grab MAP_PROJECTION_TYPE ************/
    CPLString map_proj_name = 
        poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.MAP_PROJECTION_TYPE");
    poDS->CleanString( map_proj_name );

    /***********   Grab SEMI-MAJOR ************/
    semi_major = 
        CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.A_AXIS_RADIUS")) * 1000.0;

    /***********   Grab semi-minor ************/
    semi_minor = 
        CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.C_AXIS_RADIUS")) * 1000.0;

    /***********   Grab CENTER_LAT ************/
    center_lat = 
        CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.CENTER_LATITUDE"));

    /***********   Grab CENTER_LON ************/
    center_lon = 
        CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.CENTER_LONGITUDE"));

    /***********   Grab 1st std parallel ************/
    first_std_parallel = 
        CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.FIRST_STANDARD_PARALLEL"));

    /***********   Grab 2nd std parallel ************/
    second_std_parallel = 
        CPLAtof(poDS->GetKeyword( "QUBE.IMAGE_MAP_PROJECTION.SECOND_STANDARD_PARALLEL"));
     
    /*** grab  PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/
    // Need to further study how ocentric/ographic will effect the gdal library.
    // So far we will use this fact to define a sphere or ellipse for some projections
    // Frank - may need to talk this over
    char bIsGeographic = TRUE;
    value = poDS->GetKeyword("CUBE.IMAGE_MAP_PROJECTION.PROJECTION_LATITUDE_TYPE");
    if (EQUAL( value, "\"PLANETOCENTRIC\"" ))
        bIsGeographic = FALSE; 
     
    CPLDebug("ISIS2","using projection %s", map_proj_name.c_str() );

    //Set oSRS projection and parameters
    if ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) ||
        (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ||
        (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ) {
        oSRS.OGRSpatialReference::SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 );
    } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) { 
        oSRS.OGRSpatialReference::SetOrthographic ( center_lat, center_lon, 0, 0 );
    } else if ((EQUAL( map_proj_name, "SINUSOIDAL" )) ||
               (EQUAL( map_proj_name, "SINUSOIDAL_EQUAL-AREA" ))) {
        oSRS.OGRSpatialReference::SetSinusoidal ( center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "MERCATOR" )) {
        oSRS.OGRSpatialReference::SetMercator ( center_lat, center_lon, 1, 0, 0 );
    } else if (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )) {
        oSRS.OGRSpatialReference::SetPS ( center_lat, center_lon, 1, 0, 0 );
    } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) {
        oSRS.OGRSpatialReference::SetTM ( center_lat, center_lon, 1, 0, 0 );
    } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) {
        oSRS.OGRSpatialReference::SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "") ) {
        /* no projection */
        bProjectionSet = FALSE;
    } else {
        CPLDebug( "ISIS2",
                  "Dataset projection %s is not supported. Continuing...",
                  map_proj_name.c_str() );
        bProjectionSet = FALSE;
    }

    if (bProjectionSet) {
        //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
        CPLString proj_target_name = map_proj_name + " " + target_name;
        oSRS.SetProjCS(proj_target_name); //set ProjCS keyword
     
        //The geographic/geocentric name will be the same basic name as the body name
        //'GCS' = Geographic/Geocentric Coordinate System
        CPLString geog_name = "GCS_" + target_name;
        
        //The datum and sphere names will be the same basic name aas the planet
        CPLString datum_name = "D_" + target_name;
        CPLString sphere_name = target_name; // + "_IAU_IAG");  //Might not be IAU defined so don't add
          
        //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
        if ((semi_major - semi_minor) < 0.0000001) 
            iflattening = 0;
        else
            iflattening = semi_major / (semi_major - semi_minor);
     
        //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
        //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
        if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || 
             (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))  
        {
            if (bIsGeographic) { 
                //Geograpraphic, so set an ellipse
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_major, iflattening, 
                                "Reference_Meridian", 0.0 );
            } else {
                //Geocentric, so force a sphere using the semi-minor axis. I hope... 
                sphere_name += "_polarRadius";
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_minor, 0.0, 
                                "Reference_Meridian", 0.0 );
            }
        }
        else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || 
                  (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) ||
                  (EQUAL( map_proj_name, "STEREOGRAPHIC" )) ||
                  (EQUAL( map_proj_name, "SINUSOIDAL_EQUAL-AREA" )) ||
                  (EQUAL( map_proj_name, "SINUSOIDAL" ))  ) {
            //isis uses the sphereical equation for these projections so force a sphere
            oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                            semi_major, 0.0, 
                            "Reference_Meridian", 0.0 );
        } 
        else if  ((EQUAL( map_proj_name, "EQUIRECTANGULAR_CYLINDRICAL" )) || 
                  (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ) {
            //Calculate localRadius using ISIS3 simple elliptical method 
            //  not the more standard Radius of Curvature method
            //PI = 4 * atan(1);
            double radLat, localRadius;
            if (center_lon == 0) { //No need to calculate local radius
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_major, 0.0, 
                                "Reference_Meridian", 0.0 );
            } else {  
                radLat = center_lat * M_PI / 180;  // in radians
                localRadius = semi_major * semi_minor / sqrt(pow(semi_minor*cos(radLat),2)
                                                             + pow(semi_major*sin(radLat),2) );
                sphere_name += "_localRadius";
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                localRadius, 0.0, 
                                "Reference_Meridian", 0.0 );
                CPLDebug( "ISIS2", "local radius: %f", localRadius);
            }
        } 
        else { 
            //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
            //Geographic, so set an ellipse
            if (bIsGeographic) {
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_major, iflattening, 
                                "Reference_Meridian", 0.0 );
            } else { 
                //Geocentric, so force a sphere. I hope... 
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_major, 0.0, 
                                "Reference_Meridian", 0.0 );
            }
        }
        

        // translate back into a projection string.
        char *pszResult = NULL;
        oSRS.exportToWkt( &pszResult );
        poDS->osProjection = pszResult;
        CPLFree( pszResult );
    }

/* END ISIS2 Label Read */
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    
/* -------------------------------------------------------------------- */
/*      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 || nBands < 1 )
    {
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Capture some information from the file that is of interest.     */
/* -------------------------------------------------------------------- */
    poDS->nRasterXSize = nCols;
    poDS->nRasterYSize = nRows;

/* -------------------------------------------------------------------- */
/*      Open target binary file.                                        */
/* -------------------------------------------------------------------- */
    
    if( poOpenInfo->eAccess == GA_ReadOnly )
        poDS->fpImage = VSIFOpenL( osTargetFile, "rb" );
    else
        poDS->fpImage = VSIFOpenL( osTargetFile, "r+b" );

    if( poDS->fpImage == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "Failed to open %s with write permission.\n%s", 
                  osTargetFile.c_str(), VSIStrerror( errno ) );
        delete poDS;
        return NULL;
    }

    poDS->eAccess = poOpenInfo->eAccess;

/* -------------------------------------------------------------------- */
/*      Compute the line offset.                                        */
/* -------------------------------------------------------------------- */
    int     nItemSize = GDALGetDataTypeSize(eDataType)/8;
    int		nLineOffset, nPixelOffset, nBandOffset;
    
    if( EQUAL(szLayout,"BIP") )
    {
        nPixelOffset = nItemSize * nBands;
        nLineOffset = nPixelOffset * nCols;
        nBandOffset = nItemSize;
    }
    else if( EQUAL(szLayout,"BSQ") )
    {
        nPixelOffset = nItemSize;
        nLineOffset = nPixelOffset * nCols;
        nBandOffset = nLineOffset * nRows;
    }
    else /* assume BIL */
    {
        nPixelOffset = nItemSize;
        nLineOffset = nItemSize * nBands * nCols;
        nBandOffset = nItemSize * nCols;
    }
    
/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    int i;

    poDS->nBands = nBands;;
    for( i = 0; i < poDS->nBands; i++ )
    {
        RawRasterBand	*poBand;

        poBand = 
            new RawRasterBand( poDS, i+1, poDS->fpImage,
                               nSkipBytes + nBandOffset * i, 
                               nPixelOffset, nLineOffset, eDataType,
#ifdef CPL_LSB                               
                               chByteOrder == 'I' || chByteOrder == 'L',
#else
                               chByteOrder == 'M',
#endif        
                               TRUE );

        if( bNoDataSet )
            poBand->SetNoDataValue( dfNoData );

        poDS->SetBand( i+1, poBand );

        // Set offset/scale values at the PAM level.
        poBand->SetOffset( 
            CPLAtofM(poDS->GetKeyword("QUBE.CORE_BASE","0.0")));
        poBand->SetScale( 
            CPLAtofM(poDS->GetKeyword("QUBE.CORE_MULTIPLIER","1.0")));
    }

/* -------------------------------------------------------------------- */
/*      Check for a .prj file. For isis2 I would like to keep this in   */
/* -------------------------------------------------------------------- */
    CPLString osPath, osName;

    osPath = CPLGetPath( poOpenInfo->pszFilename );
    osName = CPLGetBasename(poOpenInfo->pszFilename);
    const char  *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" );

    fp = VSIFOpenL( pszPrjFile, "r" );
    if( fp != NULL )
    {
        char	**papszLines;
        OGRSpatialReference oSRS;

        VSIFCloseL( fp );
        
        papszLines = CSLLoad( pszPrjFile );

        if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
        {
            char *pszResult = NULL;
            oSRS.exportToWkt( &pszResult );
            poDS->osProjection = pszResult;
            CPLFree( pszResult );
        }

        CSLDestroy( papszLines );
    }

    if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
    {
        poDS->bGotTransform = TRUE;
        poDS->adfGeoTransform[0] = dfULXMap;
        poDS->adfGeoTransform[1] = dfXDim;
        poDS->adfGeoTransform[2] = 0.0;
        poDS->adfGeoTransform[3] = dfULYMap;
        poDS->adfGeoTransform[4] = 0.0;
        poDS->adfGeoTransform[5] = dfYDim;
    }

    if( !poDS->bGotTransform )
        poDS->bGotTransform = 
            GDALReadWorldFile( poOpenInfo->pszFilename, "cbw", 
                               poDS->adfGeoTransform );

    if( !poDS->bGotTransform )
        poDS->bGotTransform = 
            GDALReadWorldFile( poOpenInfo->pszFilename, "wld", 
                               poDS->adfGeoTransform );

/* -------------------------------------------------------------------- */ 
/*      Initialize any PAM information.                                 */ 
/* -------------------------------------------------------------------- */ 
    poDS->SetDescription( poOpenInfo->pszFilename ); 
    poDS->TryLoadXML(); 

/* -------------------------------------------------------------------- */
/*      Check for overviews.                                            */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );

    return( poDS );
}
Exemple #24
0
swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                                    swq_expr_node **sub_node_values )

{
    swq_expr_node *poRet = NULL;

/* -------------------------------------------------------------------- */
/*      Floating point operations.                                      */
/* -------------------------------------------------------------------- */
    if( sub_node_values[0]->field_type == SWQ_FLOAT 
        || (node->nSubExprCount > 1 
            && sub_node_values[1]->field_type == SWQ_FLOAT) )
            
    {
        poRet = new swq_expr_node(0);
        poRet->field_type = node->field_type;

        if( sub_node_values[0]->field_type == SWQ_INTEGER )
            sub_node_values[0]->float_value = sub_node_values[0]->int_value;
        if( sub_node_values[1]->field_type == SWQ_INTEGER )
            sub_node_values[1]->float_value = sub_node_values[1]->int_value;

        switch( (swq_op) node->nOperation )
        {
          case SWQ_EQ:
            poRet->int_value = sub_node_values[0]->float_value 
                == sub_node_values[1]->float_value;
            break;

          case SWQ_NE:
            poRet->int_value = sub_node_values[0]->float_value 
                != sub_node_values[1]->float_value;
            break;

          case SWQ_GT:
            poRet->int_value = sub_node_values[0]->float_value 
                > sub_node_values[1]->float_value;
            break;

          case SWQ_LT:
            poRet->int_value = sub_node_values[0]->float_value 
                < sub_node_values[1]->float_value;
            break;

          case SWQ_GE:
            poRet->int_value = sub_node_values[0]->float_value 
                >= sub_node_values[1]->float_value;
            break;

          case SWQ_LE:
            poRet->int_value = sub_node_values[0]->float_value 
                <= sub_node_values[1]->float_value;
            break;

          case SWQ_IN:
          {
              int i;
              poRet->int_value = 0;
              for( i = 1; i < node->nSubExprCount; i++ )
              {
                  if( sub_node_values[0]->float_value 
                      == sub_node_values[i]->float_value )
                  {
                      poRet->int_value = 1;
                      break;
                  }
              }
          }
          break;

          case SWQ_BETWEEN:
            poRet->int_value = sub_node_values[0]->float_value
                                >= sub_node_values[1]->float_value &&
                               sub_node_values[0]->float_value
                                <= sub_node_values[2]->float_value;
            break;

          case SWQ_ISNULL:
            poRet->int_value = sub_node_values[0]->is_null;
            break;

          case SWQ_ADD:
            poRet->float_value = sub_node_values[0]->float_value 
                + sub_node_values[1]->float_value;
            break;
            
          case SWQ_SUBTRACT:
            poRet->float_value = sub_node_values[0]->float_value 
                - sub_node_values[1]->float_value;
            break;
            
          case SWQ_MULTIPLY:
            poRet->float_value = sub_node_values[0]->float_value 
                * sub_node_values[1]->float_value;
            break;
            
          case SWQ_DIVIDE:
            if( sub_node_values[1]->float_value == 0 )
                poRet->float_value = INT_MAX;
            else
                poRet->float_value = sub_node_values[0]->float_value 
                    / sub_node_values[1]->float_value;
            break;
            
          case SWQ_MODULUS:
          {
            int nRight = (int) sub_node_values[1]->float_value;
            poRet->field_type = SWQ_INTEGER;
            if (nRight == 0)
                poRet->int_value = INT_MAX;
            else
                poRet->int_value = ((int) sub_node_values[0]->float_value)
                    % nRight;
            break;
          }

          default:
            CPLAssert( FALSE );
            delete poRet;
            poRet = NULL;
            break;
        }
    }
/* -------------------------------------------------------------------- */
/*      integer/boolean operations.                                     */
/* -------------------------------------------------------------------- */
    else if( sub_node_values[0]->field_type == SWQ_INTEGER
        || sub_node_values[0]->field_type == SWQ_BOOLEAN )
    {
        poRet = new swq_expr_node(0);
        poRet->field_type = node->field_type;

        switch( (swq_op) node->nOperation )
        {
          case SWQ_AND:
            poRet->int_value = sub_node_values[0]->int_value 
                && sub_node_values[1]->int_value;
            break;
            
          case SWQ_OR:
            poRet->int_value = sub_node_values[0]->int_value 
                || sub_node_values[1]->int_value;
            break;
            
          case SWQ_NOT:
            poRet->int_value = !sub_node_values[0]->int_value;
            break;
            
          case SWQ_EQ:
            poRet->int_value = sub_node_values[0]->int_value 
                == sub_node_values[1]->int_value;
            break;

          case SWQ_NE:
            poRet->int_value = sub_node_values[0]->int_value 
                != sub_node_values[1]->int_value;
            break;

          case SWQ_GT:
            poRet->int_value = sub_node_values[0]->int_value 
                > sub_node_values[1]->int_value;
            break;

          case SWQ_LT:
            poRet->int_value = sub_node_values[0]->int_value 
                < sub_node_values[1]->int_value;
            break;

          case SWQ_GE:
            poRet->int_value = sub_node_values[0]->int_value 
                >= sub_node_values[1]->int_value;
            break;

          case SWQ_LE:
            poRet->int_value = sub_node_values[0]->int_value 
                <= sub_node_values[1]->int_value;
            break;

          case SWQ_IN:
          {
              int i;
              poRet->int_value = 0;
              for( i = 1; i < node->nSubExprCount; i++ )
              {
                  if( sub_node_values[0]->int_value 
                      == sub_node_values[i]->int_value )
                  {
                      poRet->int_value = 1;
                      break;
                  }
              }
          }
          break;

          case SWQ_BETWEEN:
            poRet->int_value = sub_node_values[0]->int_value
                                >= sub_node_values[1]->int_value &&
                               sub_node_values[0]->int_value
                                <= sub_node_values[2]->int_value;
            break;

          case SWQ_ISNULL:
            poRet->int_value = sub_node_values[0]->is_null;
            break;

          case SWQ_ADD:
            poRet->int_value = sub_node_values[0]->int_value 
                + sub_node_values[1]->int_value;
            break;
            
          case SWQ_SUBTRACT:
            poRet->int_value = sub_node_values[0]->int_value 
                - sub_node_values[1]->int_value;
            break;
            
          case SWQ_MULTIPLY:
            poRet->int_value = sub_node_values[0]->int_value 
                * sub_node_values[1]->int_value;
            break;
            
          case SWQ_DIVIDE:
            if( sub_node_values[1]->int_value == 0 )
                poRet->int_value = INT_MAX;
            else
                poRet->int_value = sub_node_values[0]->int_value 
                    / sub_node_values[1]->int_value;
            break;
            
          case SWQ_MODULUS:
            if( sub_node_values[1]->int_value == 0 )
                poRet->int_value = INT_MAX;
            else
                poRet->int_value = sub_node_values[0]->int_value
                    % sub_node_values[1]->int_value;
            break;
            
          default:
            CPLAssert( FALSE );
            delete poRet;
            poRet = NULL;
            break;
        }
    }

/* -------------------------------------------------------------------- */
/*      String operations.                                              */
/* -------------------------------------------------------------------- */
    else
    {
        poRet = new swq_expr_node(0);
        poRet->field_type = node->field_type;

        switch( (swq_op) node->nOperation )
        {
          case SWQ_EQ:
            poRet->int_value = 
                strcasecmp(sub_node_values[0]->string_value,
                           sub_node_values[1]->string_value) == 0;
            break;

          case SWQ_NE:
            poRet->int_value = 
                strcasecmp(sub_node_values[0]->string_value,
                           sub_node_values[1]->string_value) != 0;
            break;

          case SWQ_GT:
            poRet->int_value = 
                strcasecmp(sub_node_values[0]->string_value,
                           sub_node_values[1]->string_value) > 0;
            break;

          case SWQ_LT:
            poRet->int_value = 
                strcasecmp(sub_node_values[0]->string_value,
                           sub_node_values[1]->string_value) < 0;
            break;

          case SWQ_GE:
            poRet->int_value = 
                strcasecmp(sub_node_values[0]->string_value,
                           sub_node_values[1]->string_value) >= 0;
            break;

          case SWQ_LE:
            poRet->int_value = 
                strcasecmp(sub_node_values[0]->string_value,
                           sub_node_values[1]->string_value) <= 0;
            break;

          case SWQ_IN:
          {
              int i;
              poRet->int_value = 0;
              for( i = 1; i < node->nSubExprCount; i++ )
              {
                  if( strcasecmp(sub_node_values[0]->string_value,
                                 sub_node_values[i]->string_value) == 0 )
                  {
                      poRet->int_value = 1;
                      break;
                  }
              }
          }
          break;

          case SWQ_BETWEEN:
            poRet->int_value =
                strcasecmp(sub_node_values[0]->string_value,
                           sub_node_values[1]->string_value) >= 0 &&
                strcasecmp(sub_node_values[0]->string_value,
                           sub_node_values[2]->string_value) <= 0;
            break;

          case SWQ_LIKE:
            poRet->int_value = swq_test_like(sub_node_values[0]->string_value,
                                             sub_node_values[1]->string_value);
            break;

          case SWQ_ISNULL:
            poRet->int_value = sub_node_values[0]->is_null;
            break;

          case SWQ_CONCAT:
          case SWQ_ADD:
          {
              CPLString osResult = sub_node_values[0]->string_value;
              int i;

              for( i = 1; i < node->nSubExprCount; i++ )
                  osResult += sub_node_values[i]->string_value;
              
              poRet->string_value = CPLStrdup(osResult);
              break;
          }
            
          case SWQ_SUBSTR:
          {
              int nOffset, nSize;
              const char *pszSrcStr = sub_node_values[0]->string_value;

              if( sub_node_values[1]->field_type == SWQ_INTEGER )
                  nOffset = sub_node_values[1]->int_value;
              else if( sub_node_values[1]->field_type == SWQ_FLOAT )
                  nOffset = (int) sub_node_values[1]->float_value; 
              else
                  nOffset = 0;

              if( node->nSubExprCount < 3 )
                  nSize = 100000;
              else if( sub_node_values[2]->field_type == SWQ_INTEGER )
                  nSize = sub_node_values[2]->int_value;
              else if( sub_node_values[2]->field_type == SWQ_FLOAT )
                  nSize = (int) sub_node_values[2]->float_value; 
              else
                  nSize = 0;

              int nSrcStrLen = (int)strlen(pszSrcStr);
              if( nOffset < 0 || nSize < 0 || nOffset > nSrcStrLen )
              {
                  nOffset = 0;
                  nSize = 0;
              }
              else if( nOffset + nSize > nSrcStrLen )
                  nSize = nSrcStrLen - nOffset;

              CPLString osResult = pszSrcStr + nOffset;
              if( (int)osResult.size() > nSize )
                  osResult.resize( nSize );
              
              poRet->string_value = CPLStrdup(osResult);
              break;
          }

          default:
            CPLAssert( FALSE );
            delete poRet;
            poRet = NULL;
            break;
        }
    }

    return poRet;
}
GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
{
/* -------------------------------------------------------------------- */
/*      Does this look like a VICAR dataset?                             */
/* -------------------------------------------------------------------- */
    if( !Identify( poOpenInfo ) )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Open the file using the large file API.                         */
/* -------------------------------------------------------------------- */
    VSILFILE *fpQube = VSIFOpenL( poOpenInfo->pszFilename, "rb" );

    if( fpQube == NULL )
        return NULL;

    VICARDataset 	*poDS;

    poDS = new VICARDataset();
    if( ! poDS->oKeywords.Ingest( fpQube, poOpenInfo->pabyHeader ) ) {
        VSIFCloseL( fpQube );
        delete poDS;
        return NULL;
    }
    
    VSIFCloseL( fpQube );

    CPLString osQubeFile;
    osQubeFile = poOpenInfo->pszFilename;
    GDALDataType eDataType = GDT_Byte;

    int	nRows = -1;
    int nCols = -1;
    int nBands = 1;
    int nSkipBytes = 0;
    int bIsDTM = FALSE;
    char chByteOrder = 'M';
    double dfNoData = 0.0;
    const char *value;
    
    /***** CHECK ENDIANNESS **************/
    
    value = poDS->GetKeyword( "INTFMT" );
    if (!EQUAL(value,"LOW") ) {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "%s layout not supported. Abort\n\n", value);
        return FALSE;
    }
    value = poDS->GetKeyword( "REALFMT" );
    if (!EQUAL(value,"RIEEE") ) {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "%s layout not supported. Abort\n\n", value);
        return FALSE;
    }
    value = poDS->GetKeyword( "BREALFMT" );
    if (EQUAL(value,"VAX") ) {
        chByteOrder = 'I';
    }
    
    /************ CHECK INSTRUMENT *****************/
    /************ ONLY HRSC TESTED *****************/
    
    value = poDS->GetKeyword( "DTM.DTM_OFFSET" );
    if (!EQUAL(value,"") ) {
        bIsDTM = TRUE;
    }
    
    
    value = poDS->GetKeyword( "BLTYPE" );
    if (!EQUAL(value,"M94_HRSC") && bIsDTM==FALSE ) {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "%s instrument not tested. Continue with caution!\n\n", value);
    }
    
    /***********   Grab layout type (BSQ, BIP, BIL) ************/
    
    char szLayout[10] = "BSQ"; //default to band seq.
    value = poDS->GetKeyword( "ORG" );
    if (EQUAL(value,"BSQ") ) {
        strcpy(szLayout,"BSQ");
        nCols = atoi(poDS->GetKeyword("NS"));
        nRows = atoi(poDS->GetKeyword("NL"));
        nBands = atoi(poDS->GetKeyword("NB"));
    }
    else {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "%s layout not supported. Abort\n\n", value);
        return FALSE;
    }
    
    /***********   Grab record bytes  **********/
    nSkipBytes = atoi(poDS->GetKeyword("NBB"));
    
    if (EQUAL( poDS->GetKeyword( "FORMAT" ), "BYTE" )) {
        eDataType = GDT_Byte;
        dfNoData = NULL1;
    }
    else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "HALF" )) {
        eDataType = GDT_Int16;
        dfNoData = NULL2;
        chByteOrder = 'I';
    }
    else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "FULL" )) {
        eDataType = GDT_UInt32;
        dfNoData = 0;
    } 
    else if (EQUAL( poDS->GetKeyword( "FORMAT" ), "REAL" )) {
        eDataType = GDT_Float32;
        dfNoData = NULL3;
        chByteOrder = 'I';
    }
    else {
	    printf("Could not find known VICAR label entries!\n");
        delete poDS;
        return NULL;
    }

    if( nRows < 1 || nCols < 1 || nBands < 1 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "File %s appears to be a VICAR file, but failed to find some required keywords.", 
                  poDS->GetDescription() );
        return FALSE;
    }
/* -------------------------------------------------------------------- */
/*      Capture some information from the file that is of interest.     */
/* -------------------------------------------------------------------- */
    poDS->nRasterXSize = nCols;
    poDS->nRasterYSize = nRows;

    double dfULXMap=0.5;
    double dfULYMap = 0.5;
    double dfXDim = 1.0;
    double dfYDim = 1.0;
    double xulcenter = 0.0;
    double yulcenter = 0.0;

    value = poDS->GetKeyword("MAP.MAP_SCALE");
    if (strlen(value) > 0 ) {
        dfXDim = CPLAtof(value);
        dfYDim = CPLAtof(value) * -1;
        dfXDim = dfXDim * 1000.0;
        dfYDim = dfYDim * 1000.0;
    }

    double   dfSampleOffset_Shift;
    double   dfLineOffset_Shift;
    double   dfSampleOffset_Mult;
    double   dfLineOffset_Mult;
    
    dfSampleOffset_Shift = 
        CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Shift", "0.5" ));
    
    dfLineOffset_Shift = 
        CPLAtof(CPLGetConfigOption( "PDS_LineProjOffset_Shift", "0.5" ));

    dfSampleOffset_Mult =
        CPLAtof(CPLGetConfigOption( "PDS_SampleProjOffset_Mult", "-1.0") );

    dfLineOffset_Mult = 
        CPLAtof( CPLGetConfigOption( "PDS_LineProjOffset_Mult", "1.0") );

    /***********   Grab LINE_PROJECTION_OFFSET ************/
    value = poDS->GetKeyword("MAP.LINE_PROJECTION_OFFSET");
    if (strlen(value) > 0) {
        yulcenter = CPLAtof(value);
        dfULYMap = ((yulcenter + dfLineOffset_Shift) * -dfYDim * dfLineOffset_Mult);
    }
    /***********   Grab SAMPLE_PROJECTION_OFFSET ************/
    value = poDS->GetKeyword("MAP.SAMPLE_PROJECTION_OFFSET");
    if( strlen(value) > 0 ) {
        xulcenter = CPLAtof(value);
        dfULXMap = ((xulcenter + dfSampleOffset_Shift) * dfXDim * dfSampleOffset_Mult);
    }
    
/* ==================================================================== */
/*      Get the coordinate system.                                      */
/* ==================================================================== */
    int	bProjectionSet = TRUE;
    double semi_major = 0.0;
    double semi_minor = 0.0;
    double iflattening = 0.0;
    double center_lat = 0.0;
    double center_lon = 0.0;
    double first_std_parallel = 0.0;
    double second_std_parallel = 0.0;    
    OGRSpatialReference oSRS;
    
    /***********  Grab TARGET_NAME  ************/
    /**** This is the planets name i.e. MARS ***/
    CPLString target_name = poDS->GetKeyword("MAP.TARGET_NAME");
     
    /**********   Grab MAP_PROJECTION_TYPE *****/
    CPLString map_proj_name = 
        poDS->GetKeyword( "MAP.MAP_PROJECTION_TYPE");
     
    /******  Grab semi_major & convert to KM ******/
    semi_major = 
        CPLAtof(poDS->GetKeyword( "MAP.A_AXIS_RADIUS")) * 1000.0;
    
    /******  Grab semi-minor & convert to KM ******/
    semi_minor = 
        CPLAtof(poDS->GetKeyword( "MAP.C_AXIS_RADIUS")) * 1000.0;

    /***********   Grab CENTER_LAT ************/
    center_lat = 
        CPLAtof(poDS->GetKeyword( "MAP.CENTER_LATITUDE"));

    /***********   Grab CENTER_LON ************/
    center_lon = 
        CPLAtof(poDS->GetKeyword( "MAP.CENTER_LONGITUDE"));

    /**********   Grab 1st std parallel *******/
    first_std_parallel = 
        CPLAtof(poDS->GetKeyword( "MAP.FIRST_STANDARD_PARALLEL"));

    /**********   Grab 2nd std parallel *******/
    second_std_parallel = 
        CPLAtof(poDS->GetKeyword( "MAP.SECOND_STANDARD_PARALLEL"));
     
    /*** grab  PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/
    // Need to further study how ocentric/ographic will effect the gdal library.
    // So far we will use this fact to define a sphere or ellipse for some projections
    // Frank - may need to talk this over
    char bIsGeographic = TRUE;
    value = poDS->GetKeyword("MAP.COORDINATE_SYSTEM_NAME");
    if (EQUAL( value, "PLANETOCENTRIC" ))
        bIsGeographic = FALSE; 

/**   Set oSRS projection and parameters --- all PDS supported types added if apparently supported in oSRS
      "AITOFF",  ** Not supported in GDAL??
      "ALBERS", 
      "BONNE",
      "BRIESEMEISTER",   ** Not supported in GDAL??
      "CYLINDRICAL EQUAL AREA",
      "EQUIDISTANT",
      "EQUIRECTANGULAR",
      "GNOMONIC",
      "HAMMER",    ** Not supported in GDAL??
      "HENDU",     ** Not supported in GDAL??
      "LAMBERT AZIMUTHAL EQUAL AREA",
      "LAMBERT CONFORMAL",
      "MERCATOR",
      "MOLLWEIDE",
      "OBLIQUE CYLINDRICAL",
      "ORTHOGRAPHIC",
      "SIMPLE CYLINDRICAL",
      "SINUSOIDAL",
      "STEREOGRAPHIC",
      "TRANSVERSE MERCATOR",
      "VAN DER GRINTEN",     ** Not supported in GDAL??
      "WERNER"     ** Not supported in GDAL?? 
**/ 
    CPLDebug( "PDS","using projection %s\n\n", map_proj_name.c_str());

    if ((EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ||
        (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ||
        (EQUAL( map_proj_name, "EQUIDISTANT" )) )  {
        oSRS.SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 );
    } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) {
        oSRS.SetOrthographic ( center_lat, center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "SINUSOIDAL" )) {
        oSRS.SetSinusoidal ( center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "MERCATOR" )) {
        oSRS.SetMercator ( center_lat, center_lon, 1, 0, 0 );
    } else if (EQUAL( map_proj_name, "STEREOGRAPHIC" )) {
        oSRS.SetStereographic ( center_lat, center_lon, 1, 0, 0 );
    } else if (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC")) {
        oSRS.SetPS ( center_lat, center_lon, 1, 0, 0 );
    } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) {
        oSRS.SetTM ( center_lat, center_lon, 1, 0, 0 );
    } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) {
        oSRS.SetLCC ( first_std_parallel, second_std_parallel, 
                      center_lat, center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "LAMBERT_AZIMUTHAL_EQUAL_AREA" )) {
        oSRS.SetLAEA( center_lat, center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "CYLINDRICAL_EQUAL_AREA" )) {
        oSRS.SetCEA  ( first_std_parallel, center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "MOLLWEIDE" )) {
        oSRS.SetMollweide ( center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "ALBERS" )) {
        oSRS.SetACEA ( first_std_parallel, second_std_parallel, 
                       center_lat, center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "BONNE" )) {
        oSRS.SetBonne ( first_std_parallel, center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "GNOMONIC" )) {
        oSRS.SetGnomonic ( center_lat, center_lon, 0, 0 );
    } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) { 
        // hope Swiss Oblique Cylindrical is the same
        oSRS.SetSOC ( center_lat, center_lon, 0, 0 );
    } else {
        CPLDebug( "VICAR",
                  "Dataset projection %s is not supported. Continuing...",
                  map_proj_name.c_str() );
        bProjectionSet = FALSE;
    }

    if (bProjectionSet) {
        //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
        CPLString proj_target_name = map_proj_name + " " + target_name;
        oSRS.SetProjCS(proj_target_name); //set ProjCS keyword
     
        //The geographic/geocentric name will be the same basic name as the body name
        //'GCS' = Geographic/Geocentric Coordinate System
        CPLString geog_name = "GCS_" + target_name;
        
        //The datum and sphere names will be the same basic name aas the planet
        CPLString datum_name = "D_" + target_name;
        CPLString sphere_name = target_name; // + "_IAU_IAG");  //Might not be IAU defined so don't add
          
        //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
        if ((semi_major - semi_minor) < 0.0000001) 
            iflattening = 0;
        else
            iflattening = semi_major / (semi_major - semi_minor);
     
        //Set the body size but take into consideration which proj is being used to help w/ compatibility
        //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical 
        //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
        //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
        if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || 
             (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))  
        {
            if (bIsGeographic) { 
                //Geograpraphic, so set an ellipse
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_major, iflattening, 
                                "Reference_Meridian", 0.0 );
            } else {
                //Geocentric, so force a sphere using the semi-minor axis. I hope... 
                sphere_name += "_polarRadius";
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_minor, 0.0, 
                                "Reference_Meridian", 0.0 );
            }
        }
        else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || 
                  (EQUAL( map_proj_name, "EQUIDISTANT" )) || 
                  (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || 
                  (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || 
                  (EQUAL( map_proj_name, "SINUSOIDAL" )) ) {
            //isis uses the spherical equation for these projections so force a sphere
            oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                            semi_major, 0.0, 
                            "Reference_Meridian", 0.0 );
        } 
        else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) { 
            //isis uses local radius as a sphere, which is pre-calculated in the PDS label as the semi-major
            sphere_name += "_localRadius";
            oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                            semi_major, 0.0, 
                            "Reference_Meridian", 0.0 );
        } 
        else { 
            //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
            //Geographic, so set an ellipse
            if (bIsGeographic) {
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_major, iflattening, 
                                "Reference_Meridian", 0.0 );
            } else { 
                //Geocentric, so force a sphere. I hope... 
                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
                                semi_major, 0.0, 
                                "Reference_Meridian", 0.0 );
            }
        }

        // translate back into a projection string.
        char *pszResult = NULL;
        oSRS.exportToWkt( &pszResult );
        poDS->osProjection = pszResult;
        CPLFree( pszResult );
    }
    {
        poDS->bGotTransform = TRUE;
        poDS->adfGeoTransform[0] = dfULXMap;
        poDS->adfGeoTransform[1] = dfXDim;
        poDS->adfGeoTransform[2] = 0.0;
        poDS->adfGeoTransform[3] = dfULYMap;
        poDS->adfGeoTransform[4] = 0.0;
        poDS->adfGeoTransform[5] = dfYDim;
    }
    
    if( !poDS->bGotTransform )
        poDS->bGotTransform = 
            GDALReadWorldFile( osQubeFile, "psw", 
                               poDS->adfGeoTransform );

    if( !poDS->bGotTransform )
        poDS->bGotTransform = 
            GDALReadWorldFile( osQubeFile, "wld", 
                               poDS->adfGeoTransform );


/* -------------------------------------------------------------------- */
/*      Open target binary file.                                        */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->eAccess == GA_ReadOnly )
        poDS->fpImage = VSIFOpenL( osQubeFile, "r" );
    else
        poDS->fpImage = VSIFOpenL( osQubeFile, "r+" );

    if( poDS->fpImage == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "Failed to open %s with write permission.\n%s", 
                  osQubeFile.c_str(),
                  VSIStrerror( errno ) );
        delete poDS;
        return NULL;
    }

    poDS->eAccess = poOpenInfo->eAccess;

/* -------------------------------------------------------------------- */
/*      Compute the line offsets.                                        */
/* -------------------------------------------------------------------- */

    long int        nItemSize = GDALGetDataTypeSize(eDataType)/8;
    long int	    nLineOffset=0, nPixelOffset=0, nBandOffset=0;
    nPixelOffset = nItemSize;
    nLineOffset = nPixelOffset * nCols + atoi(poDS->GetKeyword("NBB")) ;
    nBandOffset = nLineOffset * nRows;

    nSkipBytes = atoi(poDS->GetKeyword("LBLSIZE"));

/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    int i;

    for( i = 0; i < nBands; i++ )
    {
        GDALRasterBand	*poBand;

        poBand = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i, 
                                   nPixelOffset, nLineOffset, eDataType,
#ifdef CPL_LSB                               
                                   chByteOrder == 'I' || chByteOrder == 'L',
#else
                                   chByteOrder == 'M',
#endif
                                   TRUE );

        poDS->SetBand( i+1, poBand );
        poBand->SetNoDataValue( dfNoData );
        if (bIsDTM==TRUE) {
            poBand->SetScale( (double) CPLAtof(poDS->GetKeyword( "DTM.DTM_SCALING_FACTOR") ) );
            poBand->SetOffset( (double) CPLAtof(poDS->GetKeyword( "DTM.DTM_OFFSET") ) );
            const char* pszMin = poDS->GetKeyword( "DTM.DTM_MINIMUM_DN", NULL );
            const char* pszMax = poDS->GetKeyword( "DTM.DTM_MAXIMUM_DN", NULL );
            if (pszMin != NULL && pszMax != NULL )
                poBand->SetStatistics(CPLAtofM(pszMin),CPLAtofM(pszMax),0,0);
            const char* pszNoData = poDS->GetKeyword( "DTM.DTM_MISSING_DN", NULL );
            if (pszNoData != NULL )
                poBand->SetNoDataValue( CPLAtofM(pszNoData) );
        } else if (EQUAL( poDS->GetKeyword( "BLTYPE"), "M94_HRSC" )) {
            float scale=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_SCALING_FACTOR","-1."));
            if (scale < 0.) {
                scale = CPLAtof(poDS->GetKeyword( "HRCAL.REFLECTANCE_SCALING_FACTOR","1."));
            }
            poBand->SetScale( scale );
            float offset=CPLAtof(poDS->GetKeyword("DLRTO8.REFLECTANCE_OFFSET","-1."));
            if (offset < 0.) {
                offset = CPLAtof(poDS->GetKeyword( "HRCAL.REFLECTANCE_OFFSET","0."));
            }
            poBand->SetOffset( offset );
        }
        const char* pszMin = poDS->GetKeyword( "STATISTICS.MINIMUM", NULL );
        const char* pszMax = poDS->GetKeyword( "STATISTICS.MAXIMUM", NULL );
        const char* pszMean = poDS->GetKeyword( "STATISTICS.MEAN", NULL );
        const char* pszStdDev = poDS->GetKeyword( "STATISTICS.STANDARD_DEVIATION", NULL );
        if (pszMin != NULL && pszMax != NULL && pszMean != NULL && pszStdDev != NULL )
                poBand->SetStatistics(CPLAtofM(pszMin),CPLAtofM(pszMax),CPLAtofM(pszMean),CPLAtofM(pszStdDev));
    }


/* -------------------------------------------------------------------- */
/*      Instrument-specific keywords as metadata.                       */
/* -------------------------------------------------------------------- */

/******************   HRSC    ******************************/
   
    if (EQUAL( poDS->GetKeyword( "BLTYPE"), "M94_HRSC" ) ) {
        poDS->SetMetadataItem( "SPACECRAFT_NAME", poDS->GetKeyword( "M94_INSTRUMENT.INSTRUMENT_HOST_NAME") );
        poDS->SetMetadataItem( "PRODUCT_TYPE", poDS->GetKeyword( "TYPE"));
    	
        if (EQUAL( poDS->GetKeyword( "M94_INSTRUMENT.DETECTOR_ID"), "MEX_HRSC_SRC" )) {
            static const char *apszKeywords[] =  {
                        "M94_ORBIT.IMAGE_TIME",
                        "FILE.EVENT_TYPE",
                        "FILE.PROCESSING_LEVEL_ID",
                        "M94_INSTRUMENT.DETECTOR_ID", 
                        "M94_CAMERAS.EXPOSURE_DURATION",
                        "HRCONVER.INSTRUMENT_TEMPERATURE", NULL
                    };
            for( i = 0; apszKeywords[i] != NULL; i++ ) {
                const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
                if( pszKeywordValue != NULL )
                    poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
            }
        } else {
            static const char *apszKeywords[] =  {
                "M94_ORBIT.START_TIME", "M94_ORBIT.STOP_TIME",
                "M94_INSTRUMENT.DETECTOR_ID",
                "M94_CAMERAS.MACROPIXEL_SIZE",
                "FILE.EVENT_TYPE",
                "M94_INSTRUMENT.MISSION_PHASE_NAME",
                "HRORTHO.SPICE_FILE_NAME",
                "HRCONVER.MISSING_FRAMES", "HRCONVER.OVERFLOW_FRAMES", "HRCONVER.ERROR_FRAMES",
                "HRFOOT.BEST_GROUND_SAMPLING_DISTANCE",
                "DLRTO8.RADIANCE_SCALING_FACTOR", "DLRTO8.RADIANCE_OFFSET",
                "DLRTO8.REFLECTANCE_SCALING_FACTOR", "DLRTO8.REFLECTANCE_OFFSET",
                "HRCAL.RADIANCE_SCALING_FACTOR", "HRCAL.RADIANCE_OFFSET",
                "HRCAL.REFLECTANCE_SCALING_FACTOR", "HRCAL.REFLECTANCE_OFFSET",
                "HRORTHO.DTM_NAME", "HRORTHO.EXTORI_FILE_NAME", "HRORTHO.GEOMETRIC_CALIB_FILE_NAME",
                NULL
            };
            for( i = 0; apszKeywords[i] != NULL; i++ ) {
                const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i], NULL );
                if( pszKeywordValue != NULL )
                    poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
            }
        }
    }
    if (bIsDTM==TRUE && EQUAL( poDS->GetKeyword( "MAP.TARGET_NAME"), "MARS" )) {
        poDS->SetMetadataItem( "SPACECRAFT_NAME", "MARS_EXPRESS" );
        poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM");
        static const char *apszKeywords[] = {
            "DTM.DTM_MISSING_DN", "DTM.DTM_OFFSET", "DTM.DTM_SCALING_FACTOR", "DTM.DTM_A_AXIS_RADIUS", 
            "DTM.DTM_B_AXIS_RADIUS", "DTM.DTM_C_AXIS_RADIUS", "DTM.DTM_DESC", "DTM.DTM_MINIMUM_DN",
            "DTM.DTM_MAXIMUM_DN", NULL };
        for( i = 0; apszKeywords[i] != NULL; i++ ) {
            const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
            if( pszKeywordValue != NULL )
                poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
        }
    }


/******************   DAWN   ******************************/
    else if (EQUAL( poDS->GetKeyword( "INSTRUMENT_ID"), "FC2" )) {
        poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" );
        static const char *apszKeywords[] =  {"ORBIT_NUMBER","FILTER_NUMBER",
        "FRONT_DOOR_STATUS",
        "FIRST_LINE",
        "FIRST_LINE_SAMPLE",
        "PRODUCER_INSTITUTION_NAME",
        "SOURCE_FILE_NAME",
        "PROCESSING_LEVEL_ID",
        "TARGET_NAME",
        "LIMB_IN_IMAGE",
        "POLE_IN_IMAGE",
        "REFLECTANCE_SCALING_FACTOR",
        "SPICE_FILE_NAME",
        "SPACECRAFT_CENTRIC_LATITUDE",
        "SPACECRAFT_EASTERN_LONGITUDE",
        "FOOTPRINT_POSITIVE_LONGITUDE",
            NULL };
        for( i = 0; apszKeywords[i] != NULL; i++ ) {
            const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
            if( pszKeywordValue != NULL )
                poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
        }
        
    }
    else if (bIsDTM==TRUE && EQUAL( poDS->GetKeyword( "TARGET_NAME"), "VESTA" )) {
        poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" );
        poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM");
        static const char *apszKeywords[] = {
            "DTM_MISSING_DN", "DTM_OFFSET", "DTM_SCALING_FACTOR", "DTM_A_AXIS_RADIUS", 
            "DTM_B_AXIS_RADIUS", "DTM_C_AXIS_RADIUS", "DTM_MINIMUM_DN",
            "DTM_MAXIMUM_DN", "MAP_PROJECTION_TYPE", "COORDINATE_SYSTEM_NAME",
            "POSITIVE_LONGITUDE_DIRECTION", "MAP_SCALE",
            "CENTER_LONGITUDE", "LINE_PROJECTION_OFFSET", "SAMPLE_PROJECTION_OFFSET",
            NULL };
        for( i = 0; apszKeywords[i] != NULL; i++ ) {
            const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
            if( pszKeywordValue != NULL )
                poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
        }
    }


/* -------------------------------------------------------------------- */
/*      END Instrument-specific keywords as metadata.                   */
/* -------------------------------------------------------------------- */

    if (EQUAL(poDS->GetKeyword( "EOL"), "1" ))
        poDS->SetMetadataItem( "END-OF-DATASET_LABEL", "PRESENT" );
    poDS->SetMetadataItem( "CONVERSION_DETAILS", "http://www.lpi.usra.edu/meetings/lpsc2014/pdf/1088.pdf" );
    poDS->SetMetadataItem( "PIXEL-SHIFT-BUG", "CORRECTED" );

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->TryLoadXML();

/* -------------------------------------------------------------------- */
/*      Check for overviews.                                            */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );

    return( poDS );
}
Exemple #26
0
OGRFeature *OGRDXFLayer::TranslateHATCH()

{
    char szLineBuf[257];
    int nCode;
    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );

    CPLString osHatchPattern;
    /* int nFillFlag = 0; */
    OGRGeometryCollection oGC;

    while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
    {
        switch( nCode )
        {
          case 70:
            /* nFillFlag = atoi(szLineBuf); */
            break;

          case 2:
            osHatchPattern = szLineBuf;
            poFeature->SetField( "Text", osHatchPattern.c_str() );
            break;

          case 91:
          {
              int nBoundaryPathCount = atoi(szLineBuf);
              int iBoundary;

              for( iBoundary = 0; iBoundary < nBoundaryPathCount; iBoundary++ )
              {
                  if (CollectBoundaryPath( &oGC ) != OGRERR_NONE)
                      break;
              }
          }
          break;

          default:
            TranslateGenericProperty( poFeature, nCode, szLineBuf );
            break;
        }
    }

    if( nCode == 0 )
        poDS->UnreadValue();

/* -------------------------------------------------------------------- */
/*      Try to turn the set of lines into something useful.             */
/* -------------------------------------------------------------------- */
    OGRErr eErr;

    OGRGeometry* poFinalGeom = (OGRGeometry *)
        OGRBuildPolygonFromEdges( (OGRGeometryH) &oGC,
                                  TRUE, TRUE, 0.0000001, &eErr );
    if( eErr != OGRERR_NONE )
    {
        delete poFinalGeom;
        OGRMultiLineString* poMLS = new OGRMultiLineString();
        for(int i=0;i<oGC.getNumGeometries();i++)
            poMLS->addGeometry(oGC.getGeometryRef(i));
        poFinalGeom = poMLS;
    }

    ApplyOCSTransformer( poFinalGeom );
    poFeature->SetGeometryDirectly( poFinalGeom );

/* -------------------------------------------------------------------- */
/*      Work out the color for this feature.  For now we just assume    */
/*      solid fill.  We cannot trivially translate the various sorts    */
/*      of hatching.                                                    */
/* -------------------------------------------------------------------- */
    CPLString osLayer = poFeature->GetFieldAsString("Layer");

    int nColor = 256;

    if( oStyleProperties.count("Color") > 0 )
        nColor = atoi(oStyleProperties["Color"]);

    // Use layer color? 
    if( nColor < 1 || nColor > 255 )
    {
        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
        if( pszValue != NULL )
            nColor = atoi(pszValue);
    }
        
/* -------------------------------------------------------------------- */
/*      Setup the style string.                                         */
/* -------------------------------------------------------------------- */
    if( nColor >= 1 && nColor <= 255 )
    {
        CPLString osStyle;
        const unsigned char *pabyDXFColors = ACGetColorTable();
        
        osStyle.Printf( "BRUSH(fc:#%02x%02x%02x)",
                        pabyDXFColors[nColor*3+0],
                        pabyDXFColors[nColor*3+1],
                        pabyDXFColors[nColor*3+2] );
        
        poFeature->SetStyleString( osStyle );
    }

    return poFeature;
}
Exemple #27
0
CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
    CPLErr ret = CE_None;

    char* pszXML = CPLSerializeXMLTree( config );
    if (pszXML)
    {
        m_osXML = pszXML;
        CPLFree(pszXML);
    }

    // Initialize the minidriver, which can set parameters for the dataset using member functions
    CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
    if (service_node != NULL) {
	const CPLString service_name = CPLGetXMLValue(service_node, "name", "");
	if (!service_name.empty()) {
	    GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
	    GDALWMSMiniDriverFactory *const mdf = mdm->Find(service_name);
	    if (mdf != NULL) {
		m_mini_driver = mdf->New();
		m_mini_driver->m_parent_dataset = this;
		if (m_mini_driver->Initialize(service_node) == CE_None) {
		    m_mini_driver_caps.m_capabilities_version = -1;
		    m_mini_driver->GetCapabilities(&m_mini_driver_caps);
		    if (m_mini_driver_caps.m_capabilities_version == -1) {
			CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
			ret = CE_Failure;
		    }
		} else {
		    delete m_mini_driver;
		    m_mini_driver = NULL;

		    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
		    ret = CE_Failure;
		}
	    } else {
		CPLError(CE_Failure, CPLE_AppDefined, 
                         "GDALWMS: No mini-driver registered for '%s'.", service_name.c_str());
		ret = CE_Failure;
	    }
	} else {
	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
	    ret = CE_Failure;
	}
    } else {
	CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
	ret = CE_Failure;
    }


    /*
    Parameters that could be set by minidriver already, based on server side information.
    If the size is set, minidriver has done this already
    A "server" side minidriver needs to set at least:
      - Blocksize (x and y)
      - Clamp flag (defaults to true)
      - DataWindow
      - Band Count
      - Data Type
    It should also initialize and register the bands and overviews.
    */

    if (m_data_window.m_sx<1) {

	if (ret == CE_None) {
	    m_block_size_x = atoi(CPLGetXMLValue(config, "BlockSizeX", CPLString().Printf("%d", m_default_block_size_x)));
	    m_block_size_y = atoi(CPLGetXMLValue(config, "BlockSizeY", CPLString().Printf("%d", m_default_block_size_y)));
	    if (m_block_size_x <= 0 || m_block_size_y <= 0) {
		CPLError( CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
		ret = CE_Failure;
	    }
	}

	if (ret == CE_None) {
	    m_clamp_requests = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
	    if (m_clamp_requests<0) {
		CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true/false expected.");
		ret = CE_Failure;
	    }
	}

	if (ret == CE_None) {
	    CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
	    if (data_window_node == NULL && m_bNeedsDataWindow) {
		CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
		ret = CE_Failure;
	    } else {
        CPLString osDefaultX0, osDefaultX1, osDefaultY0, osDefaultY1;
        CPLString osDefaultTileCountX, osDefaultTileCountY, osDefaultTileLevel;
        CPLString osDefaultOverviewCount;
        osDefaultX0.Printf("%.8f", m_default_data_window.m_x0);
        osDefaultX1.Printf("%.8f", m_default_data_window.m_x1);
        osDefaultY0.Printf("%.8f", m_default_data_window.m_y0);
        osDefaultY1.Printf("%.8f", m_default_data_window.m_y1);
        osDefaultTileCountX.Printf("%d", m_default_tile_count_x);
        osDefaultTileCountY.Printf("%d", m_default_tile_count_y);
        if (m_default_data_window.m_tlevel >= 0)
            osDefaultTileLevel.Printf("%d", m_default_data_window.m_tlevel);
        if (m_default_overview_count >= 0)
            osDefaultOverviewCount.Printf("%d", m_default_overview_count);
		const char *overview_count = CPLGetXMLValue(config, "OverviewCount", osDefaultOverviewCount);
		const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", osDefaultX0);
		const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", osDefaultY0);
		const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", osDefaultX1);
		const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", osDefaultY1);
		const char *sx = CPLGetXMLValue(data_window_node, "SizeX", "");
		const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
		const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
		const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
		const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", osDefaultTileLevel);
		const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", osDefaultTileCountX);
		const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", osDefaultTileCountY);
		const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");

		if (ret == CE_None) {
		    if ((ulx[0] != '\0') && (uly[0] != '\0') && (lrx[0] != '\0') && (lry[0] != '\0')) {
			m_data_window.m_x0 = atof(ulx);
			m_data_window.m_y0 = atof(uly);
			m_data_window.m_x1 = atof(lrx);
			m_data_window.m_y1 = atof(lry);
		    } else {
			CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
			ret = CE_Failure;
		    }
		}
		
        m_data_window.m_tlevel = atoi(tlevel);

		if (ret == CE_None) {
		    if ((sx[0] != '\0') && (sy[0] != '\0')) {
			m_data_window.m_sx = atoi(sx);
			m_data_window.m_sy = atoi(sy);
		    } else if ((tlevel[0] != '\0') && (str_tile_count_x[0] != '\0') && (str_tile_count_y[0] != '\0')) {
			int tile_count_x = atoi(str_tile_count_x);
			int tile_count_y = atoi(str_tile_count_y);
			m_data_window.m_sx = tile_count_x * m_block_size_x * (1 << m_data_window.m_tlevel);
			m_data_window.m_sy = tile_count_y * m_block_size_y * (1 << m_data_window.m_tlevel);
		    } else {
			CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: SizeX, SizeY.");
			ret = CE_Failure;
		    }
		}
		if (ret == CE_None) {
		    if ((tx[0] != '\0') && (ty[0] != '\0')) {
			m_data_window.m_tx = atoi(tx);
			m_data_window.m_ty = atoi(ty);
		    } else {
			CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: TileX, TileY.");
			ret = CE_Failure;
		    }
		}
		if (ret == CE_None) {
		    if (overview_count[0] != '\0') {
			m_overview_count = atoi(overview_count);
		    } else if (tlevel[0] != '\0') {
			m_overview_count = m_data_window.m_tlevel;
		    } else {
			const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
			double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0) 
			    - log(static_cast<double>(min_overview_size)) / log(2.0);
			m_overview_count = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
		    }
		}
		if (ret == CE_None) {
		    CPLString y_origin_str = y_origin;
		    if (y_origin_str == "top") {
			m_data_window.m_y_origin = GDALWMSDataWindow::TOP;
		    } else if (y_origin_str == "bottom") {
			m_data_window.m_y_origin = GDALWMSDataWindow::BOTTOM;
		    } else if (y_origin_str == "default") {
			m_data_window.m_y_origin = GDALWMSDataWindow::DEFAULT;
		    } else {
			CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow YOrigin must be set to " 
			    "one of 'default', 'top', or 'bottom', not '%s'.", y_origin_str.c_str());
			ret = CE_Failure;
		    }
		}
	    }
	}

	if (ret == CE_None) {
	    if (nBands<1)
		nBands=atoi(CPLGetXMLValue(config,"BandsCount","3"));
	    if (nBands<1) {
		CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad number of bands.");
		ret = CE_Failure;
	    }
	}

	if (ret == CE_None)
	{
	    const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
	    m_data_type = GDALGetDataTypeByName( data_type );
	    if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
	    {
		CPLError( CE_Failure, CPLE_AppDefined,
		    "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
		ret = CE_Failure;
	    }
	}

	// Initialize the bands and the overviews.  Assumes overviews are powers of two
	if (ret == CE_None) {
            nRasterXSize = m_data_window.m_sx;
            nRasterYSize = m_data_window.m_sy;
            
            if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
                !GDALCheckBandCount(nBands, TRUE))
            {
                return CE_Failure;
            }
            
            GDALColorInterp default_color_interp[4][4] = {
                { GCI_GrayIndex, GCI_Undefined, GCI_Undefined, GCI_Undefined },
                { GCI_GrayIndex, GCI_AlphaBand, GCI_Undefined, GCI_Undefined },
                { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_Undefined },
                { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand }
            };
            for (int i = 0; i < nBands; ++i) {
                GDALColorInterp color_interp = (nBands <= 4 && i <= 3 ? default_color_interp[nBands - 1][i] : GCI_Undefined);
                GDALWMSRasterBand *band = new GDALWMSRasterBand(this, i, 1.0);
                band->m_color_interp = color_interp;
                SetBand(i + 1, band);
                double scale = 0.5;
                for (int j = 0; j < m_overview_count; ++j) {
                    band->AddOverview(scale);
                    band->m_color_interp = color_interp;
                    scale *= 0.5;
                }
            }
	}
    }

    const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
    if (pszUserAgent[0] != '\0')
        m_osUserAgent = pszUserAgent;
    
    const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
    if (pszReferer[0] != '\0')
        m_osReferer = pszReferer;
    
    if (ret == CE_None) {
        const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
        if(pszHttpZeroBlockCodes == '\0') {
            m_http_zeroblock_codes.push_back(204);
        } else {
            char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes,",",CSLT_HONOURSTRINGS);
            int nCount = CSLCount(kv);
            for(int i=0; i<nCount; i++) {
                int code = atoi(kv[i]);
                if(code <= 0) {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes \"%s\", comma separated HTTP response codes expected.",
                            kv[i]);
                    ret = CE_Failure;
                    break;
                }
                m_http_zeroblock_codes.push_back(code);
            }
            CSLDestroy(kv);
        }
    }


    if (ret == CE_None) {
        const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
        if(pszZeroExceptions[0] != '\0') {
            m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
            if (m_zeroblock_on_serverexceptions == -1) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException \"%s\", true/false expected.",
                     pszZeroExceptions);
                ret = CE_Failure;
            }
        }
    }

    if (ret == CE_None) {
        const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
        if (max_conn[0] != '\0') {
            m_http_max_conn = atoi(max_conn);
        } else {
            m_http_max_conn = 2;
        }
    }
    if (ret == CE_None) {
        const char *timeout = CPLGetXMLValue(config, "Timeout", "");
        if (timeout[0] != '\0') {
            m_http_timeout = atoi(timeout);
        } else {
            m_http_timeout = 300;
        }
    }
    if (ret == CE_None) {
        const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
        if (offline_mode[0] != '\0') {
            const int offline_mode_bool = StrToBool(offline_mode);
            if (offline_mode_bool == -1) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
                ret = CE_Failure;
            } else {
                m_offline_mode = offline_mode_bool;
            }
        } else {
            m_offline_mode = 0;
        }
    }

    if (ret == CE_None) {
        const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
        if (advise_read[0] != '\0') {
            const int advise_read_bool = StrToBool(advise_read);
            if (advise_read_bool == -1) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
                ret = CE_Failure;
            } else {
                m_use_advise_read = advise_read_bool;
            }
        } else {
            m_use_advise_read = 0;
        }
    }

    if (ret == CE_None) {
        const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
        if (m_use_advise_read) {
            if (verify_advise_read[0] != '\0') {
                const int verify_advise_read_bool = StrToBool(verify_advise_read);
                if (verify_advise_read_bool == -1) {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
                    ret = CE_Failure;
                } else {
                    m_verify_advise_read = verify_advise_read_bool;
                }
            } else {
                m_verify_advise_read = 1;
            }
        }
    }

    // Let the local configuration override the minidriver supplied projection

    if (ret == CE_None) {
        const char *proj = CPLGetXMLValue(config, "Projection", "");
        if (proj[0] != '\0') {
            m_projection = ProjToWKT(proj);
            if (m_projection.size() == 0) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
                ret = CE_Failure;
            }
        }
    }

    if (ret == CE_None) {
        CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
        if (cache_node != NULL) {
            m_cache = new GDALWMSCache();
            if (m_cache->Initialize(cache_node) != CE_None) {
                delete m_cache;
                m_cache = NULL;
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
                ret = CE_Failure;
            }
        }
    }
    
    if (ret == CE_None) {
    	const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
    	if (v == -1) {
	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
	    ret = CE_Failure;
	} else {
	    m_unsafeSsl = v;
	}
    }

    if (ret == CE_None) {
        /* If we dont have projection already set ask mini-driver. */
        if (!m_projection.size()) {
            const char *proj = m_mini_driver->GetProjectionInWKT();
            if (proj != NULL) {
                m_projection = proj;
            }
        }
    }

    return ret;
}
Exemple #28
0
VSIVirtualHandle *
VSIMemFilesystemHandler::Open( const char *pszFilename,
                               const char *pszAccess,
                               bool bSetError )

{
    CPLMutexHolder oHolder( &hMutex );
    CPLString osFilename = pszFilename;
    NormalizePath( osFilename );
    if( osFilename.empty() )
        return nullptr;

    vsi_l_offset nMaxLength = GUINTBIG_MAX;
    const size_t iPos = osFilename.find("||maxlength=");
    if( iPos != std::string::npos )
    {
        nMaxLength = static_cast<vsi_l_offset>(CPLAtoGIntBig(
                    osFilename.substr(iPos + strlen("||maxlength=")).c_str()));
    }

/* -------------------------------------------------------------------- */
/*      Get the filename we are opening, create if needed.              */
/* -------------------------------------------------------------------- */
    VSIMemFile *poFile = nullptr;
    if( oFileList.find(osFilename) != oFileList.end() )
        poFile = oFileList[osFilename];

    // If no file and opening in read, error out.
    if( strstr(pszAccess, "w") == nullptr
        && strstr(pszAccess, "a") == nullptr
        && poFile == nullptr )
    {
        if( bSetError )
        {
            VSIError(VSIE_FileError, "No such file or directory");
        }
        errno = ENOENT;
        return nullptr;
    }

    // Create.
    if( poFile == nullptr )
    {
        poFile = new VSIMemFile;
        poFile->osFilename = osFilename;
        oFileList[poFile->osFilename] = poFile;
        CPLAtomicInc(&(poFile->nRefCount));  // For file list.
        poFile->nMaxLength = nMaxLength;
    }
    // Overwrite
    else if( strstr(pszAccess, "w") )
    {
        poFile->SetLength(0);
        poFile->nMaxLength = nMaxLength;
    }

    if( poFile->bIsDirectory )
    {
        errno = EISDIR;
        return nullptr;
    }

/* -------------------------------------------------------------------- */
/*      Setup the file handle on this file.                             */
/* -------------------------------------------------------------------- */
    VSIMemHandle *poHandle = new VSIMemHandle;

    poHandle->poFile = poFile;
    poHandle->m_nOffset = 0;
    poHandle->bEOF = false;
    poHandle->bUpdate =
        strstr(pszAccess, "w") ||
        strstr(pszAccess, "+") ||
        strstr(pszAccess, "a");

    CPLAtomicInc(&(poFile->nRefCount));

    if( strstr(pszAccess, "a") )
        poHandle->m_nOffset = poFile->nLength;

    return poHandle;
}
int VSIArchiveFilesystemHandler::Stat( const char *pszFilename,
                                       VSIStatBufL *pStatBuf,
                                       CPL_UNUSED int nFlags )
{
    int ret = -1;
    CPLString osFileInArchive;

    memset(pStatBuf, 0, sizeof(VSIStatBufL));

    char* archiveFilename = SplitFilename(pszFilename, osFileInArchive, TRUE);
    if (archiveFilename == NULL)
        return -1;

    if (strlen(osFileInArchive) != 0)
    {
        if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Looking for %s %s\n",
                                    archiveFilename, osFileInArchive.c_str());

        const VSIArchiveEntry* archiveEntry = NULL;
        if (FindFileInArchive(archiveFilename, osFileInArchive, &archiveEntry))
        {
            /* Patching st_size with uncompressed file size */
            pStatBuf->st_size = archiveEntry->uncompressed_size;
            pStatBuf->st_mtime = (time_t)archiveEntry->nModifiedTime;
            if (archiveEntry->bIsDir)
                pStatBuf->st_mode = S_IFDIR;
            else
                pStatBuf->st_mode = S_IFREG;
            ret = 0;
        }
    }
    else
    {
        VSIArchiveReader* poReader = CreateReader(archiveFilename);
        CPLFree(archiveFilename);
        archiveFilename = NULL;

        if (poReader != NULL && poReader->GotoFirstFile())
        {
            /* Skip optionnal leading subdir */
            CPLString osFileName = poReader->GetFileName();
            const char* fileName = osFileName.c_str();
            if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
            {
                if (poReader->GotoNextFile() == FALSE)
                {
                    delete(poReader);
                    return -1;
                }
            }

            if (poReader->GotoNextFile())
            {
                /* Several files in archive --> treat as dir */
                pStatBuf->st_size = 0;
                pStatBuf->st_mode = S_IFDIR;
            }
            else
            {
                /* Patching st_size with uncompressed file size */
                pStatBuf->st_size = poReader->GetFileSize();
                pStatBuf->st_mtime = (time_t)poReader->GetModifiedTime();
                pStatBuf->st_mode = S_IFREG;
            }

            ret = 0;
        }

        delete(poReader);
    }

    CPLFree(archiveFilename);
    return ret;
}
Exemple #30
0
OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
{
    int iLine;
    const char *pszDatum, *pszProj = NULL, *pszProjParms = NULL;

    Clear();

    int nLines = CSLCount((char**)papszLines);
    if( nLines < 5 )
        return OGRERR_NOT_ENOUGH_DATA;

    pszDatum = papszLines[4];

    for ( iLine = 5; iLine < nLines; iLine++ )
    {
        if ( STARTS_WITH_CI(papszLines[iLine], "Map Projection") )
        {
            pszProj = papszLines[iLine];
        }
        else if ( STARTS_WITH_CI(papszLines[iLine], "Projection Setup") )
        {
            pszProjParms = papszLines[iLine];
        }
    }

    if ( ! ( pszDatum && pszProj && pszProjParms ) )
        return OGRERR_NOT_ENOUGH_DATA;

/* -------------------------------------------------------------------- */
/*      Operate on the basis of the projection name.                    */
/* -------------------------------------------------------------------- */
    char    **papszProj = CSLTokenizeStringComplex( pszProj, ",", TRUE, TRUE );
    char    **papszProjParms = CSLTokenizeStringComplex( pszProjParms, ",",
                                                         TRUE, TRUE );
    char    **papszDatum = NULL;

    if (CSLCount(papszProj) < 2)
    {
        goto not_enough_data;
    }

    if ( STARTS_WITH_CI(papszProj[1], "Latitude/Longitude") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Mercator") )
    {
        if (CSLCount(papszProjParms) < 6) goto not_enough_data;
        double dfScale = CPLAtof(papszProjParms[3]);
        if (papszProjParms[3][0] == 0) dfScale = 1; /* if unset, default to scale = 1 */
        SetMercator( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
                     dfScale,
                     CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Transverse Mercator") )
    {
        if (CSLCount(papszProjParms) < 6) goto not_enough_data;
        SetTM( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
               CPLAtof(papszProjParms[3]),
               CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Lambert Conformal Conic") )
    {
        if (CSLCount(papszProjParms) < 8) goto not_enough_data;
        SetLCC( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
                CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
                CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Sinusoidal") )
    {
        if (CSLCount(papszProjParms) < 6) goto not_enough_data;
        SetSinusoidal( CPLAtof(papszProjParms[2]),
                       CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Albers Equal Area") )
    {
        if (CSLCount(papszProjParms) < 8) goto not_enough_data;
        SetACEA( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
                 CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
                 CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(UTM) Universal Transverse Mercator") && nLines > 5 )
    {
        /* Look for the UTM zone in the calibration point data */
        for ( iLine = 5; iLine < nLines; iLine++ )
        {
            if ( STARTS_WITH_CI(papszLines[iLine], "Point") )
            {
                char    **papszTok = NULL;
                papszTok = CSLTokenizeString2( papszLines[iLine], ",",
                                               CSLT_ALLOWEMPTYTOKENS
                                               | CSLT_STRIPLEADSPACES
                                               | CSLT_STRIPENDSPACES );
                if ( CSLCount(papszTok) < 17
                     || EQUAL(papszTok[2], "")
                     || EQUAL(papszTok[13], "")
                     || EQUAL(papszTok[14], "")
                     || EQUAL(papszTok[15], "")
                     || EQUAL(papszTok[16], "") )
                {
                    CSLDestroy(papszTok);
                    continue;
                }
                SetUTM( atoi(papszTok[13]), EQUAL(papszTok[16], "N") );
                CSLDestroy(papszTok);
                break;
            }
        }
        if ( iLine == nLines )    /* Try to guess the UTM zone */
        {
            float fMinLongitude = 1000.0f;
            float fMaxLongitude = -1000.0f;;
            float fMinLatitude = 1000.0f;
            float fMaxLatitude = -1000.0f;
            bool bFoundMMPLL = false;
            for ( iLine = 5; iLine < nLines; iLine++ )
            {
                if ( STARTS_WITH_CI(papszLines[iLine], "MMPLL") )
                {
                    char    **papszTok = NULL;
                    papszTok = CSLTokenizeString2( papszLines[iLine], ",",
                                                   CSLT_ALLOWEMPTYTOKENS
                                                   | CSLT_STRIPLEADSPACES
                                                   | CSLT_STRIPENDSPACES );
                    if ( CSLCount(papszTok) < 4 )
                    {
                        CSLDestroy(papszTok);
                        continue;
                    }
                    float fLongitude = static_cast<float>(CPLAtofM(papszTok[2]));
                    float fLatitude = static_cast<float>(CPLAtofM(papszTok[3]));
                    CSLDestroy(papszTok);

                    bFoundMMPLL = true;

                    if ( fMinLongitude > fLongitude )
                        fMinLongitude = fLongitude;
                    if ( fMaxLongitude < fLongitude )
                        fMaxLongitude = fLongitude;
                    if ( fMinLatitude > fLatitude )
                        fMinLatitude = fLatitude;
                    if ( fMaxLatitude < fLatitude )
                        fMaxLatitude = fLatitude;
                }
            }
            float fMedianLatitude = ( fMinLatitude + fMaxLatitude ) / 2;
            float fMedianLongitude = ( fMinLongitude + fMaxLongitude ) / 2;
            if ( bFoundMMPLL && fMaxLatitude <= 90 )
            {
                int nUtmZone;
                if ( fMedianLatitude >= 56 && fMedianLatitude <= 64 &&
                     fMedianLongitude >= 3 && fMedianLongitude <= 12 )
                    nUtmZone = 32;                                             /* Norway exception */
                else if ( fMedianLatitude >= 72 && fMedianLatitude <= 84 &&
                         fMedianLongitude >= 0 && fMedianLongitude <= 42 )
                    nUtmZone = (int) ((fMedianLongitude + 3 ) / 12) * 2 + 31;  /* Svalbard exception */
                else
                    nUtmZone = (int) ((fMedianLongitude + 180 ) / 6) + 1;
                SetUTM( nUtmZone, fMedianLatitude >= 0 );
            }
            else
                CPLDebug( "OSR_Ozi", "UTM Zone not found");
        }
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(I) France Zone I") )
    {
        SetLCC1SP( 49.5, 2.337229167, 0.99987734, 600000, 1200000 );
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(II) France Zone II") )
    {
        SetLCC1SP( 46.8, 2.337229167, 0.99987742, 600000, 2200000 );
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(III) France Zone III") )
    {
        SetLCC1SP( 44.1, 2.337229167, 0.99987750, 600000, 3200000 );
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(IV) France Zone IV") )
    {
        SetLCC1SP( 42.165, 2.337229167, 0.99994471, 234.358, 4185861.369 );
    }

/*
 *  Note : The following projections have not been implemented yet
 *
 */

/*
    else if ( STARTS_WITH_CI(papszProj[1], "(BNG) British National Grid") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(IG) Irish Grid") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(NZG) New Zealand Grid") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(NZTM2) New Zealand TM 2000") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(SG) Swedish Grid") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(SUI) Swiss Grid") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(A)Lambert Azimuthual Equal Area") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(EQC) Equidistant Conic") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Polyconic (American)") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Van Der Grinten") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Vertical Near-Sided Perspective") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(WIV) Wagner IV") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Bonne") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(MT0) Montana State Plane Zone 2500") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "ITA1) Italy Grid Zone 1") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "ITA2) Italy Grid Zone 2") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(VICMAP-TM) Victoria Aust.(pseudo AMG)") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "VICGRID) Victoria Australia") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "(VG94) VICGRID94 Victoria Australia") )
    {
    }

    else if ( STARTS_WITH_CI(papszProj[1], "Gnomonic") )
    {
    }
*/

    else
    {
        CPLDebug( "OSR_Ozi", "Unsupported projection: \"%s\"", papszProj[1] );
        SetLocalCS( CPLString().Printf("\"Ozi\" projection \"%s\"",
                                       papszProj[1]) );
    }

/* -------------------------------------------------------------------- */
/*      Try to translate the datum/spheroid.                            */
/* -------------------------------------------------------------------- */
    papszDatum = CSLTokenizeString2( pszDatum, ",",
                                               CSLT_ALLOWEMPTYTOKENS
                                               | CSLT_STRIPLEADSPACES
                                               | CSLT_STRIPENDSPACES );
    if ( papszDatum == NULL)
        goto not_enough_data;

    if ( !IsLocal() )
    {

/* -------------------------------------------------------------------- */
/*      Verify that we can find the CSV file containing the datums      */
/* -------------------------------------------------------------------- */
        if( CSVScanFileByName( CSVFilename( "ozi_datum.csv" ),
                            "EPSG_DATUM_CODE",
                            "4326", CC_Integer ) == NULL )
        {
            CPLError( CE_Failure, CPLE_OpenFailed,
                    "Unable to open OZI support file %s.\n"
                    "Try setting the GDAL_DATA environment variable to point\n"
                    "to the directory containing OZI csv files.",
                    CSVFilename( "ozi_datum.csv" ) );
            goto other_error;
        }

/* -------------------------------------------------------------------- */
/*      Search for matching datum                                       */
/* -------------------------------------------------------------------- */
        const char *pszOziDatum = CSVFilename( "ozi_datum.csv" );
        CPLString osDName = CSVGetField( pszOziDatum, "NAME", papszDatum[0],
                                    CC_ApproxString, "NAME" );
        if( strlen(osDName) == 0 )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                    "Failed to find datum %s in ozi_datum.csv.",
                    papszDatum[0] );
            goto other_error;
        }

        int nDatumCode = atoi( CSVGetField( pszOziDatum, "NAME", papszDatum[0],
                                            CC_ApproxString, "EPSG_DATUM_CODE" ) );

        if ( nDatumCode > 0 ) // There is a matching EPSG code
        {
            OGRSpatialReference oGCS;
            oGCS.importFromEPSG( nDatumCode );
            CopyGeogCSFrom( &oGCS );
        }
        else // We use the parameters from the CSV files
        {
            CPLString osEllipseCode = CSVGetField( pszOziDatum, "NAME", papszDatum[0],
                                                CC_ApproxString, "ELLIPSOID_CODE" );
            double dfDeltaX = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
                                                CC_ApproxString, "DELTAX" ) );
            double dfDeltaY = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
                                                CC_ApproxString, "DELTAY" ) );
            double dfDeltaZ = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
                                                CC_ApproxString, "DELTAZ" ) );


    /* -------------------------------------------------------------------- */
    /*      Verify that we can find the CSV file containing the ellipsoids  */
    /* -------------------------------------------------------------------- */
            if( CSVScanFileByName( CSVFilename( "ozi_ellips.csv" ),
                                "ELLIPSOID_CODE",
                                "20", CC_Integer ) == NULL )
            {
                CPLError( CE_Failure, CPLE_OpenFailed,
                    "Unable to open OZI support file %s.\n"
                    "Try setting the GDAL_DATA environment variable to point\n"
                    "to the directory containing OZI csv files.",
                    CSVFilename( "ozi_ellips.csv" ) );
                goto other_error;
            }

    /* -------------------------------------------------------------------- */
    /*      Lookup the ellipse code.                                        */
    /* -------------------------------------------------------------------- */
            const char *pszOziEllipse = CSVFilename( "ozi_ellips.csv" );

            CPLString osEName = CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
                                        CC_ApproxString, "NAME" );
            if( strlen(osEName) == 0 )
            {
                CPLError( CE_Failure, CPLE_AppDefined,
                        "Failed to find ellipsoid %s in ozi_ellips.csv.",
                        osEllipseCode.c_str() );
                goto other_error;
            }

            double dfA = CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
                                        CC_ApproxString, "A" ));
            double dfInvF = CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
                                            CC_ApproxString, "INVF" ));

    /* -------------------------------------------------------------------- */
    /*      Create geographic coordinate system.                            */
    /* -------------------------------------------------------------------- */

            SetGeogCS( osDName, osDName, osEName, dfA, dfInvF );
            SetTOWGS84( dfDeltaX, dfDeltaY, dfDeltaZ );

        }
    }

/* -------------------------------------------------------------------- */
/*      Grid units translation                                          */
/* -------------------------------------------------------------------- */
    if( IsLocal() || IsProjected() )
        SetLinearUnits( SRS_UL_METER, 1.0 );

    FixupOrdering();

    CSLDestroy(papszProj);
    CSLDestroy(papszProjParms);
    CSLDestroy(papszDatum);

    return OGRERR_NONE;

not_enough_data:

    CSLDestroy(papszProj);
    CSLDestroy(papszProjParms);
    CSLDestroy(papszDatum);

    return OGRERR_NOT_ENOUGH_DATA;

other_error:

    CSLDestroy(papszProj);
    CSLDestroy(papszProjParms);
    CSLDestroy(papszDatum);

    return OGRERR_FAILURE;
}