osgEarth 2.1.1
|
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 |
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.
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.
Technique for elevation data sampling - see setTechnique
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.
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.
map | Map against which to perform elevation queries. |
technique | Technique to use for elevation data sampling. |
Definition at line 14 of file ElevationManager.cpp.
: _mapf( map, Map::ELEVATION_LAYERS ) { postCTOR(); }
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.
x,y | Map coordinates for which to query elevation. |
resolution | Optimal resolution of elevation data to use for the query (if available). Pass in 0 (zero) to use the best available resolution. |
srs | Spatial 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_elevation | Resulting elevation value (if the method returns true.) |
out_resolution | Resolution of the resulting elevation value (if the method returns true). |
Definition at line 91 of file ElevationManager.cpp.
{ sync(); return getElevationImpl(x, y, resolution, srs, out_elevation, out_resolution); }
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; } }
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; }
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.
{ _tileSize = 0; _maxDataLevel = 0; _maxCacheSize = 100; _technique = TECHNIQUE_PARAMETRIC; _interpolation = INTERP_BILINEAR; _maxLevelOverride = -1; }
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; } } }
ElevationInterpolation osgEarth::Util::ElevationManager::_interpolation [private] |
Definition at line 172 of file ElevationManager.
Definition at line 162 of file ElevationManager.
int osgEarth::Util::ElevationManager::_maxCacheSize [private] |
Definition at line 167 of file ElevationManager.
unsigned int osgEarth::Util::ElevationManager::_maxDataLevel [private] |
Definition at line 169 of file ElevationManager.
int osgEarth::Util::ElevationManager::_maxLevelOverride [private] |
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.
int osgEarth::Util::ElevationManager::_tileSize [private] |
Definition at line 168 of file ElevationManager.