osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/Map.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/Map>
00020 #include <osgEarth/Registry>
00021 #include <osgEarth/TileSource>
00022 #include <OpenThreads/ScopedLock>
00023 #include <iterator>
00024 
00025 using namespace osgEarth;
00026 using namespace OpenThreads;
00027 
00028 #define LC "[Map] "
00029 
00030 //------------------------------------------------------------------------
00031 
00032 void
00033 MapCallback::onMapModelChanged( const MapModelChange& change )
00034 {
00035     switch( change.getAction() )
00036     {
00037     case MapModelChange::ADD_ELEVATION_LAYER: 
00038         onElevationLayerAdded( change.getElevationLayer(), change.getFirstIndex() ); break;
00039     case MapModelChange::ADD_IMAGE_LAYER:
00040         onImageLayerAdded( change.getImageLayer(), change.getFirstIndex() ); break;
00041     case MapModelChange::ADD_MASK_LAYER:
00042         onMaskLayerAdded( change.getMaskLayer() ); break;
00043     case MapModelChange::ADD_MODEL_LAYER:
00044                                 onModelLayerAdded( change.getModelLayer(), change.getFirstIndex() ); break;
00045     case MapModelChange::REMOVE_ELEVATION_LAYER:
00046         onElevationLayerRemoved( change.getElevationLayer(), change.getFirstIndex() ); break;
00047     case MapModelChange::REMOVE_IMAGE_LAYER:
00048         onImageLayerRemoved( change.getImageLayer(), change.getFirstIndex() ); break;
00049     case MapModelChange::REMOVE_MASK_LAYER:
00050         onMaskLayerRemoved( change.getMaskLayer() ); break;
00051     case MapModelChange::REMOVE_MODEL_LAYER:
00052         onModelLayerRemoved( change.getModelLayer() ); break;
00053     case MapModelChange::MOVE_ELEVATION_LAYER:
00054         onElevationLayerMoved( change.getElevationLayer(), change.getFirstIndex(), change.getSecondIndex() ); break;
00055     case MapModelChange::MOVE_IMAGE_LAYER:
00056         onImageLayerMoved( change.getImageLayer(), change.getFirstIndex(), change.getSecondIndex() ); break;
00057                 case MapModelChange::MOVE_MODEL_LAYER:
00058                                 onModelLayerMoved( change.getModelLayer(), change.getFirstIndex(), change.getSecondIndex() ); break;
00059     }
00060 }
00061 
00062 //------------------------------------------------------------------------
00063 
00064 Map::Map( const MapOptions& options ) :
00065 osg::Referenced( true ),
00066 _mapOptions( options ),
00067 _dataModelRevision(0)
00068 {
00069     //NOP
00070 }
00071 
00072 bool
00073 Map::isGeocentric() const
00074 {
00075     return 
00076         _mapOptions.coordSysType() == MapOptions::CSTYPE_GEOCENTRIC ||
00077         _mapOptions.coordSysType() == MapOptions::CSTYPE_GEOCENTRIC_CUBE;
00078 }
00079 
00080 const osgDB::ReaderWriter::Options*
00081 Map::getGlobalOptions() const {
00082     return _globalOptions.get();
00083 }
00084 
00085 void
00086 Map::setGlobalOptions( const osgDB::ReaderWriter::Options* options ) {
00087     _globalOptions = options;
00088 }
00089 
00090 int
00091 Map::getImageLayers( ImageLayerVector& out_list, bool validLayersOnly ) const
00092 {
00093     out_list.reserve( _imageLayers.size() );
00094 
00095     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
00096     for( ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
00097         if ( !validLayersOnly || i->get()->getProfile() )
00098             out_list.push_back( i->get() );
00099 
00100     return _dataModelRevision;
00101 }
00102 
00103 int
00104 Map::getNumImageLayers() const
00105 {
00106     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
00107     return _imageLayers.size();
00108 }
00109 
00110 ImageLayer*
00111 Map::getImageLayerByName( const std::string& name ) const
00112 {
00113     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00114     for( ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
00115         if ( i->get()->getName() == name )
00116             return i->get();
00117     return 0L;
00118 }
00119 
00120 ImageLayer*
00121 Map::getImageLayerByUID( UID layerUID ) const
00122 {
00123     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00124     for( ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
00125         if ( i->get()->getUID() == layerUID )
00126             return i->get();
00127     return 0L;
00128 }
00129 
00130 ImageLayer*
00131 Map::getImageLayerAt( int index ) const
00132 {
00133     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00134     if ( index >= 0 && index < (int)_imageLayers.size() )
00135         return _imageLayers[index].get();
00136     else
00137         return 0L;
00138 }
00139 
00140 int
00141 Map::getElevationLayers( ElevationLayerVector& out_list, bool validLayersOnly ) const
00142 {
00143     out_list.reserve( _elevationLayers.size() );
00144 
00145     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
00146     for( ElevationLayerVector::const_iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); ++i )
00147         if ( !validLayersOnly || i->get()->getProfile() )
00148             out_list.push_back( i->get() );
00149 
00150     return _dataModelRevision;
00151 }
00152 
00153 int
00154 Map::getNumElevationLayers() const
00155 {
00156     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
00157     return _elevationLayers.size();
00158 }
00159 
00160 ElevationLayer*
00161 Map::getElevationLayerByName( const std::string& name ) const
00162 {
00163     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00164     for( ElevationLayerVector::const_iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); ++i )
00165         if ( i->get()->getName() == name )
00166             return i->get();
00167     return 0L;
00168 }
00169 
00170 ElevationLayer*
00171 Map::getElevationLayerByUID( UID layerUID ) const
00172 {
00173     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00174     for( ElevationLayerVector::const_iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); ++i )
00175         if ( i->get()->getUID() == layerUID )
00176             return i->get();
00177     return 0L;
00178 }
00179 
00180 ElevationLayer*
00181 Map::getElevationLayerAt( int index ) const
00182 {
00183     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00184     if ( index >= 0 && index < (int)_elevationLayers.size() )
00185         return _elevationLayers[index].get();
00186     else
00187         return 0L;
00188 }
00189 
00190 int
00191 Map::getModelLayers( ModelLayerVector& out_list, bool validLayersOnly ) const
00192 {
00193     out_list.reserve( _modelLayers.size() );
00194 
00195     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
00196     for( ModelLayerVector::const_iterator i = _modelLayers.begin(); i != _modelLayers.end(); ++i )
00197         //if ( !validLayersOnly || i->get()->i->get()->getProfile() )
00198             out_list.push_back( i->get() );
00199 
00200     return _dataModelRevision;
00201 }
00202 
00203 ModelLayer*
00204 Map::getModelLayerByName( const std::string& name ) const
00205 {
00206     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00207     for( ModelLayerVector::const_iterator i = _modelLayers.begin(); i != _modelLayers.end(); ++i )
00208         if ( i->get()->getName() == name )
00209             return i->get();
00210     return 0L;
00211 }
00212 
00213 ModelLayer*
00214 Map::getModelLayerByUID( UID layerUID ) const
00215 {
00216     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00217     for( ModelLayerVector::const_iterator i = _modelLayers.begin(); i != _modelLayers.end(); ++i )
00218         if ( i->get()->getUID() == layerUID )
00219             return i->get();
00220     return 0L;
00221 }
00222 
00223 
00224 ModelLayer*
00225 Map::getModelLayerAt( int index ) const
00226 {
00227     Threading::ScopedReadLock( const_cast<Map*>(this)->_mapDataMutex );
00228     if ( index >= 0 && index < (int)_modelLayers.size() )
00229         return _modelLayers[index].get();
00230     else
00231         return 0L;
00232 }
00233 
00234 int
00235 Map::getNumModelLayers() const
00236 {
00237     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
00238     return _modelLayers.size();
00239 }
00240 
00241 int
00242 Map::getTerrainMaskLayers( MaskLayerVector& out_list ) const
00243 {
00244     out_list.reserve( _terrainMaskLayers.size() );
00245 
00246     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
00247     for( MaskLayerVector::const_iterator i = _terrainMaskLayers.begin(); i != _terrainMaskLayers.end(); ++i )
00248         out_list.push_back( i->get() );
00249 
00250     return _dataModelRevision;
00251 }
00252 
00253 void
00254 Map::setName( const std::string& name ) {
00255     _name = name;
00256 }
00257 
00258 Revision
00259 Map::getDataModelRevision() const
00260 {
00261     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
00262     return _dataModelRevision;
00263 }
00264 
00265 const Profile*
00266 Map::getProfile() const
00267 {
00268     if ( !_profile.valid() )
00269         const_cast<Map*>(this)->calculateProfile();
00270     return _profile.get();
00271 }
00272 
00273 Cache*
00274 Map::getCache() const
00275 {
00276     if ( !_cache.valid() )
00277     {
00278         Cache* cache = 0L;
00279 
00280         // if there's a cache override in the registry, install it now.
00281         if ( osgEarth::Registry::instance()->getCacheOverride() )
00282         {
00283             cache = osgEarth::Registry::instance()->getCacheOverride();
00284         }
00285 
00286         else if ( _mapOptions.cache().isSet() )
00287         {
00288             cache = CacheFactory::create( _mapOptions.cache().get() );
00289         }
00290 
00291         if ( cache )
00292         {
00293             const_cast<Map*>(this)->setCache( cache );
00294         }
00295     }
00296         return _cache.get();
00297 }
00298 
00299 void
00300 Map::setCache( Cache* cache )
00301 {
00302     if (_cache.get() != cache)
00303     {
00304         _cache = cache;
00305         _cache->setReferenceURI( _mapOptions.referenceURI().value() );
00306 
00307         //Propagate the cache to any of our layers
00308         for (ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i)
00309         {
00310             i->get()->setCache( _cache.get() );
00311         }
00312 
00313         for (ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); ++i)
00314         {
00315             i->get()->setCache( _cache.get() );
00316         }
00317     }
00318 }
00319 
00320 void 
00321 Map::addMapCallback( MapCallback* cb ) const
00322 {
00323     if ( cb )
00324         const_cast<Map*>(this)->_mapCallbacks.push_back( cb );
00325 }
00326 
00327 void 
00328 Map::removeMapCallback( MapCallback* cb )
00329 {
00330     MapCallbackList::iterator i = std::find( _mapCallbacks.begin(), _mapCallbacks.end(), cb);
00331     if (i != _mapCallbacks.end())
00332     {
00333         _mapCallbacks.erase( i );
00334     }    
00335 }
00336 
00337 void
00338 Map::addImageLayer( ImageLayer* layer )
00339 {
00340     osgEarth::Registry::instance()->clearBlacklist();
00341     unsigned int index = -1;
00342     if ( layer )
00343     {
00344             //Set options for the map from the layer
00345                 layer->setReferenceURI( _mapOptions.referenceURI().value() );
00346 
00347         //propagate the cache to the layer:
00348         if ( _mapOptions.cache().isSet() && _mapOptions.cache()->cacheOnly().isSetTo( true ) )
00349                 {
00350                         layer->setCacheOnly( true );
00351                 }
00352 
00353                 //Set the Cache for the MapLayer to our cache.
00354                 layer->setCache( this->getCache() );
00355 
00356         // Tell the layer the map profile, if possible:
00357         if ( _profile.valid() )
00358             layer->setTargetProfileHint( _profile.get() );
00359 
00360         int newRevision;
00361 
00362         // Add the layer to our stack.
00363         {
00364             Threading::ScopedWriteLock lock( _mapDataMutex );
00365 
00366             _imageLayers.push_back( layer );
00367             index = _imageLayers.size() - 1;
00368             newRevision = ++_dataModelRevision;
00369         }
00370 
00371         // a separate block b/c we don't need the mutex   
00372         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00373         {
00374             i->get()->onMapModelChanged( MapModelChange(
00375                 MapModelChange::ADD_IMAGE_LAYER, newRevision, layer, index) );
00376             //i->get()->onImageLayerAdded( layer, index, newRevision );
00377         }       
00378     }   
00379 }
00380 
00381 
00382 void
00383 Map::insertImageLayer( ImageLayer* layer, unsigned int index )
00384 {
00385     osgEarth::Registry::instance()->clearBlacklist();
00386     if ( layer )
00387     {
00388         //Set options for the map from the layer
00389         layer->setReferenceURI( _mapOptions.referenceURI().value() );
00390 
00391         //propagate the cache to the layer:
00392         if ( _mapOptions.cache().isSet() && _mapOptions.cache()->cacheOnly().isSetTo( true ) )
00393         {
00394             layer->setCacheOnly( true );
00395         }
00396 
00397         //Set the Cache for the MapLayer to our cache.
00398         layer->setCache( this->getCache() );
00399 
00400         // Tell the layer the map profile, if possible:
00401         if ( _profile.valid() )
00402             layer->setTargetProfileHint( _profile.get() );
00403 
00404         int newRevision;
00405 
00406         // Add the layer to our stack.
00407         {
00408             Threading::ScopedWriteLock lock( _mapDataMutex );
00409 
00410             if (index >= _imageLayers.size())
00411                 _imageLayers.push_back(layer);
00412             else
00413                 _imageLayers.insert( _imageLayers.begin() + index, layer );
00414 
00415             newRevision = ++_dataModelRevision;
00416         }
00417 
00418         // a separate block b/c we don't need the mutex   
00419         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00420         {
00421             i->get()->onMapModelChanged( MapModelChange(
00422                 MapModelChange::ADD_IMAGE_LAYER, newRevision, layer, index) );
00423         }       
00424     }   
00425 }
00426 
00427 void
00428 Map::addElevationLayer( ElevationLayer* layer )
00429 {
00430     osgEarth::Registry::instance()->clearBlacklist();
00431     unsigned int index = -1;
00432     if ( layer )
00433     {
00434             //Set options for the map from the layer
00435                 layer->setReferenceURI( _mapOptions.referenceURI().value() );
00436 
00437         //propagate the cache to the layer:
00438         if ( _mapOptions.cache().isSet() && _mapOptions.cache()->cacheOnly().isSetTo( true ) )
00439                 {
00440                         layer->setCacheOnly( true );
00441                 }
00442 
00443                 //Set the Cache for the MapLayer to our cache.
00444                 layer->setCache( this->getCache() );
00445         
00446         // Tell the layer the map profile, if possible:
00447         if ( _profile.valid() )
00448             layer->setTargetProfileHint( _profile.get() );
00449 
00450         int newRevision;
00451 
00452         // Add the layer to our stack.
00453         {
00454             Threading::ScopedWriteLock lock( _mapDataMutex );
00455 
00456             _elevationLayers.push_back( layer );
00457             index = _elevationLayers.size() - 1;
00458             newRevision = ++_dataModelRevision;
00459         }
00460 
00461         // a separate block b/c we don't need the mutex   
00462         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00463         {
00464             i->get()->onMapModelChanged( MapModelChange(
00465                 MapModelChange::ADD_ELEVATION_LAYER, newRevision, layer, index) );
00466         }       
00467     }   
00468 }
00469 
00470 void 
00471 Map::removeImageLayer( ImageLayer* layer )
00472 {
00473     osgEarth::Registry::instance()->clearBlacklist();
00474     unsigned int index = -1;
00475 
00476     osg::ref_ptr<ImageLayer> layerToRemove = layer;
00477     Revision newRevision;
00478 
00479     if ( layerToRemove.get() )
00480     {
00481         Threading::ScopedWriteLock lock( _mapDataMutex );
00482         index = 0;
00483         for( ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end(); i++, index++ )
00484         {
00485             if ( i->get() == layerToRemove.get() )
00486             {
00487                 _imageLayers.erase( i );
00488                 newRevision = ++_dataModelRevision;
00489                 break;
00490             }
00491         }
00492     }
00493 
00494     // a separate block b/c we don't need the mutex
00495     if ( newRevision >= 0 ) // layerToRemove.get() )
00496     {
00497         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00498         {
00499             i->get()->onMapModelChanged( MapModelChange(
00500                 MapModelChange::REMOVE_IMAGE_LAYER, newRevision, layerToRemove.get(), index) );
00501             //i->get()->onImageLayerRemoved( layerToRemove.get(), index, newRevision );
00502         }
00503     }
00504 }
00505 
00506 void 
00507 Map::removeElevationLayer( ElevationLayer* layer )
00508 {
00509     osgEarth::Registry::instance()->clearBlacklist();
00510     unsigned int index = -1;
00511 
00512     osg::ref_ptr<ElevationLayer> layerToRemove = layer;
00513     Revision newRevision;
00514 
00515     if ( layerToRemove.get() )
00516     {
00517         Threading::ScopedWriteLock lock( _mapDataMutex );
00518         index = 0;
00519         for( ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); i++, index++ )
00520         {
00521             if ( i->get() == layerToRemove.get() )
00522             {
00523                 _elevationLayers.erase( i );
00524                 newRevision = ++_dataModelRevision;
00525                 break;
00526             }
00527         }
00528     }
00529 
00530     // a separate block b/c we don't need the mutex
00531     if ( newRevision >= 0 ) //layerToRemove.get() )
00532     {
00533         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00534         {
00535             i->get()->onMapModelChanged( MapModelChange(
00536                 MapModelChange::REMOVE_ELEVATION_LAYER, newRevision, layerToRemove.get(), index) );
00537         }
00538     }
00539 }
00540 
00541 void
00542 Map::moveImageLayer( ImageLayer* layer, unsigned int newIndex )
00543 {
00544     unsigned int oldIndex = 0;
00545     unsigned int actualIndex = 0;
00546     Revision newRevision;
00547 
00548     if ( layer )
00549     {
00550         Threading::ScopedWriteLock lock( _mapDataMutex );
00551 
00552         // preserve the layer with a ref:
00553         osg::ref_ptr<ImageLayer> layerToMove = layer;
00554 
00555         // find it:
00556         ImageLayerVector::iterator i_oldIndex = _imageLayers.end();
00557         for( ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end(); i++, actualIndex++ )
00558         {
00559             if ( i->get() == layer )
00560             {
00561                 i_oldIndex = i;
00562                 oldIndex = actualIndex;
00563                 break;
00564             }
00565         }
00566 
00567         if ( i_oldIndex == _imageLayers.end() )
00568             return; // layer not found in list
00569 
00570         // erase the old one and insert the new one.
00571         _imageLayers.erase( i_oldIndex );
00572         _imageLayers.insert( _imageLayers.begin() + newIndex, layerToMove.get() );
00573 
00574         newRevision = ++_dataModelRevision;
00575     }
00576 
00577     // a separate block b/c we don't need the mutex
00578     if ( layer )
00579     {
00580         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00581         {
00582             i->get()->onMapModelChanged( MapModelChange(
00583                 MapModelChange::MOVE_IMAGE_LAYER, newRevision, layer, oldIndex, newIndex) );
00584         }
00585     }
00586 }
00587 
00588 void
00589 Map::moveElevationLayer( ElevationLayer* layer, unsigned int newIndex )
00590 {
00591     unsigned int oldIndex = 0;
00592     unsigned int actualIndex = 0;
00593     Revision newRevision;
00594 
00595     if ( layer )
00596     {
00597         Threading::ScopedWriteLock lock( _mapDataMutex );
00598 
00599         // preserve the layer with a ref:
00600         osg::ref_ptr<ElevationLayer> layerToMove = layer;
00601 
00602         // find it:
00603         ElevationLayerVector::iterator i_oldIndex = _elevationLayers.end();
00604         for( ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); i++, actualIndex++ )
00605         {
00606             if ( i->get() == layer )
00607             {
00608                 i_oldIndex = i;
00609                 oldIndex = actualIndex;
00610                 break;
00611             }
00612         }
00613 
00614         if ( i_oldIndex == _elevationLayers.end() )
00615             return; // layer not found in list
00616 
00617         // erase the old one and insert the new one.
00618         _elevationLayers.erase( i_oldIndex );
00619         _elevationLayers.insert( _elevationLayers.begin() + newIndex, layerToMove.get() );
00620 
00621         newRevision = ++_dataModelRevision;
00622     }
00623 
00624     // a separate block b/c we don't need the mutex
00625     if ( layer )
00626     {
00627         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00628         {
00629             i->get()->onMapModelChanged( MapModelChange(
00630                 MapModelChange::MOVE_ELEVATION_LAYER, newRevision, layer, oldIndex, newIndex) );
00631         }
00632     }
00633 }
00634 
00635 void
00636 Map::addModelLayer( ModelLayer* layer )
00637 {
00638     if ( layer )
00639     {
00640         unsigned int index = -1;
00641 
00642         Revision newRevision;
00643         {
00644             Threading::ScopedWriteLock lock( _mapDataMutex );
00645             _modelLayers.push_back( layer );
00646                                                 index = _modelLayers.size() - 1;
00647             newRevision = ++_dataModelRevision;
00648         }
00649 
00650         layer->initialize( _mapOptions.referenceURI().get(), this ); //getReferenceURI(), this );        
00651 
00652         // a seprate block b/c we don't need the mutex
00653         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00654         {
00655             i->get()->onMapModelChanged( MapModelChange(
00656                                                                 MapModelChange::ADD_MODEL_LAYER, newRevision, layer, index ) );
00657         }
00658     }
00659 }
00660 
00661 void
00662 Map::insertModelLayer( ModelLayer* layer, unsigned int index )
00663 {
00664     if ( layer )
00665     {
00666         Revision newRevision;
00667         {
00668             Threading::ScopedWriteLock lock( _mapDataMutex );
00669             _modelLayers.insert( _modelLayers.begin() + index, layer );
00670             newRevision = ++_dataModelRevision;
00671         }
00672 
00673         layer->initialize( _mapOptions.referenceURI().get(), this ); //getReferenceURI(), this );        
00674 
00675         // a seprate block b/c we don't need the mutex
00676         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00677         {
00678             i->get()->onMapModelChanged( MapModelChange(
00679                 MapModelChange::ADD_MODEL_LAYER, newRevision, layer, index) );
00680         }
00681     }
00682 }
00683 
00684 void
00685 Map::removeModelLayer( ModelLayer* layer )
00686 {
00687     if ( layer )
00688     {
00689         //Take a reference to the layer since we will be deleting it
00690         osg::ref_ptr< ModelLayer > layerRef = layer;
00691 
00692         Revision newRevision;
00693         {
00694             Threading::ScopedWriteLock lock( _mapDataMutex );
00695             for( ModelLayerVector::iterator i = _modelLayers.begin(); i != _modelLayers.end(); ++i )
00696             {
00697                 if ( i->get() == layer )
00698                 {
00699                     _modelLayers.erase( i );
00700                     newRevision = ++_dataModelRevision;
00701                     break;
00702                 }
00703             }
00704         }
00705 
00706         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); ++i )
00707         {
00708             i->get()->onMapModelChanged( MapModelChange(
00709                 MapModelChange::REMOVE_MODEL_LAYER, newRevision, layerRef.get()) );
00710         }
00711     }
00712 }
00713 
00714 void
00715 Map::moveModelLayer( ModelLayer* layer, unsigned int newIndex )
00716 {
00717     unsigned int oldIndex = 0;
00718     unsigned int actualIndex = 0;
00719     Revision newRevision;
00720 
00721     if ( layer )
00722     {
00723         Threading::ScopedWriteLock lock( _mapDataMutex );
00724 
00725         // preserve the layer with a ref:
00726         osg::ref_ptr<ModelLayer> layerToMove = layer;
00727 
00728         // find it:
00729         ModelLayerVector::iterator i_oldIndex = _modelLayers.end();
00730         for( ModelLayerVector::iterator i = _modelLayers.begin(); i != _modelLayers.end(); i++, actualIndex++ )
00731         {
00732             if ( i->get() == layer )
00733             {
00734                 i_oldIndex = i;
00735                 oldIndex = actualIndex;
00736                 break;
00737             }
00738         }
00739 
00740         if ( i_oldIndex == _modelLayers.end() )
00741             return; // layer not found in list
00742 
00743         // erase the old one and insert the new one.
00744         _modelLayers.erase( i_oldIndex );
00745         _modelLayers.insert( _modelLayers.begin() + newIndex, layerToMove.get() );
00746 
00747         newRevision = ++_dataModelRevision;
00748     }
00749 
00750     // a separate block b/c we don't need the mutex
00751     if ( layer )
00752     {
00753         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00754         {
00755             i->get()->onMapModelChanged( MapModelChange(
00756                 MapModelChange::MOVE_MODEL_LAYER, newRevision, layer, oldIndex, newIndex) );
00757         }
00758     }
00759 }
00760 
00761 void
00762 Map::addTerrainMaskLayer( MaskLayer* layer )
00763 {
00764     if ( layer )
00765     {
00766         Revision newRevision;
00767         {
00768             Threading::ScopedWriteLock lock( _mapDataMutex );
00769             _terrainMaskLayers.push_back(layer);
00770             newRevision = ++_dataModelRevision;
00771         }
00772 
00773         layer->initialize( _mapOptions.referenceURI().value(), this );
00774 
00775         // a separate block b/c we don't need the mutex   
00776         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00777         {
00778             i->get()->onMapModelChanged( MapModelChange(
00779                 MapModelChange::ADD_MASK_LAYER, newRevision, layer) );
00780         }
00781     }
00782 }
00783 
00784 void
00785 Map::removeTerrainMaskLayer( MaskLayer* layer )
00786 {
00787     if ( layer )
00788     {
00789         //Take a reference to the layer since we will be deleting it
00790         osg::ref_ptr< MaskLayer > layerRef = layer;
00791         Revision newRevision;
00792         {
00793             Threading::ScopedWriteLock lock( _mapDataMutex );
00794             for( MaskLayerVector::iterator i = _terrainMaskLayers.begin(); i != _terrainMaskLayers.end(); ++i )
00795             {
00796                 if ( i->get() == layer )
00797                 {
00798                     _terrainMaskLayers.erase( i );
00799                     newRevision = ++_dataModelRevision;
00800                     break;
00801                 }
00802             }
00803         }
00804         
00805         // a separate block b/c we don't need the mutex   
00806         for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00807         {
00808             i->get()->onMapModelChanged( MapModelChange(
00809                 MapModelChange::REMOVE_MASK_LAYER, newRevision, layerRef.get()) );
00810         }       
00811     }
00812 }
00813 
00814 void
00815 Map::calculateProfile()
00816 {
00817     if ( !_profile.valid() )
00818     {
00819         osg::ref_ptr<const Profile> userProfile;
00820         if ( _mapOptions.profile().isSet() )
00821         {
00822             userProfile = Profile::create( _mapOptions.profile().value() );
00823         }
00824 
00825         if ( _mapOptions.coordSysType() == MapOptions::CSTYPE_GEOCENTRIC )
00826         {
00827             if ( userProfile.valid() )
00828             {
00829                 if ( userProfile->isOK() && userProfile->getSRS()->isGeographic() )
00830                 {
00831                     _profile = userProfile.get();
00832                 }
00833                 else
00834                 {
00835                     OE_WARN << LC 
00836                         << "Map is geocentric, but the configured profile does not "
00837                         << "have a geographic SRS. Falling back on default.."
00838                         << std::endl;
00839                 }
00840             }
00841 
00842             if ( !_profile.valid() )
00843             {
00844                 // by default, set a geocentric map to use global-geodetic WGS84.
00845                 _profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
00846             }
00847         }
00848 
00849         else if ( _mapOptions.coordSysType() == MapOptions::CSTYPE_GEOCENTRIC_CUBE )
00850         {
00851             //If the map type is a Geocentric Cube, set the profile to the cube profile.
00852             _profile = osgEarth::Registry::instance()->getCubeProfile();
00853         }
00854 
00855         else // CSTYPE_PROJECTED
00856         {
00857             if ( userProfile.valid() )
00858             {
00859                 _profile = userProfile.get();
00860             }
00861         }
00862 
00863         // At this point, if we don't have a profile we need to search tile sources until we find one.
00864         if ( !_profile.valid() )
00865         {
00866             Threading::ScopedReadLock lock( _mapDataMutex );
00867 
00868             for( ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end() && !_profile.valid(); i++ )
00869             {
00870                 ImageLayer* layer = i->get();
00871                 if ( layer->getTileSource() )
00872                 {
00873                     _profile = layer->getTileSource()->getProfile();
00874                 }
00875             }
00876 
00877             for( ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end() && !_profile.valid(); i++ )
00878             {
00879                 ElevationLayer* layer = i->get();
00880                 if ( layer->getTileSource() )
00881                 {
00882                     _profile = layer->getTileSource()->getProfile();
00883                 }
00884             }
00885         }
00886 
00887         // finally, fire an event if the profile has been set.
00888         if ( _profile.valid() )
00889         {
00890             OE_INFO << LC << "Map profile is: " << _profile->toString() << std::endl;
00891 
00892             for( MapCallbackList::iterator i = _mapCallbacks.begin(); i != _mapCallbacks.end(); i++ )
00893             {
00894                 i->get()->onMapInfoEstablished( MapInfo(this) );
00895             }
00896         }
00897 
00898         else
00899         {
00900             OE_WARN << LC << "Warning, not yet able to establish a map profile!" << std::endl;
00901         }
00902     }
00903 
00904     if ( _profile.valid() )
00905     {
00906         // tell all the loaded layers what the profile is, as a hint
00907         {
00908             Threading::ScopedWriteLock lock( _mapDataMutex );
00909 
00910             for( ImageLayerVector::iterator i = _imageLayers.begin(); i != _imageLayers.end(); i++ )
00911             {
00912                 ImageLayer* layer = i->get();
00913                 layer->setTargetProfileHint( _profile.get() );
00914             }
00915 
00916             for( ElevationLayerVector::iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); i++ )
00917             {
00918                 ElevationLayer* layer = i->get();
00919                 layer->setTargetProfileHint( _profile.get() );
00920             }
00921         }
00922     }
00923 }
00924 
00925 namespace
00926 {
00927     bool
00928     s_getHeightField(const TileKey& key,
00929                      const ElevationLayerVector& elevLayers,
00930                      const Profile* mapProfile,
00931                      bool fallback,
00932                      ElevationInterpolation interpolation,
00933                      ElevationSamplePolicy samplePolicy,
00934                      osg::ref_ptr<osg::HeightField>& out_result,
00935                      bool* out_isFallback,
00936                      ProgressCallback* progress) 
00937     {
00938         unsigned int lowestLOD = key.getLevelOfDetail();
00939         bool hfInitialized = false;
00940 
00941         typedef std::map< TerrainLayer*, bool > LayerValidMap;
00942         LayerValidMap layerValidMap;
00943 
00944             //Get a HeightField for each of the enabled layers
00945             GeoHeightFieldVector heightFields;
00946 
00947         unsigned int numValidHeightFields = 0;
00948 
00949         if ( out_isFallback )
00950         {
00951             *out_isFallback = false;
00952         }
00953         
00954         //First pass:  Try to get the exact LOD requested for each enabled heightfield
00955         for( ElevationLayerVector::const_iterator i = elevLayers.begin(); i != elevLayers.end(); i++ )
00956         {
00957             ElevationLayer* layer = i->get();
00958             if (layer->getProfile() && layer->getEnabled() )
00959             {
00960                 osg::HeightField* hf = layer->createHeightField( key, progress );
00961                 layerValidMap[ layer ] = (hf != 0L);
00962                 if ( hf )                {
00963                     numValidHeightFields++;
00964                     GeoHeightField ghf( hf, key.getExtent(), layer->getProfile()->getVerticalSRS() );
00965                     heightFields.push_back( ghf );
00966                 }
00967             }
00968         }
00969 
00970         //If we didn't get any heightfields and weren't requested to fallback, just return NULL
00971         if (numValidHeightFields == 0 && !fallback)
00972         {
00973             return false;
00974         }
00975 
00976         //Second pass:  We were either asked to fallback or we might have some heightfields at the requested
00977         //              LOD and some that are NULL. Fall back on parent tiles to fill in the missing data if possible.
00978         for( ElevationLayerVector::const_iterator i = elevLayers.begin(); i != elevLayers.end(); i++ )
00979         {
00980             ElevationLayer* layer = i->get();
00981 
00982             if (layer->getProfile() && layer->getEnabled() )
00983             {
00984                 if (!layerValidMap[ layer ])
00985                 {
00986                     TileKey hf_key = key;
00987                     osg::ref_ptr< osg::HeightField > hf;
00988                     while (hf_key.valid())
00989                     {
00990                         hf = layer->createHeightField( hf_key, progress );
00991                         if ( hf.valid() )
00992                             break;
00993 
00994                         hf_key = hf_key.createParentKey();
00995                     }
00996 
00997                     if (hf.valid())
00998                     {
00999                         if ( hf_key.getLevelOfDetail() < lowestLOD )
01000                             lowestLOD = hf_key.getLevelOfDetail();
01001 
01002                         heightFields.push_back( GeoHeightField(
01003                             hf.get(), hf_key.getExtent(), layer->getProfile()->getVerticalSRS() ) );
01004 
01005                         if ( out_isFallback )
01006                             *out_isFallback = true;
01007 
01008                     }
01009                 }
01010             }
01011         }
01012 
01013             if (heightFields.size() == 0)
01014             {
01015                 //If we got no heightfields, return NULL
01016                     return false;
01017             }
01018 
01019             else if (heightFields.size() == 1)
01020             {
01021             if ( lowestLOD == key.getLevelOfDetail() )
01022             {
01023                         //If we only have on heightfield, just return it.
01024                         out_result = heightFields[0].takeHeightField();
01025             }
01026             else
01027             {
01028                 GeoHeightField geoHF = heightFields[0].createSubSample( key.getExtent(), interpolation);
01029                 out_result = geoHF.takeHeightField();
01030                 hfInitialized = true;
01031             }
01032             }
01033 
01034             else
01035             {
01036                     //If we have multiple heightfields, we need to composite them together.
01037                     unsigned int width = 0;
01038                     unsigned int height = 0;
01039 
01040                     for (GeoHeightFieldVector::const_iterator i = heightFields.begin(); i < heightFields.end(); ++i)
01041                     {
01042                             if (i->getHeightField()->getNumColumns() > width) 
01043                     width = i->getHeightField()->getNumColumns();
01044                             if (i->getHeightField()->getNumRows() > height) 
01045                     height = i->getHeightField()->getNumRows();
01046                     }
01047                     out_result = new osg::HeightField();
01048                     out_result->allocate( width, height );
01049 
01050                     //Go ahead and set up the heightfield so we don't have to worry about it later
01051             double minx, miny, maxx, maxy;
01052             key.getExtent().getBounds(minx, miny, maxx, maxy);
01053             double dx = (maxx - minx)/(double)(out_result->getNumColumns()-1);
01054             double dy = (maxy - miny)/(double)(out_result->getNumRows()-1);
01055 
01056             const VerticalSpatialReference* vsrs = mapProfile->getVerticalSRS();
01057             
01058                     //Create the new heightfield by sampling all of them.
01059             for (unsigned int c = 0; c < width; ++c)
01060             {
01061                 double geoX = minx + (dx * (double)c);
01062                 for (unsigned r = 0; r < height; ++r)
01063                 {
01064                     double geoY = miny + (dy * (double)r);
01065 
01066                     //Collect elevations from all of the layers
01067                     std::vector<float> elevations;
01068                     for (GeoHeightFieldVector::iterator itr = heightFields.begin(); itr != heightFields.end(); ++itr)
01069                     {
01070                         const GeoHeightField& geoHF = *itr;
01071 
01072                         float elevation = 0.0f;
01073                         if ( geoHF.getElevation(key.getExtent().getSRS(), geoX, geoY, interpolation, vsrs, elevation) )
01074                         {
01075                             if (elevation != NO_DATA_VALUE)
01076                             {
01077                                 elevations.push_back(elevation);
01078                             }
01079                         }
01080                     }
01081 
01082                     float elevation = NO_DATA_VALUE;
01083 
01084                     //The list of elevations only contains valid values
01085                     if (elevations.size() > 0)
01086                     {
01087                         if (samplePolicy == SAMPLE_FIRST_VALID)
01088                         {
01089                             elevation = elevations[0];
01090                         }
01091                         else if (samplePolicy == SAMPLE_HIGHEST)
01092                         {
01093                             elevation = -FLT_MAX;
01094                             for (unsigned int i = 0; i < elevations.size(); ++i)
01095                             {
01096                                 if (elevation < elevations[i]) elevation = elevations[i];
01097                             }
01098                         }
01099                         else if (samplePolicy == SAMPLE_LOWEST)
01100                         {
01101                             elevation = FLT_MAX;
01102                             for (unsigned i = 0; i < elevations.size(); ++i)
01103                             {
01104                                 if (elevation > elevations[i]) elevation = elevations[i];
01105                             }
01106                         }
01107                         else if (samplePolicy == SAMPLE_AVERAGE)
01108                         {
01109                             elevation = 0.0;
01110                             for (unsigned i = 0; i < elevations.size(); ++i)
01111                             {
01112                                 elevation += elevations[i];
01113                             }
01114                             elevation /= (float)elevations.size();
01115                         }
01116                     }
01117                     out_result->setHeight(c, r, elevation);
01118                 }
01119             }
01120             }
01121 
01122             //Replace any NoData areas with 0
01123             if (out_result.valid())
01124             {
01125                     ReplaceInvalidDataOperator o;
01126                     o.setValidDataOperator(new osgTerrain::NoDataValue(NO_DATA_VALUE));
01127                     o( out_result.get() );
01128             }
01129 
01130             //Initialize the HF values for osgTerrain
01131             if (out_result.valid() && !hfInitialized )
01132             {   
01133                     //Go ahead and set up the heightfield so we don't have to worry about it later
01134                     double minx, miny, maxx, maxy;
01135                     key.getExtent().getBounds(minx, miny, maxx, maxy);
01136                     out_result->setOrigin( osg::Vec3d( minx, miny, 0.0 ) );
01137                     double dx = (maxx - minx)/(double)(out_result->getNumColumns()-1);
01138                     double dy = (maxy - miny)/(double)(out_result->getNumRows()-1);
01139                     out_result->setXInterval( dx );
01140                     out_result->setYInterval( dy );
01141                     out_result->setBorderWidth( 0 );
01142             }
01143 
01144             return out_result.valid();
01145     }
01146 }
01147 
01148 
01149 bool
01150 Map::getHeightField(const TileKey& key,
01151                     bool fallback,
01152                     osg::ref_ptr<osg::HeightField>& out_result,
01153                     bool* out_isFallback,
01154                     ElevationInterpolation interpolation,
01155                     ElevationSamplePolicy samplePolicy,
01156                     ProgressCallback* progress) const
01157 {
01158     Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
01159 
01160     return s_getHeightField(
01161         key, _elevationLayers, getProfile(), fallback, 
01162         interpolation, samplePolicy, 
01163         out_result, out_isFallback,
01164         progress );
01165 }
01166 
01167 bool
01168 Map::sync( MapFrame& frame ) const
01169 {
01170     bool result = false;
01171 
01172     if ( frame._mapDataModelRevision != _dataModelRevision || !frame._initialized )
01173     {
01174         // hold the read lock while copying the layer lists.
01175         Threading::ScopedReadLock lock( const_cast<Map*>(this)->_mapDataMutex );
01176 
01177         if ( frame._parts & IMAGE_LAYERS )
01178         {
01179             if ( !frame._initialized )
01180                 frame._imageLayers.reserve( _imageLayers.size() );
01181             frame._imageLayers.clear();
01182             if ( frame._copyValidDataOnly )
01183             {
01184                 for( ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
01185                     if ( i->get()->getProfile() )
01186                         frame._imageLayers.push_back( i->get() );
01187             }
01188             else
01189                 std::copy( _imageLayers.begin(), _imageLayers.end(), std::back_inserter(frame._imageLayers) );
01190         }
01191 
01192         if ( frame._parts & ELEVATION_LAYERS )
01193         {
01194             if ( !frame._initialized )
01195                 frame._elevationLayers.reserve( _elevationLayers.size() );
01196             frame._elevationLayers.clear();
01197             if ( frame._copyValidDataOnly )
01198             {
01199                 for( ElevationLayerVector::const_iterator i = _elevationLayers.begin(); i != _elevationLayers.end(); ++i )
01200                     if ( i->get()->getProfile() )
01201                         frame._elevationLayers.push_back( i->get() );
01202             }
01203             else
01204                 std::copy( _elevationLayers.begin(), _elevationLayers.end(), std::back_inserter(frame._elevationLayers) );
01205         }
01206 
01207         if ( frame._parts & MODEL_LAYERS )
01208         {
01209             if ( !frame._initialized )
01210                 frame._modelLayers.reserve( _modelLayers.size() );
01211             frame._modelLayers.clear();
01212             std::copy( _modelLayers.begin(), _modelLayers.end(), std::back_inserter(frame._modelLayers) );
01213         }
01214 
01215         if ( frame._parts & MASK_LAYERS )
01216         {
01217           if ( !frame._initialized )
01218               frame._maskLayers.reserve( _terrainMaskLayers.size() );
01219           frame._maskLayers.clear();
01220           std::copy( _terrainMaskLayers.begin(), _terrainMaskLayers.end(), std::back_inserter(frame._maskLayers) );
01221         }
01222 
01223         // sync the revision numbers.
01224         frame._initialized = true;
01225         frame._mapDataModelRevision = _dataModelRevision;
01226             
01227         result = true;
01228     }    
01229     return result;
01230 }
01231 
01232 bool
01233 Map::toMapPoint( const osg::Vec3d& input, const SpatialReference* inputSRS, osg::Vec3d& output ) const
01234 {
01235     return MapInfo(this).toMapPoint(input, inputSRS, output);
01236 }
01237 
01238 bool
01239 Map::mapPointToWorldPoint( const osg::Vec3d& input, osg::Vec3d& output ) const
01240 {
01241     return MapInfo(this).mapPointToWorldPoint(input, output);
01242 }
01243 
01244 bool
01245 Map::worldPointToMapPoint( const osg::Vec3d& input, osg::Vec3d& output ) const
01246 {
01247     return MapInfo(this).worldPointToMapPoint(input, output);
01248 }
01249 
01250 //------------------------------------------------------------------------
01251 
01252 bool
01253 MapInfo::toMapPoint( const osg::Vec3d& input, const SpatialReference* inputSRS, osg::Vec3d& output ) const
01254 {
01255     if ( !inputSRS )
01256         return false;
01257 
01258     const SpatialReference* mapSRS = _profile->getSRS();
01259 
01260     if ( inputSRS->isEquivalentTo( mapSRS ) )
01261     {
01262         output = input;
01263         return true;
01264     }
01265 
01266     return inputSRS->transform(
01267         input.x(), input.y(), input.z(),
01268         mapSRS,
01269         output.x(), output.y(), output.z() );
01270 }
01271 
01272 bool
01273 MapInfo::mapPointToWorldPoint( const osg::Vec3d& input, osg::Vec3d& output ) const
01274 {
01275     if ( _isGeocentric )
01276     {
01277         _profile->getSRS()->getEllipsoid()->convertLatLongHeightToXYZ(
01278             osg::DegreesToRadians( input.y() ), osg::DegreesToRadians( input.x() ), input.z(),
01279             output.x(), output.y(), output.z() );
01280     }
01281     else
01282     {
01283         output = input;
01284     }
01285     return true;
01286 }
01287 
01288 bool
01289 MapInfo::worldPointToMapPoint( const osg::Vec3d& input, osg::Vec3d& output ) const
01290 {
01291     if ( _isGeocentric )
01292     { 
01293         _profile->getSRS()->getEllipsoid()->convertXYZToLatLongHeight(
01294             input.x(), input.y(), input.z(),
01295             output.y(), output.x(), output.z() );
01296 
01297         output.y() = osg::RadiansToDegrees(output.y());
01298         output.x() = osg::RadiansToDegrees(output.x());
01299     }
01300     else
01301     {
01302         output = input;
01303     }
01304     return true;
01305 }
01306 
01307 //------------------------------------------------------------------------
01308 
01309 MapFrame::MapFrame( const Map* map, Map::ModelParts parts, const std::string& name ) :
01310 _initialized( false ),
01311 _map( map ),
01312 _name( name ),
01313 _mapInfo( map ),
01314 _parts( parts ),
01315 _copyValidDataOnly( false )
01316 {
01317     sync();
01318 }
01319 
01320 MapFrame::MapFrame( const Map* map, bool copyValidDataOnly, Map::ModelParts parts, const std::string& name ) :
01321 _initialized( false ),
01322 _map( map ),
01323 _name( name ),
01324 _mapInfo( map ),
01325 _parts( parts ),
01326 _copyValidDataOnly( copyValidDataOnly )
01327 {
01328     sync();
01329 }
01330 
01331 MapFrame::MapFrame( const MapFrame& src, const std::string& name ) :
01332 _initialized( src._initialized ),
01333 _map( src._map.get() ),
01334 _name( name ),
01335 _mapInfo( src._mapInfo ), // src._map.get() ),
01336 _parts( src._parts ),
01337 _copyValidDataOnly( src._copyValidDataOnly ),
01338 _mapDataModelRevision( src._mapDataModelRevision ),
01339 _imageLayers( src._imageLayers ),
01340 _elevationLayers( src._elevationLayers ),
01341 _modelLayers( src._modelLayers ),
01342 _maskLayers( src._maskLayers )
01343 {
01344     //no sync required here; we copied the arrays etc
01345 }
01346 
01347 bool
01348 MapFrame::sync()
01349 {
01350     return _map->sync( *this );
01351 }
01352 
01353 bool
01354 MapFrame::getHeightField(const TileKey& key,
01355                             bool fallback,
01356                             osg::ref_ptr<osg::HeightField>& out_hf,
01357                             bool* out_isFallback,
01358                             ElevationInterpolation interpolation,
01359                             ElevationSamplePolicy samplePolicy,
01360                             ProgressCallback* progress) const
01361 {
01362     return s_getHeightField( key, _elevationLayers, _mapInfo.getProfile(), fallback, interpolation, samplePolicy, out_hf, out_isFallback, progress );
01363 }
01364 
01365 int
01366 MapFrame::indexOf( ImageLayer* layer ) const
01367 {
01368     ImageLayerVector::const_iterator i = std::find( _imageLayers.begin(), _imageLayers.end(), layer );
01369     return i != _imageLayers.end() ? i - _imageLayers.begin() : -1;
01370 }
01371 
01372 int
01373 MapFrame::indexOf( ElevationLayer* layer ) const
01374 {
01375     ElevationLayerVector::const_iterator i = std::find( _elevationLayers.begin(), _elevationLayers.end(), layer );
01376     return i != _elevationLayers.end() ? i - _elevationLayers.begin() : -1;
01377 }
01378 
01379 int
01380 MapFrame::indexOf( ModelLayer* layer ) const
01381 {
01382     ModelLayerVector::const_iterator i = std::find( _modelLayers.begin(), _modelLayers.end(), layer );
01383     return i != _modelLayers.end() ? i - _modelLayers.begin() : -1;
01384 }
01385 
01386 ImageLayer*
01387 MapFrame::getImageLayerByUID( UID uid ) const
01388 {
01389     for(ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
01390         if ( i->get()->getUID() == uid )
01391             return i->get();
01392     return 0L;
01393 }
01394 
01395 ImageLayer*
01396 MapFrame::getImageLayerByName( const std::string& name ) const
01397 {
01398     for(ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
01399         if ( i->get()->getName() == name )
01400             return i->get();
01401     return 0L;
01402 }
01403 
01404 bool
01405 MapFrame::isCached( const osgEarth::TileKey& key ) const
01406 {
01407     const Profile* mapProfile = getProfile();
01408 
01409     //Check the imagery layers
01410     for( ImageLayerVector::const_iterator i = imageLayers().begin(); i != imageLayers().end(); i++ )
01411     {
01412         ImageLayer* layer = i->get();
01413         osg::ref_ptr< Cache > cache = layer->getCache();
01414 
01415         if ( !cache.valid() || !layer->getProfile() ) 
01416             return false;
01417 
01418         std::vector< TileKey > keys;
01419 
01420         if ( mapProfile->isEquivalentTo( layer->getProfile() ) )
01421         {
01422             keys.push_back( key );
01423         }
01424         else
01425         {
01426             layer->getProfile()->getIntersectingTiles( key, keys );
01427         }
01428 
01429         for (unsigned int j = 0; j < keys.size(); ++j)
01430         {
01431             if ( layer->isKeyValid( keys[j] ) )
01432             {
01433                 if ( !cache->isCached( keys[j], layer->getCacheSpec() ) )
01434                 {
01435                     return false;
01436                 }
01437             }
01438         }
01439     }
01440 
01441     for( ElevationLayerVector::const_iterator i = elevationLayers().begin(); i != elevationLayers().end(); ++i )
01442     {
01443         ElevationLayer* layer = i->get();
01444         osg::ref_ptr< Cache > cache = layer->getCache();
01445 
01446         if ( !cache.valid() || !layer->getProfile() )
01447             return false;
01448 
01449         std::vector<TileKey> keys;
01450 
01451         if ( mapProfile->isEquivalentTo( layer->getProfile() ) )
01452         {
01453             keys.push_back( key );
01454         }
01455         else
01456         {
01457             layer->getProfile()->getIntersectingTiles( key, keys );
01458         }
01459 
01460         for (unsigned int j = 0; j < keys.size(); ++j)
01461         {
01462             if ( layer->isKeyValid( keys[j] ) )
01463             {
01464                 if ( !cache->isCached( keys[j], layer->getCacheSpec() ) )
01465                 {
01466                     return false;
01467                 }
01468             }
01469         }
01470     }
01471     return true;
01472 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines