osgEarth 2.1.1
Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes

osgEarth::ElevationLayer Class Reference

Inheritance diagram for osgEarth::ElevationLayer:
Collaboration diagram for osgEarth::ElevationLayer:

List of all members.

Public Member Functions

 ElevationLayer (const ElevationLayerOptions &options)
 ElevationLayer (const std::string &name, const TileSourceOptions &driverOptions)
 ElevationLayer (const ElevationLayerOptions &options, TileSource *tileSource)
const ElevationLayerOptionsgetElevationLayerOptions () const
virtual const TerrainLayerOptionsgetTerrainLayerOptions () const
void addCallback (ElevationLayerCallback *cb)
void removeCallback (ElevationLayerCallback *cb)
osg::HeightField * createHeightField (const TileKey &key, ProgressCallback *progress=0L)

Protected Member Functions

virtual GeoHeightField createGeoHeightField (const TileKey &key, ProgressCallback *progress)
virtual std::string suggestCacheFormat () const
virtual void initTileSource ()

Private Member Functions

virtual void fireCallback (TerrainLayerCallbackMethodPtr method)
virtual void fireCallback (ElevationLayerCallbackMethodPtr method)
void init ()

Private Attributes

ElevationLayerOptions _runtimeOptions
ElevationLayerCallbackList _callbacks
osg::ref_ptr
< TileSource::HeightFieldOperation
_preCacheOp

Detailed Description

A map terrain layer containing elevation grid heightfields.

Definition at line 73 of file ElevationLayer.


Constructor & Destructor Documentation

ElevationLayer::ElevationLayer ( const ElevationLayerOptions options)

Constructs a new elevation layer with the specified options. It expects the layer options to contain a reference to the neccesary driver options.

Definition at line 99 of file ElevationLayer.cpp.

                                                                     :
TerrainLayer   ( &_runtimeOptions ),
_runtimeOptions( options )
{
    init();
}

Here is the call graph for this function:

ElevationLayer::ElevationLayer ( const std::string &  name,
const TileSourceOptions driverOptions 
)

Constructs a new elevation layer with the specific name and driver options. The layer will load its driver by using the tilesource options.

Definition at line 106 of file ElevationLayer.cpp.

                                                                                              :
TerrainLayer   ( &_runtimeOptions ),
_runtimeOptions( ElevationLayerOptions(name, driverOptions) )
{
    init();
}

Here is the call graph for this function:

ElevationLayer::ElevationLayer ( const ElevationLayerOptions options,
TileSource tileSource 
)

Constructs a new elevation layer with the specified layer options and with a custom TileSource instance created by the user.

Definition at line 113 of file ElevationLayer.cpp.

                                                                                             :
TerrainLayer   ( &_runtimeOptions, tileSource ),
_runtimeOptions( options )
{
    init();
}

Here is the call graph for this function:


Member Function Documentation

void ElevationLayer::addCallback ( ElevationLayerCallback cb)

Adds a property notification callback to this layer

Definition at line 139 of file ElevationLayer.cpp.

{
    _callbacks.push_back( cb );
}
GeoHeightField ElevationLayer::createGeoHeightField ( const TileKey key,
ProgressCallback progress 
) [protected, virtual]

Definition at line 183 of file ElevationLayer.cpp.

{
    osg::HeightField* hf = 0L;
    //osg::ref_ptr<osg::HeightField> hf;

    TileSource* source = getTileSource();

    //Only try to get the tile if it isn't blacklisted
    if (!source->getBlacklist()->contains( key.getTileId() ))
    {
        //Only try to get data if the source actually has data
        if (source->hasData( key ) )
        {
            hf = source->createHeightField( key, _preCacheOp.get(), progress );

            //Blacklist the tile if we can't get it and it wasn't cancelled
            if ( !hf && (!progress || !progress->isCanceled()))
            {
                source->getBlacklist()->add(key.getTileId());
            }
        }
        else
        {
            OE_DEBUG << LC << "Source for layer \"" << getName() << "\" has no data at " << key.str() << std::endl;
        }
    }
    else
    {
        OE_DEBUG << LC << "Tile " << key.str() << " is blacklisted " << std::endl;
    }

    return hf ?
        GeoHeightField( hf, key.getExtent(), getProfile()->getVerticalSRS() ) :
        GeoHeightField::INVALID;
}

Here is the call graph for this function:

Here is the caller graph for this function:

osg::HeightField * ElevationLayer::createHeightField ( const TileKey key,
ProgressCallback progress = 0L 
)

Creates a GeoHeightField for this layer that corresponds to the extents and LOD in the specified TileKey. The returned HeightField will always match the geospatial extents of that TileKey.

Definition at line 220 of file ElevationLayer.cpp.

{
    osg::HeightField* result = 0L;
    //osg::ref_ptr<osg::HeightField> result;

    const Profile* layerProfile = getProfile();
    const Profile* mapProfile = key.getProfile();

        if ( !layerProfile )
        {
                OE_WARN << LC << "Could not get a valid profile for Layer \"" << getName() << "\"" << std::endl;
        return 0L;
        }

        if ( !isCacheOnly() && !getTileSource() )
        {
                OE_WARN << LC << "Error: ElevationLayer does not have a valid TileSource, cannot create heightfield " << std::endl;
                return 0L;
        }

    //Write the layer properties if they haven't been written yet.  Heightfields are always stored in the map profile.
    if (!_cacheProfile.valid() && _cache.valid() && _runtimeOptions.cacheEnabled() == true && _tileSource.valid())
    {
        _cacheProfile = mapProfile;
        if ( _tileSource->isOK() )
        {
            _cache->storeProperties( _cacheSpec, _cacheProfile.get(),  _tileSource->getPixelsPerTile() );
        }
    }

        //See if we can get it from the cache.
        if (_cache.valid() && _runtimeOptions.cacheEnabled() == true )
        {
        osg::ref_ptr<const osg::HeightField> cachedHF;
                if ( _cache->getHeightField( key, _cacheSpec, cachedHF ) )
                {
                        OE_DEBUG << LC << "ElevationLayer::createHeightField got tile " << key.str() << " from layer \"" << getName() << "\" from cache " << std::endl;

            // make a copy:
            result = new osg::HeightField( *cachedHF.get() );
                }
        }

    //in cache-only mode, if the cache fetch failed, bail out.
    if ( result == 0L && isCacheOnly() )
    {
        return 0L;
    }

        if ( result == 0L && getTileSource() && getTileSource()->isOK() )
    {
                //If the profiles are equivalent, get the HF from the TileSource.
                if (key.getProfile()->isEquivalentTo( getProfile() ))
                {
                        if (isKeyValid( key ) )
                        {
                                GeoHeightField hf = createGeoHeightField( key, progress );
                                if (hf.valid())
                                {
                                        result = hf.takeHeightField();
                                }
                        }
                }

                else
                {
                        //Collect the heightfields for each of the intersecting tiles.
                        //typedef std::vector< GeoHeightField > HeightFields;
                        GeoHeightFieldVector heightFields;

                        //Determine the intersecting keys
                        std::vector< TileKey > intersectingTiles;
                        getProfile()->getIntersectingTiles(key, intersectingTiles);
                        if (intersectingTiles.size() > 0)
                        {
                                for (unsigned int i = 0; i < intersectingTiles.size(); ++i)
                                {
                                        if (isKeyValid( intersectingTiles[i] ) )
                                        {
                        GeoHeightField hf = createGeoHeightField( intersectingTiles[i], progress );
                                                if (hf.valid())
                                                {
                                                        heightFields.push_back(hf);
                                                }
                                        }
                                }
                        }

                        //If we actually got a HeightField, resample/reproject it to match the incoming TileKey's extents.
                        if (heightFields.size() > 0)
                        {               
                                unsigned int width = 0;
                                unsigned int height = 0;

                for (GeoHeightFieldVector::iterator itr = heightFields.begin(); itr != heightFields.end(); ++itr)
                                {
                                        if (itr->getHeightField()->getNumColumns() > width)
                        width = itr->getHeightField()->getNumColumns();
                                        if (itr->getHeightField()->getNumRows() > height) 
                        height = itr->getHeightField()->getNumRows();
                                }

                result = new osg::HeightField();
                                result->allocate(width, height);

                                //Go ahead and set up the heightfield so we don't have to worry about it later
                                double minx, miny, maxx, maxy;
                                key.getExtent().getBounds(minx, miny, maxx, maxy);
                                double dx = (maxx - minx)/(double)(width-1);
                                double dy = (maxy - miny)/(double)(height-1);

                                //Create the new heightfield by sampling all of them.
                                for (unsigned int c = 0; c < width; ++c)
                                {
                                        double geoX = minx + (dx * (double)c);
                                        for (unsigned r = 0; r < height; ++r)
                                        {
                                                double geoY = miny + (dy * (double)r);

                                                //For each sample point, try each heightfield.  The first one with a valid elevation wins.
                                                float elevation = NO_DATA_VALUE;
                                                for (GeoHeightFieldVector::iterator itr = heightFields.begin(); itr != heightFields.end(); ++itr)
                                                {
                                                        float e = 0.0;
                            if (itr->getElevation(key.getExtent().getSRS(), geoX, geoY, INTERP_BILINEAR, _profile->getVerticalSRS(), e))
                                                        {
                                                                elevation = e;
                                                                break;
                                                        }
                                                }
                                                result->setHeight( c, r, elevation );                
                                        }
                                }
                        }
                }
    
        //Write the result to the cache.
        if (result && _cache.valid() && _runtimeOptions.cacheEnabled() == true )
        {
            _cache->setHeightField( key, _cacheSpec, result );
        }
    }

        //Initialize the HF values for osgTerrain
        if ( result )
        {       
                //Go ahead and set up the heightfield so we don't have to worry about it later
                double minx, miny, maxx, maxy;
                key.getExtent().getBounds(minx, miny, maxx, maxy);
                result->setOrigin( osg::Vec3d( minx, miny, 0.0 ) );
                double dx = (maxx - minx)/(double)(result->getNumColumns()-1);
                double dy = (maxy - miny)/(double)(result->getNumRows()-1);
                result->setXInterval( dx );
                result->setYInterval( dy );
                result->setBorderWidth( 0 );
        }
        
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ElevationLayer::fireCallback ( TerrainLayerCallbackMethodPtr  method) [private, virtual]

Implements osgEarth::TerrainLayer.

Definition at line 153 of file ElevationLayer.cpp.

{
    for( ElevationLayerCallbackList::const_iterator i = _callbacks.begin(); i != _callbacks.end(); ++i )
    {
        ElevationLayerCallback* cb = i->get();
        (cb->*method)( this );
    }
}
void ElevationLayer::fireCallback ( ElevationLayerCallbackMethodPtr  method) [private, virtual]

Definition at line 163 of file ElevationLayer.cpp.

{
    for( ElevationLayerCallbackList::const_iterator i = _callbacks.begin(); i != _callbacks.end(); ++i )
    {
        ElevationLayerCallback* cb = i->get();
        (cb->*method)( this );
    }
}
const ElevationLayerOptions& osgEarth::ElevationLayer::getElevationLayerOptions ( ) const [inline]

Gets the initialization options with which the layer was created.

Definition at line 95 of file ElevationLayer.

{ return _runtimeOptions; }

Here is the caller graph for this function:

virtual const TerrainLayerOptions& osgEarth::ElevationLayer::getTerrainLayerOptions ( ) const [inline, virtual]

The options data connected to this layer.

Reimplemented from osgEarth::TerrainLayer.

Definition at line 96 of file ElevationLayer.

{ return _runtimeOptions; }

Here is the caller graph for this function:

void ElevationLayer::init ( ) [private]

Reimplemented from osgEarth::TerrainLayer.

Definition at line 121 of file ElevationLayer.cpp.

{
    _tileSize = 32;
}

Here is the caller graph for this function:

void ElevationLayer::initTileSource ( ) [protected, virtual]

Reimplemented from osgEarth::TerrainLayer.

Definition at line 173 of file ElevationLayer.cpp.

{
    // call superclass first.
    TerrainLayer::initTileSource();

    if ( _tileSource.valid() )
        _preCacheOp = new ElevationLayerPreCacheOperation( _tileSource.get() );
}
void ElevationLayer::removeCallback ( ElevationLayerCallback cb)

Removes a property notification callback from this layer

Definition at line 145 of file ElevationLayer.cpp.

{
    ElevationLayerCallbackList::iterator i = std::find( _callbacks.begin(), _callbacks.end(), cb );
    if ( i != _callbacks.end() ) 
        _callbacks.erase( i );
}
std::string ElevationLayer::suggestCacheFormat ( ) const [protected, virtual]

Reimplemented from osgEarth::TerrainLayer.

Definition at line 127 of file ElevationLayer.cpp.

{
#if OSG_MIN_VERSION_REQUIRED(2,8,0)
        //OSG 2.8 onwards should use TIF for heightfields
        return "tif";
#else
        //OSG 2.8 and below should use DDS
        return "dds";
#endif
}

Member Data Documentation

Definition at line 126 of file ElevationLayer.

Definition at line 130 of file ElevationLayer.

Reimplemented from osgEarth::TerrainLayer.

Definition at line 124 of file ElevationLayer.


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