osgEarth 2.1.1
|
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 }