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

osgEarth::Util::ElevationManager Class Reference

Inheritance diagram for osgEarth::Util::ElevationManager:
Collaboration diagram for osgEarth::Util::ElevationManager:

List of all members.

Public Types

enum  Technique { TECHNIQUE_GEOMETRIC, TECHNIQUE_PARAMETRIC }

Public Member Functions

 ElevationManager (Map *map)
bool getElevation (double x, double y, double resolution, const SpatialReference *srs, double &out_elevation, double &out_resolution)
bool getPlacementMatrix (double x, double y, double z, double resolution, const SpatialReference *srs, osg::Matrixd &out_matrix, double &out_elevation, double &out_resolution)
void setTechnique (Technique technique)
Technique getTechnique () const
void setMaxTilesToCache (int value)
int getMaxTilesToCache () const
void setInterpolation (ElevationInterpolation interp)
ElevationInterpolation getElevationInterpolation () const
void setMaxLevelOverride (int maxLevelOverride)
int getMaxLevelOverride () const

Private Types

typedef std::map
< osgTerrain::TileID,
osg::ref_ptr
< osgTerrain::TerrainTile > > 
TileTable
typedef std::list
< osgTerrain::TileID > 
TileIdList

Private Member Functions

void postCTOR ()
void sync ()
bool getElevationImpl (double x, double y, double resolution, const SpatialReference *srs, double &out_elevation, double &out_resolution)

Private Attributes

MapFrame _mapf
TileTable _tileCache
TileIdList _tileCacheFIFO
int _maxCacheSize
int _tileSize
unsigned int _maxDataLevel
int _maxLevelOverride
Technique _technique
ElevationInterpolation _interpolation

Detailed Description

ElevationManager (EM) lets you query the elevation at any point on a terrain map.

Rather than intersecting with a loaded scene graph, EM uses the osgEarth engine to directly access the best terrain tile for elevation query. You give it the DEM resolution at which you want an elevation point, and it will access the necessary tile and sample it.

EM supports two types of sampling:

PARAMTERIC - EM will sample the actual heightfield directly. This method is the fastest since it does not require geometry intersection testing. GEOMETRIC - EM will create a temporary tesselated terrain tile and do an intersection test (using osgUtil::IntersectionVisitor). This method is slower but more visually correlated.

NOTE: EM does NOT take into account rendering properties like vertical scale or skirts. If you need a vertical scale, for example, simply scale the resulting elevation value.

Definition at line 50 of file ElevationManager.


Member Typedef Documentation

typedef std::list< osgTerrain::TileID > osgEarth::Util::ElevationManager::TileIdList [private]

Definition at line 165 of file ElevationManager.

typedef std::map< osgTerrain::TileID, osg::ref_ptr<osgTerrain::TerrainTile> > osgEarth::Util::ElevationManager::TileTable [private]

Definition at line 163 of file ElevationManager.


Member Enumeration Documentation

Technique for elevation data sampling - see setTechnique

Enumerator:
TECHNIQUE_GEOMETRIC 

Intersect with triangulated geometry - using the highest resolution data available from the Map source layers

TECHNIQUE_PARAMETRIC 

Sample height from the parametric heightfield directly (bilinear)

Definition at line 54 of file ElevationManager.


Constructor & Destructor Documentation

ElevationManager::ElevationManager ( Map map)

Constructs a new elevation manager. If you are not using a MapNode, use this constructor to perform elevation queries against a Map. If you *do* have a MapNode, use the other CTOR that takes a MapNode.

Parameters:
mapMap against which to perform elevation queries.
techniqueTechnique to use for elevation data sampling.

Definition at line 14 of file ElevationManager.cpp.

Here is the call graph for this function:


Member Function Documentation

bool ElevationManager::getElevation ( double  x,
double  y,
double  resolution,
const SpatialReference srs,
double &  out_elevation,
double &  out_resolution 
)

Gets the terrain elevation at a point, given a terrain resolution.

Parameters:
x,yMap coordinates for which to query elevation.
resolutionOptimal resolution of elevation data to use for the query (if available). Pass in 0 (zero) to use the best available resolution.
srsSpatial reference of x, y, and resolution. If this is NULL, assume that the input values are expressed in terms of the Map's SRS.
out_elevationResulting elevation value (if the method returns true.)
out_resolutionResolution of the resulting elevation value (if the method returns true).
Returns:
True if the query succeeded, false upon failure.

Definition at line 91 of file ElevationManager.cpp.

{
    sync();
    return getElevationImpl(x, y, resolution, srs, out_elevation, out_resolution);
}

Here is the call graph for this function:

bool ElevationManager::getElevationImpl ( double  x,
double  y,
double  resolution,
const SpatialReference srs,
double &  out_elevation,
double &  out_resolution 
) [private]

Definition at line 102 of file ElevationManager.cpp.

{
    if ( _maxDataLevel == 0 || _tileSize == 0 )
    {
        // this means there are no heightfields.
        out_elevation = 0.0;
        return true;
    }
   
    // this is the ideal LOD for the requested resolution:
    unsigned int idealLevel = resolution > 0.0
        ? _mapf.getProfile()->getLevelOfDetailForHorizResolution( resolution, _tileSize )
        : _maxDataLevel;        

    // based on the heightfields available, this is the best we can theorically do:
    unsigned int bestAvailLevel = osg::minimum( idealLevel, _maxDataLevel );
    if (_maxLevelOverride >= 0)
    {
        bestAvailLevel = osg::minimum(bestAvailLevel, (unsigned int)_maxLevelOverride);
    }
    
    // transform the input coords to map coords:
    double map_x = x, map_y = y;
    if ( srs && !srs->isEquivalentTo( _mapf.getProfile()->getSRS() ) )
    {
        if ( !srs->transform2D( x, y, _mapf.getProfile()->getSRS(), map_x, map_y ) )
        {
            OE_WARN << LC << "Fail: coord transform failed" << std::endl;
            return false;
        }
    }

    osg::ref_ptr<osg::HeightField> hf;
    osg::ref_ptr<osgTerrain::TerrainTile> tile;

    // get the tilekey corresponding to the tile we need:
    TileKey key = _mapf.getProfile()->createTileKey( map_x, map_y, bestAvailLevel );
    if ( !key.valid() )
    {
        OE_WARN << LC << "Fail: coords fall outside map" << std::endl;
        return false;
    }

    // now, see if we already have this tile loaded somewhere:
    osgTerrain::TileID tileId = key.getTileId();

    if ( !tile.valid() )
    {
        // next check the local tile cache:
        TileTable::const_iterator i = _tileCache.find( tileId );
        if ( i != _tileCache.end() )
            tile = i->second.get();
    }

         
    // if we found it, make sure it has a heightfield in it:
    if ( tile.valid() )
    {
        osgTerrain::HeightFieldLayer* layer = dynamic_cast<osgTerrain::HeightFieldLayer*>(tile->getElevationLayer());
        if ( layer )
        {
            hf = layer->getHeightField();
        }
        if ( !hf.valid() )
        {
            tile = NULL;
        }
    }

    // if we didn't find it (or it didn't have heightfield data), build it.
    if ( !tile.valid() )
    {
        //OE_NOTICE << "ElevationManager: cache miss" << std::endl;

        // generate the heightfield corresponding to the tile key, automatically falling back
        // on lower resolution if necessary:
        _mapf.getHeightField( key, true, hf, 0L, _interpolation );

        // bail out if we could not make a heightfield a all.
        if ( !hf.valid() )
        {
            OE_WARN << "ElevationManager: unable to create heightfield" << std::endl;
            return false;
        }

        GeoLocator* locator = GeoLocator::createForKey( key, _mapf.getMapInfo() );

        tile = new osgTerrain::TerrainTile();

        osgTerrain::HeightFieldLayer* layer = new osgTerrain::HeightFieldLayer( hf.get() );
        layer->setLocator( locator );

        tile->setElevationLayer( layer );
        tile->setRequiresNormals( false );
        tile->setTerrainTechnique( new osgTerrain::GeometryTechnique );

        // store it in the local tile cache.
        // TODO: limit the size of the cache with a parallel FIFO list.
        _tileCache[tileId] = tile.get();
        _tileCacheFIFO.push_back( tileId );

        // prune the cache. this is a terrible pruning method.
        if ( _tileCache.size() > _maxCacheSize )
        {
            osgTerrain::TileID id = _tileCacheFIFO.front();
            _tileCacheFIFO.pop_front();
            if ( tileId != id )
                _tileCache.erase( id );
        }
    }


    // see what the actual resolution of the heightfield is.
    out_resolution = (double)hf->getXInterval();


    // finally it's time to get a height value:
    if ( _technique == TECHNIQUE_PARAMETRIC )
    {
        const GeoExtent& extent = key.getExtent();
        double xInterval = extent.width()  / (double)(hf->getNumColumns()-1);
        double yInterval = extent.height() / (double)(hf->getNumRows()-1);
        out_elevation = (double) HeightFieldUtils::getHeightAtLocation( hf.get(), map_x, map_y, extent.xMin(), extent.yMin(), xInterval, yInterval );
        return true;
    }
    else // ( _technique == TECHNIQUE_GEOMETRIC )
    {
        osg::Vec3d start, end, zero;

        if ( _mapf.getMapInfo().isGeocentric() )
        {
            const osg::EllipsoidModel* ellip = _mapf.getProfile()->getSRS()->getEllipsoid();

            ellip->convertLatLongHeightToXYZ(
                osg::DegreesToRadians( map_y ),
                osg::DegreesToRadians( map_x ),
                50000,
                start.x(), start.y(), start.z() );

            ellip->convertLatLongHeightToXYZ(
                osg::DegreesToRadians( map_y ),
                osg::DegreesToRadians( map_x ),
                -50000,
                end.x(), end.y(), end.z() );

            ellip->convertLatLongHeightToXYZ(
                osg::DegreesToRadians( map_y ),
                osg::DegreesToRadians( map_x ),
                0.0,
                zero.x(), zero.y(), zero.z() );
        }
        else // PROJECTED
        {
            start.x() = map_x; start.y() = map_y; start.z() = 50000;
            end.x() = map_x; end.y() = map_y; end.z() = -50000;
            zero.x() = map_x; zero.y() = map_y; zero.z() = 0;
        }

        osgUtil::LineSegmentIntersector* i = new osgUtil::LineSegmentIntersector( start, end );
        osgUtil::IntersectionVisitor iv;
        iv.setIntersector( i );

        tile->accept( iv );

        osgUtil::LineSegmentIntersector::Intersections& results = i->getIntersections();
        if ( !results.empty() )
        {
            const osgUtil::LineSegmentIntersector::Intersection& result = *results.begin();
            osg::Vec3d isectPoint = result.getWorldIntersectPoint();
            out_elevation = (isectPoint-end).length2() > (zero-end).length2()
                ? (isectPoint-zero).length()
                : -(isectPoint-zero).length();
            return true;            
        }

        OE_WARN << "ElevationManager: no intersections" << std::endl;
        return false;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

ElevationInterpolation ElevationManager::getElevationInterpolation ( ) const

Gets the elevation interpolation to use when sampling data

Definition at line 85 of file ElevationManager.cpp.

{
    return _interpolation;
}
int osgEarth::Util::ElevationManager::getMaxLevelOverride ( ) const

Gets the maximum level override for elevation queries.

int ElevationManager::getMaxTilesToCache ( ) const

Gets the maximum cache size for elevation tiles.

Definition at line 73 of file ElevationManager.cpp.

{
    return _maxCacheSize;
}
bool ElevationManager::getPlacementMatrix ( double  x,
double  y,
double  z,
double  resolution,
const SpatialReference srs,
osg::Matrixd &  out_matrix,
double &  out_elevation,
double &  out_resolution 
)

Gets a matrix that you can use to position a node at the specified coordinates. The elevation of the object will be the ground height + the specified Z value. The ground height will be determined by using getElevation() with the specified resolution.

Returns TRUE if the output matrix is valid.

Definition at line 288 of file ElevationManager.cpp.

{
    sync();

    const SpatialReference* mapSRS = _mapf.getProfile()->getSRS();

    // transform the input coords to map coords:
    double map_x = x, map_y = y;
    if ( srs && !srs->isEquivalentTo( mapSRS ) )
    {
        if ( !srs->transform2D( x, y, mapSRS, map_x, map_y ) )
        {
            OE_WARN << LC << "getPlacementMatrix: coord transform failed" << std::endl;
            return false;
        }
    }

    // get the elevation under those coordinates:
    if ( !getElevationImpl( map_x, map_y, resolution, mapSRS, out_elevation, out_resolution) )
    {
        OE_WARN << LC << "getPlacementMatrix: getElevation failed" << std::endl;
        return false;
    }

    if ( _mapf.getMapInfo().isGeocentric() )
    {
        mapSRS->getEllipsoid()->computeLocalToWorldTransformFromLatLongHeight(
            osg::DegreesToRadians( map_y ),
            osg::DegreesToRadians( map_x ),
            out_elevation + z,
            out_matrix );
    }
    else
    {
        out_matrix = osg::Matrixd::translate( x, y, out_elevation + z );
    }

    return true;
}

Here is the call graph for this function:

ElevationManager::Technique ElevationManager::getTechnique ( ) const

Gets the technique to use for height determination. See the Technique enum in this class.

Definition at line 55 of file ElevationManager.cpp.

{
    return _technique;
}
void ElevationManager::postCTOR ( ) [private]

Definition at line 21 of file ElevationManager.cpp.

Here is the caller graph for this function:

void ElevationManager::setInterpolation ( ElevationInterpolation  interp)

Sets the elevation interpolation to use when sampling data

Definition at line 79 of file ElevationManager.cpp.

{
    _interpolation = interp;
}
void osgEarth::Util::ElevationManager::setMaxLevelOverride ( int  maxLevelOverride)

Sets the maximum level override for elevation queries. A value of -1 turns off the override.

void ElevationManager::setMaxTilesToCache ( int  value)

Sets the maximum cache size for elevation tiles.

Definition at line 67 of file ElevationManager.cpp.

{
    _maxCacheSize = value;
}
void ElevationManager::setTechnique ( ElevationManager::Technique  technique)

Sets the technique to use for height determination. See the Technique enum in this class. The default is TECHNIQUE_PARAMETRIC.

Definition at line 61 of file ElevationManager.cpp.

{
    _technique = technique;
}
void ElevationManager::sync ( ) [private]

Definition at line 32 of file ElevationManager.cpp.

{
    if ( _mapf.sync() || _tileSize == 0 || _maxDataLevel == 0 )
    {
        _tileSize = 0;
        _maxDataLevel = 0;

        for( ElevationLayerVector::const_iterator i = _mapf.elevationLayers().begin(); i != _mapf.elevationLayers().end(); ++i )
        {
            // we need the maximum tile size
            int layerTileSize = i->get()->getTileSize();
            if ( layerTileSize > _tileSize )
                _tileSize = layerTileSize;

            // we also need the maximum available data level.
            unsigned int layerMaxDataLevel = i->get()->getMaxDataLevel();
            if ( layerMaxDataLevel > _maxDataLevel )
                _maxDataLevel = layerMaxDataLevel;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

ElevationInterpolation osgEarth::Util::ElevationManager::_interpolation [private]

Definition at line 172 of file ElevationManager.

Definition at line 162 of file ElevationManager.

Definition at line 167 of file ElevationManager.

Definition at line 169 of file ElevationManager.

Definition at line 170 of file ElevationManager.

Definition at line 171 of file ElevationManager.

Definition at line 164 of file ElevationManager.

Definition at line 166 of file ElevationManager.

Definition at line 168 of file ElevationManager.


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