osgEarth 2.1.1
Public Member Functions | Private Attributes

WorldWindSource Class Reference

Inheritance diagram for WorldWindSource:
Collaboration diagram for WorldWindSource:

List of all members.

Public Member Functions

 WorldWindSource (const TileSourceOptions &options)
void initialize (const std::string &referenceURI, const Profile *overrideProfile)
osg::HeightField * createHeightFieldFromBil (char *buf, int buflength)
osg::Image * createImage (const TileKey &key, ProgressCallback *progress)
osg::HeightField * createHeightField (const TileKey &key, ProgressCallback *progress)
std::string createCachePath (const TileKey &key) const
std::string createCacheName (const TileKey &key) const
std::string createURI (const TileKey &key) const
virtual int getPixelsPerTile () const
virtual std::string getExtension () const

Private Attributes

WorldWindOptions _options

Detailed Description

Definition at line 54 of file ReaderWriterWorldWind.cpp.


Constructor & Destructor Documentation

WorldWindSource::WorldWindSource ( const TileSourceOptions options) [inline]

Definition at line 57 of file ReaderWriterWorldWind.cpp.

                                                        : TileSource( options )
    {
        _options = options;
    }

Member Function Documentation

std::string WorldWindSource::createCacheName ( const TileKey key) const [inline]

Definition at line 266 of file ReaderWriterWorldWind.cpp.

    {
        unsigned int x, y;
        key.getTileXY(x, y);

        unsigned int lod = key.getLevelOfDetail();

        // flip the y based on level
        int flippedy = ((9 * powf((int)2,(int)lod)) - 1) - y;
        //printf("Key %i, %i, %i\n", lod,x,flippedy);

        std::stringstream buf;
        buf << "" << std::setw(4) << std::setfill('0') << x
            << "_" << std::setw(4) << std::setfill('0') << flippedy;
        std::string bufStr;
        bufStr = buf.str();
        return bufStr;
    }

Here is the call graph for this function:

std::string WorldWindSource::createCachePath ( const TileKey key) const [inline]

Definition at line 251 of file ReaderWriterWorldWind.cpp.

    {
        unsigned int x, y;
        key.getTileXY(x, y);

        unsigned int lod = key.getLevelOfDetail();

        std::stringstream buf;
        buf << "" << lod
            << "/" << std::setw(4) << std::setfill('0') << x;
        std::string bufStr;
        bufStr = buf.str();
        return bufStr;
    }

Here is the call graph for this function:

osg::HeightField* WorldWindSource::createHeightField ( const TileKey key,
ProgressCallback progress 
) [inline, virtual]

Creates a heightfield for the given TileKey The returned object is new and is the responsibility of the caller.

Reimplemented from osgEarth::TileSource.

Definition at line 104 of file ReaderWriterWorldWind.cpp.

    {
        if ( *_options.maxLOD() <= key.getLevelOfDetail()) return NULL;
        if ( !_options.elevationCachePath().isSet() ) return NULL;

        osg::HeightField *hf = NULL;
        std::string cachefilepath = *_options.elevationCachePath() + "/" + createCachePath(key);
        std::string cachefilename = createCacheName(key) + ".bil";
        std::string fullcachefilename = cachefilepath + "/" + cachefilename;
        OE_DEBUG << LC << "Cached name " << fullcachefilename << std::endl;
        if (osgDB::fileExists(fullcachefilename))
        {
            // read file
            std::ifstream fin;
            fin.open(fullcachefilename.c_str(), std::ios::in | std::ios::binary);
            if (!fin)
            {
                OE_WARN << LC << "Coud not open elevation cache " << fullcachefilename << ", maybe a permissions problem" << std::endl;
                _options.elevationCachePath().unset();
                return NULL;
            }
            int fullsize = 150*150*2;
            char *buf = new char[fullsize];
            OE_DEBUG << LC << "Loading from cache " << fullcachefilename << std::endl;
            if ( !fin.read(buf, fullsize))
            {
                OE_WARN << LC << "Coud not read from elevation cache " << fullcachefilename << ", file may be corrupt" << std::endl;
                delete[] buf;
                fin.close();
                _options.elevationCachePath().unset();
                return NULL;
            }
            hf = createHeightFieldFromBil((char*)buf,fullsize);
            delete[] buf;
            fin.close();
        }
        else // cached BIL file doesn't exist, try to download and cache it.
        {
            // download file
            HTTPResponse out_response;
            std::string URI = createURI(key);

            OE_DEBUG << "Requesting " << URI << std::endl;
            out_response = HTTPClient::get( URI, 0L, progress );

            if ( !out_response.isOK() )
            {
                OE_NOTICE << "No Response received for " << URI << std::endl;
                return NULL;
            }

            // store downloaded part as a zip file
            // Useful to store a local copy as the same file is requested many times
            unsigned int part_num = out_response.getNumParts() > 1? 1 : 0;
            std::string zipfilename;
            out_response.getPartHeader(part_num, zipfilename);
            std::istream& input_stream = out_response.getPartStream( part_num );

            if ( !osgDB::fileExists(cachefilepath) )
            {
                osgDB::makeDirectory(cachefilepath);
            }
            std::ofstream fout;
            std::string tempname = fullcachefilename + ".zip";
            fout.open(tempname.c_str(), std::ios::out | std::ios::binary);

            if ( !fout )
            {
                OE_WARN << LC << "Could not write zip file to " << tempname << std::endl;
                _options.elevationCachePath().unset();
                return NULL;
            }
            input_stream.seekg (0, std::ios::end);
            int length = input_stream.tellg();
            input_stream.seekg (0, std::ios::beg);

            char *buffer = new char[length];
            input_stream.read(buffer, length);
            fout.write(buffer, length);
            delete[] buffer;
            fout.close();


            //Unzip the file
            int err;

            //Open the zip file
            struct zip* pZip = zip_open(tempname.c_str(), ZIP_CHECKCONS, &err);
            if (pZip)
            {
                //List the files
                int numFiles = zip_get_num_files(pZip);
                //OE_DEBUG <<  tempname << " has " << numFiles << " files " << std::endl;
                /*for (int i = 0; i < numFiles; ++i)
                {
                    OE_NOTICE << i << ": " << zip_get_name(pZip, i, 0) << std::endl;
                }*/

                //Find the index within the zip file for the given zip entry
                int zipIndex = 0;

                //Open the first file for reading
                zip_file* pZipFile = zip_fopen_index(pZip, 0, 0);

                if (pZipFile) 
                {
                    //Read the data from the entry into a std::string
                    int dataSize = 0;
                    std::string data;
                    do{
                        char* buf = new char[1024];
                        dataSize = zip_fread(pZipFile, buf, 1024);
                        if (dataSize == 0)
                        {
                            delete [](buf);
                            buf = NULL;
                        }
                        if (buf)
                        {
                            data.append((char*)buf, dataSize);
                        }
                    }while (dataSize > 0);

                    //Close the zip entry and the actual zip file itself
                    zip_fclose(pZipFile);
                    zip_close(pZip);

                    //Write the BIL file to the cache
                    fout.open(fullcachefilename.c_str(), std::ios::out | std::ios::binary);
                    if ( !fout )
                    {
                        std::cout << "Cannot write bil file"<< std::endl;
                        return NULL;
                    }

                    fout.write((char*)data.c_str(), data.size());
                    fout.close(); 

                    hf = createHeightFieldFromBil((char*)data.c_str(),data.size());                    
                    // delete zip file as it has now been processed
                    remove(tempname.c_str());
                }               
            }
        }
        return hf;
    }

Here is the call graph for this function:

osg::HeightField* WorldWindSource::createHeightFieldFromBil ( char *  buf,
int  buflength 
) [inline]

Definition at line 77 of file ReaderWriterWorldWind.cpp.

    {
        osg::HeightField* hf = new osg::HeightField;
        //osg::notify(osg::NOTICE) << "Read heightfield image" << std::endl;
        hf->allocate(150, 150);

        for( unsigned int row=0; row < 150; row++ )
        {
            for( unsigned int col=0; col < 150; col++ )
            {
                short* ptr = (short*)buf;
                short val = ptr[col + ((150-row -1)*150)];

                hf->setHeight( col, row, (float)val * 0.3048 );
            }
        }
        return hf;
    }
osg::Image* WorldWindSource::createImage ( const TileKey key,
ProgressCallback progress 
) [inline, virtual]

Creates an image for the given TileKey. The returned object is new and is the responsibility of the caller.

Implements osgEarth::TileSource.

Definition at line 97 of file ReaderWriterWorldWind.cpp.

    {
        // NYI - eventually, consolidate the "tileservice" plugin into this one //GW
        return NULL;
    }
std::string WorldWindSource::createURI ( const TileKey key) const [inline]

Definition at line 285 of file ReaderWriterWorldWind.cpp.

    {
        unsigned int x, y;
        key.getTileXY(x, y);

        unsigned int lod = key.getLevelOfDetail();

        // flip the y based on level
        int flippedy = ((9 * powf((int)2,(int)lod)) - 1) - y;

        std::stringstream buf;
        buf << *_options.elevationURL() // "http://worldwind25.arc.nasa.gov/wwelevation/wwelevation.aspx?T=srtm30pluszip"
            << "&L=" << lod
            << "&X=" << x
            << "&Y=" << flippedy;
        std::string bufStr;
        bufStr = buf.str();
        return bufStr;
    }

Here is the call graph for this function:

virtual std::string WorldWindSource::getExtension ( ) const [inline, virtual]

Gets the preferred extension for this TileSource

Reimplemented from osgEarth::TileSource.

Definition at line 310 of file ReaderWriterWorldWind.cpp.

    {
        return "bil";
    }
virtual int WorldWindSource::getPixelsPerTile ( ) const [inline, virtual]

Gets the number of pixels per tile for this TileSource.

Reimplemented from osgEarth::TileSource.

Definition at line 305 of file ReaderWriterWorldWind.cpp.

    {
        return 150;
    }
void WorldWindSource::initialize ( const std::string &  referenceURI,
const Profile overrideProfile 
) [inline, virtual]

Initialize the TileSource. The profile should be computed and set here using setProfile()

Implements osgEarth::TileSource.

Definition at line 63 of file ReaderWriterWorldWind.cpp.

    {
        setProfile( Profile::create(
            "epsg:4326",
            -180.0, -90.0, 180.0, 90.0,
            "",
            18, 9 ) );

        if ( !_options.elevationCachePath().isSet() )
        {
            OE_WARN << LC << "Elevation cache path is not set, but is required. No data will be available" << std::endl;
        }
    }

Here is the call graph for this function:


Member Data Documentation

Reimplemented from osgEarth::TileSource.

Definition at line 316 of file ReaderWriterWorldWind.cpp.


The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines