osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/TerrainLayer.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2010 Pelican Mapping
00004  * http://osgearth.org
00005  *
00006  * osgEarth is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 #include <osgEarth/TerrainLayer>
00020 #include <osgEarth/TileSource>
00021 #include <osgEarth/Registry>
00022 #include <osgEarth/StringUtils>
00023 #include <osgDB/WriteFile>
00024 #include <osg/Version>
00025 #include <OpenThreads/ScopedLock>
00026 #include <memory.h>
00027 
00028 using namespace osgEarth;
00029 using namespace OpenThreads;
00030 
00031 #define LC "[TerrainLayer] "
00032 
00033 //------------------------------------------------------------------------
00034 
00035 TerrainLayerOptions::TerrainLayerOptions( const ConfigOptions& options ) :
00036 ConfigOptions( options ),
00037 _minLevel( 0 ),
00038 _maxLevel( 99 ),
00039 _cacheEnabled( true ),
00040 _cacheOnly( false ),
00041 _loadingWeight( 1.0f ),
00042 _exactCropping( false ),
00043 _enabled( true ),
00044 _reprojectedTileSize( 256 )
00045 
00046 {
00047     setDefaults();
00048     fromConfig( _conf ); 
00049 }
00050 
00051 TerrainLayerOptions::TerrainLayerOptions( const std::string& name, const TileSourceOptions& driverOptions ) :
00052 ConfigOptions()
00053 {
00054     setDefaults();
00055     fromConfig( _conf );
00056     _name = name;
00057     _driver = driverOptions;
00058 }
00059 
00060 void
00061 TerrainLayerOptions::setDefaults()
00062 {
00063     _enabled.init( true );
00064     _exactCropping.init( false );
00065     _reprojectedTileSize.init( 256 );
00066     _cacheEnabled.init( true );
00067     _cacheOnly.init( false );
00068     _loadingWeight.init( 1.0f );
00069     _minLevel.init( 0 );
00070     _maxLevel.init( 99 );
00071 }
00072 
00073 Config
00074 TerrainLayerOptions::getConfig() const
00075 {
00076     Config conf = ConfigOptions::getConfig();
00077 
00078     conf.attr("name") = _name;
00079     conf.updateIfSet( "cacheid", _cacheId );
00080     conf.updateIfSet( "min_level", _minLevel );
00081     conf.updateIfSet( "max_level", _maxLevel );
00082     conf.updateIfSet( "min_level_resolution", _minLevelResolution );
00083     conf.updateIfSet( "max_level_resolution", _maxLevelResolution );
00084     conf.updateIfSet( "cache_enabled", _cacheEnabled );
00085     conf.updateIfSet( "cache_only", _cacheOnly );
00086     conf.updateIfSet( "cache_format", _cacheFormat );
00087     conf.updateIfSet( "loading_weight", _loadingWeight );
00088     conf.updateIfSet( "enabled", _enabled );
00089     conf.updateIfSet( "edge_buffer_ratio", _edgeBufferRatio);
00090     conf.updateObjIfSet( "profile", _profile );
00091     conf.updateIfSet( "max_data_level", _maxDataLevel);
00092     conf.updateIfSet( "reprojected_tilesize", _reprojectedTileSize);
00093 
00094     //Merge the TileSource options
00095     if (driver().isSet()) conf.merge( driver()->getConfig() );
00096 
00097     return conf;
00098 }
00099 
00100 void
00101 TerrainLayerOptions::fromConfig( const Config& conf )
00102 {
00103     _name = conf.value("name");
00104     conf.getIfSet( "cacheid", _cacheId );
00105     conf.getIfSet( "min_level", _minLevel );
00106     conf.getIfSet( "max_level", _maxLevel );        
00107     conf.getIfSet( "min_level_resolution", _minLevelResolution );
00108     conf.getIfSet( "max_level_resolution", _maxLevelResolution );
00109     conf.getIfSet( "cache_enabled", _cacheEnabled );
00110     conf.getIfSet( "cache_only", _cacheOnly );
00111     conf.getIfSet( "cache_format", _cacheFormat );
00112     conf.getIfSet( "loading_weight", _loadingWeight );
00113     conf.getIfSet( "enabled", _enabled );
00114     conf.getIfSet( "edge_buffer_ratio", _edgeBufferRatio);
00115     conf.getObjIfSet( "profile", _profile );
00116     conf.getIfSet( "max_data_level", _maxDataLevel);
00117     conf.getIfSet( "reprojected_tilesize", _reprojectedTileSize);
00118 
00119 
00120     if ( conf.hasValue("driver") )
00121         driver() = TileSourceOptions(conf);
00122 }
00123 
00124 void
00125 TerrainLayerOptions::mergeConfig( const Config& conf )
00126 {
00127     ConfigOptions::mergeConfig( conf );
00128     fromConfig( conf );
00129 }
00130 
00131 //------------------------------------------------------------------------
00132 
00133 TerrainLayer::TerrainLayer( TerrainLayerOptions* options ) :
00134 _runtimeOptions( options )
00135 {
00136     init();
00137 }
00138 
00139 TerrainLayer::TerrainLayer( TerrainLayerOptions* options, TileSource* tileSource ) :
00140 _runtimeOptions( options ),
00141 _tileSource    ( tileSource )
00142 {
00143     init();
00144 }
00145 
00146 void
00147 TerrainLayer::init()
00148 {
00149     _tileSourceInitialized = false;
00150     _tileSize              = 256;
00151 }
00152 
00153 void
00154 TerrainLayer::setCache(Cache* cache)
00155 {
00156     if (_cache.get() != cache)
00157     {
00158         _cache = cache;        
00159 
00160         // Read properties from the cache if not already set
00161         if ( _cache.valid() && _runtimeOptions->cacheEnabled() == true )
00162         {
00163             // create the unique cache ID for the tile configuration.
00164             std::string cacheId;
00165 
00166             if ( _runtimeOptions->cacheId().isSet() && !_runtimeOptions->cacheId()->empty() )
00167             {
00168                 // user expliticy set a cacheId in the terrain layer options.
00169                 cacheId = *_runtimeOptions->cacheId();
00170             }
00171             else
00172             {
00173                 // system will generate a cacheId.
00174                 Config hashConf = _runtimeOptions->driver()->getConfig();
00175 
00176                 // remove cache-control properties before hashing.
00177                 hashConf.remove( "cache_only" );
00178                 hashConf.remove( "cache_enabled" );
00179 
00180                 std::stringstream buf;
00181                 //OE_NOTICE << hashConf.toHashString() << std::endl;
00182                 buf << std::fixed << std::setfill('0') << std::hex
00183                     << osgEarth::hashString( hashConf.toHashString() );
00184                 cacheId = buf.str();
00185             }
00186 
00187             // try to load the properties from the cache; if that is unsuccesful,
00188             // create new properties.
00189             osg::ref_ptr<const Profile> profile;
00190             _cache->loadProperties( cacheId, _cacheSpec, profile, _tileSize );
00191 
00192             // Set the profile if it hasn't already been set
00193             if (!_profile.valid() && profile.valid())
00194             {
00195                 _profile = profile.get();
00196             }
00197 
00198             // Set the cache format if it hasn't been explicitly set
00199             if ( !_runtimeOptions->cacheFormat().isSet() )
00200             {
00201                 _runtimeOptions->cacheFormat() = _cacheSpec.format();
00202             }
00203 
00204             _cacheSpec = CacheSpec( cacheId, *_runtimeOptions->cacheFormat(), getName() );
00205         }
00206     }
00207 }
00208 
00209 void
00210 TerrainLayer::setTargetProfileHint( const Profile* profile )
00211 {
00212     _targetProfileHint = profile;
00213 }
00214 
00215 TileSource* 
00216 TerrainLayer::getTileSource() const
00217 {
00218     if ((_tileSource.valid() && !_tileSourceInitialized) ||
00219         (!_tileSource.valid() && _runtimeOptions->cacheOnly() == false) )
00220     {
00221         OpenThreads::ScopedLock< OpenThreads::Mutex > lock(const_cast<TerrainLayer*>(this)->_initTileSourceMutex );
00222         // double-check pattern
00223         if ((_tileSource.valid() && !_tileSourceInitialized) ||
00224             (!_tileSource.valid() && _runtimeOptions->cacheOnly() == false))
00225         {
00226             const_cast<TerrainLayer*>(this)->initTileSource();
00227         }
00228     }
00229 
00230     return _tileSource.get();
00231 }
00232 
00233 const Profile*
00234 TerrainLayer::getProfile() const
00235 {
00236     if ( !_profile.valid() )
00237     {
00238         if ( _runtimeOptions->cacheOnly() == false && !_tileSourceInitialized )
00239         {
00240             // Call getTileSource to make sure the TileSource is initialized
00241             getTileSource();
00242         }
00243 
00244         if ( _tileSource.valid() && !_profile.valid() )
00245         {
00246             const_cast<TerrainLayer*>(this)->_profile = _tileSource->getProfile();
00247         }
00248     }
00249     
00250     return _profile.get();
00251 }
00252 
00253 unsigned int
00254 TerrainLayer::getMaxDataLevel() const
00255 {
00256     //Try the setting first
00257 
00258     if ( _runtimeOptions->maxDataLevel().isSet() )
00259     {
00260         return _runtimeOptions->maxDataLevel().get();
00261     }
00262 
00263     //Try the TileSource
00264         TileSource* ts = getTileSource();
00265         if ( ts )
00266         {
00267                 return ts->getMaxDataLevel();
00268         }
00269 
00270     //Just default
00271         return 20;
00272 }
00273 
00274 unsigned
00275 TerrainLayer::getTileSize() const
00276 {
00277     TileSource* ts = getTileSource();
00278     return ts ? ts->getPixelsPerTile() : _tileSize;
00279 }
00280 
00281 bool
00282 TerrainLayer::isDynamic() const
00283 {
00284     TileSource* ts = getTileSource();
00285     return ts ? ts->isDynamic() : false;
00286 }
00287 
00288 //TODO: move this to ImageLayer/ElevationLayer
00289 std::string
00290 TerrainLayer::suggestCacheFormat() const
00291 {
00292     std::string ext = _tileSource.valid() ? _tileSource->getExtension() : "";
00293     return !ext.empty() ? ext : "png";
00294 }
00295 
00296 void
00297 TerrainLayer::initTileSource()
00298 {       
00299     OE_DEBUG << LC << "Initializing tile source ..." << std::endl;
00300 
00301     // instantiate it from driver options if it has not already been created:
00302     if ( !_tileSource.valid() )
00303     {
00304         if ( _runtimeOptions->driver().isSet() )
00305         {
00306             _tileSource = TileSourceFactory::create( *_runtimeOptions->driver() );
00307         }
00308     }
00309 
00310     // next check for an override-profile. The profile usually comes from the
00311     // TileSource itself, but you have the option of overriding:
00312         osg::ref_ptr<const Profile> overrideProfile;
00313         if ( _runtimeOptions->profile().isSet() )
00314         {
00315                 overrideProfile = Profile::create( *_runtimeOptions->profile() );
00316         }
00317 
00318     // Initialize the profile with the context information:
00319         if ( _tileSource.valid() )
00320         {
00321                 _tileSource->initialize( _referenceURI, overrideProfile.get() );
00322 
00323                 if ( _tileSource->isOK() )
00324                 {
00325                         _tileSize = _tileSource->getPixelsPerTile();
00326                 }
00327                 else
00328                 {
00329                 OE_WARN << "Could not initialize TileSource for layer " << getName() << std::endl;
00330             _tileSource = NULL;
00331                 }
00332         }
00333     
00334     // Set the cache format to the native format of the TileSource if it isn't already set.
00335     if ( _runtimeOptions->cacheFormat()->empty() )
00336     {
00337         _runtimeOptions->cacheFormat() = suggestCacheFormat();
00338         _cacheSpec = CacheSpec( _cacheSpec.cacheId(), *_runtimeOptions->cacheFormat(), _cacheSpec.name() );
00339     }
00340 
00341     // Set the profile from the TileSource if possible:
00342     if ( _tileSource.valid() )
00343     {
00344         _profile = _tileSource->getProfile();
00345     }
00346     
00347     // Otherwise, force cache-only mode (since there is no tilesource). The layer will try to 
00348     // establish a profile from the metadata in the cache instead.
00349     else if (_cache.valid())
00350     {
00351         OE_NOTICE << "Could not initialize TileSource " << _name << " but cache is valid.  Setting layer to cache_only." << std::endl;
00352         _runtimeOptions->cacheOnly() = true;
00353     }
00354 
00355         // check the environment to see if cache only should be enabled
00356     if ( _runtimeOptions->cacheOnly() == false && ::getenv("OSGEARTH_CACHE_ONLY") != 0 )
00357         {
00358         _runtimeOptions->cacheOnly() = true;
00359         OE_INFO << "CACHE-ONLY mode enabled!!" << std::endl;
00360         }
00361 
00362     _tileSourceInitialized = true;
00363 }
00364 
00365 bool
00366 TerrainLayer::isKeyValid(const TileKey& key) const
00367 {
00368         if (!key.valid()) return false;
00369         
00370     // Check to see if explicit levels of detail are set
00371     if ( _runtimeOptions->minLevel().isSet() && (int)key.getLevelOfDetail() < _runtimeOptions->minLevel().value() )
00372         return false;
00373         if ( _runtimeOptions->maxLevel().isSet() && (int)key.getLevelOfDetail() > _runtimeOptions->maxLevel().value() ) 
00374         return false;
00375     
00376     // Check to see if levels of detail based on resolution are set
00377     if ( _runtimeOptions->minLevelResolution().isSet() )
00378     {        
00379         unsigned int minLevel = getProfile()->getLevelOfDetailForHorizResolution(
00380             _runtimeOptions->minLevelResolution().value(), getTileSize() );
00381         OE_DEBUG << "Computed min level of " << minLevel << std::endl;
00382         if (key.getLevelOfDetail() < minLevel) return false;
00383     }
00384 
00385     if (_runtimeOptions->maxLevelResolution().isSet())
00386     {        
00387         unsigned int maxLevel = getProfile()->getLevelOfDetailForHorizResolution(
00388             _runtimeOptions->maxLevelResolution().value(), getTileSize() );
00389         OE_DEBUG << "Computed max level of " << maxLevel << std::endl;
00390         if (key.getLevelOfDetail() > maxLevel) return false;
00391     }
00392 
00393         return true;
00394 }
00395 
00396 void
00397 TerrainLayer::setEnabled( bool value )
00398 {
00399     _runtimeOptions->enabled() = value;
00400     fireCallback( &TerrainLayerCallback::onEnabledChanged );
00401 }
00402 
00403 void
00404 TerrainLayer::setReferenceURI( const std::string& uri )
00405 {
00406     _referenceURI = uri;
00407 }
00408 
00409 void
00410 TerrainLayer::setCacheOnly( bool value )
00411 {
00412     _runtimeOptions->cacheOnly() = value;
00413 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines