void CacheSeed::seed( Map* map ) { if ( !map->getCache() ) { OE_WARN << LC << "Warning: No cache defined; aborting." << std::endl; return; } std::vector<TileKey> keys; map->getProfile()->getRootKeys(keys); //Add the map's entire extent if we don't have one specified. if (_extents.empty()) { addExtent( map->getProfile()->getExtent() ); } bool hasCaches = false; int src_min_level = INT_MAX; unsigned int src_max_level = 0; MapFrame mapf( map, Map::TERRAIN_LAYERS, "CacheSeed::seed" ); //Assumes the the TileSource will perform the caching for us when we call createImage for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); i++ ) { ImageLayer* layer = i->get(); TileSource* src = layer->getTileSource(); const ImageLayerOptions& opt = layer->getImageLayerOptions(); if ( layer->isCacheOnly() ) { OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl; } else if ( !src ) { OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl; } //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE ) //{ // OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl; //} else if ( !layer->getCache() ) { OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl; } else { hasCaches = true; if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level) src_min_level = opt.minLevel().get(); if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level) src_max_level = opt.maxLevel().get(); } } for( ElevationLayerVector::const_iterator i = mapf.elevationLayers().begin(); i != mapf.elevationLayers().end(); i++ ) { ElevationLayer* layer = i->get(); TileSource* src = layer->getTileSource(); const ElevationLayerOptions& opt = layer->getElevationLayerOptions(); if ( layer->isCacheOnly() ) { OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl; } else if (!src) { OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl; } //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE ) //{ // OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl; //} else if ( !layer->getCache() ) { OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl; } else { hasCaches = true; if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level) src_min_level = opt.minLevel().get(); if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level) src_max_level = opt.maxLevel().get(); } } if ( !hasCaches ) { OE_WARN << LC << "There are either no caches defined in the map, or no sources to cache; aborting." << std::endl; return; } if ( src_max_level > 0 && src_max_level < _maxLevel ) { _maxLevel = src_max_level; } OE_NOTICE << LC << "Maximum cache level will be " << _maxLevel << std::endl; //Estimate the number of tiles _total = 0; CacheEstimator est; est.setMinLevel( _minLevel ); est.setMaxLevel( _maxLevel ); est.setProfile( map->getProfile() ); for (unsigned int i = 0; i < _extents.size(); i++) { est.addExtent( _extents[ i ] ); } _total = est.getNumTiles(); OE_INFO << "Processing ~" << _total << " tiles" << std::endl; for (unsigned int i = 0; i < keys.size(); ++i) { processKey( mapf, keys[i] ); } _total = _completed; if ( _progress.valid()) _progress->reportProgress(_completed, _total, 0, 1, "Finished"); }
void CacheSeed::seed( Map* map ) { // We must do this to avoid an error message in OpenSceneGraph b/c the findWrapper method doesn't appear to be threadsafe. // This really isn't a big deal b/c this only effects data that is already cached. osgDB::ObjectWrapper* wrapper = osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper( "osg::Image" ); osg::Timer_t startTime = osg::Timer::instance()->tick(); if ( !map->getCache() ) { OE_WARN << LC << "Warning: No cache defined; aborting." << std::endl; return; } std::vector<TileKey> keys; map->getProfile()->getRootKeys(keys); //Add the map's entire extent if we don't have one specified. if (_extents.empty()) { addExtent( map->getProfile()->getExtent() ); } bool hasCaches = false; int src_min_level = INT_MAX; unsigned int src_max_level = 0; MapFrame mapf( map, Map::TERRAIN_LAYERS, "CacheSeed::seed" ); //Assumes the the TileSource will perform the caching for us when we call createImage for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); i++ ) { ImageLayer* layer = i->get(); TileSource* src = layer->getTileSource(); const ImageLayerOptions& opt = layer->getImageLayerOptions(); if ( layer->isCacheOnly() ) { OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl; } else if ( !src ) { OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl; } //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE ) //{ // OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl; //} else if ( !layer->getCache() ) { OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl; } else { hasCaches = true; if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level) src_min_level = opt.minLevel().get(); if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level) src_max_level = opt.maxLevel().get(); } } for( ElevationLayerVector::const_iterator i = mapf.elevationLayers().begin(); i != mapf.elevationLayers().end(); i++ ) { ElevationLayer* layer = i->get(); TileSource* src = layer->getTileSource(); const ElevationLayerOptions& opt = layer->getElevationLayerOptions(); if ( layer->isCacheOnly() ) { OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl; } else if (!src) { OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl; } //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE ) //{ // OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl; //} else if ( !layer->getCache() ) { OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl; } else { hasCaches = true; if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level) src_min_level = opt.minLevel().get(); if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level) src_max_level = opt.maxLevel().get(); } } if ( !hasCaches ) { OE_WARN << LC << "There are either no caches defined in the map, or no sources to cache; aborting." << std::endl; return; } if ( src_max_level > 0 && src_max_level < _maxLevel ) { _maxLevel = src_max_level; } OE_NOTICE << LC << "Maximum cache level will be " << _maxLevel << std::endl; //Estimate the number of tiles _total = 0; CacheEstimator est; est.setMinLevel( _minLevel ); est.setMaxLevel( _maxLevel ); est.setProfile( map->getProfile() ); for (unsigned int i = 0; i < _extents.size(); i++) { est.addExtent( _extents[ i ] ); } _total = est.getNumTiles(); OE_INFO << "Processing ~" << _total << " tiles" << std::endl; // Initialize the operations queue _queue = new osg::OperationQueue; osg::Timer_t endTime = osg::Timer::instance()->tick(); // Start the threads std::vector< osg::ref_ptr< osg::OperationsThread > > threads; for (unsigned int i = 0; i < _numThreads; i++) { osg::OperationsThread* thread = new osg::OperationsThread(); thread->setOperationQueue(_queue.get()); thread->start(); threads.push_back( thread ); } OE_NOTICE << "Startup time " << osg::Timer::instance()->delta_s( startTime, endTime ) << std::endl; // Add the root keys to the queue for (unsigned int i = 0; i < keys.size(); ++i) { //processKey( mapf, keys[i] ); _queue.get()->add( new CacheTileOperation( mapf, *this, keys[i]) ); } bool done = false; while (!done) { OpenThreads::Thread::microSleep(500000); // sleep for half a second done = true; if (_queue->getNumOperationsInQueue() > 0) { done = false; continue; } else { // Make sure no threads are currently working on an operation, which actually might add MORE operations since we are doing a quadtree traversal for (unsigned int i = 0; i < threads.size(); i++) { if (threads[i]->getCurrentOperation()) { done = false; continue; } } } } _total = _completed; if ( _progress.valid()) _progress->reportProgress(_completed, _total, 0, 1, "Finished"); }
void CacheSeed::seed( Map* map ) { if ( !map->getCache() ) { OE_WARN << LC << "Warning: No cache defined; aborting." << std::endl; return; } std::vector<TileKey> keys; map->getProfile()->getRootKeys(keys); //Add the map's entire extent if we don't have one specified. if (_extents.empty()) { addExtent( map->getProfile()->getExtent() ); } bool hasCaches = false; int src_min_level = INT_MAX; unsigned int src_max_level = 0; MapFrame mapf( map, Map::TERRAIN_LAYERS, "CacheSeed::seed" ); //Assumes the the TileSource will perform the caching for us when we call createImage for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); i++ ) { ImageLayer* layer = i->get(); TileSource* src = layer->getTileSource(); const ImageLayerOptions& opt = layer->getImageLayerOptions(); if ( layer->isCacheOnly() ) { OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl; } else if ( !src ) { OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl; } //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE ) //{ // OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl; //} else if ( !layer->getCache() ) { OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl; } else { hasCaches = true; if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level) src_min_level = opt.minLevel().get(); if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level) src_max_level = opt.maxLevel().get(); } } for( ElevationLayerVector::const_iterator i = mapf.elevationLayers().begin(); i != mapf.elevationLayers().end(); i++ ) { ElevationLayer* layer = i->get(); TileSource* src = layer->getTileSource(); const ElevationLayerOptions& opt = layer->getElevationLayerOptions(); if ( layer->isCacheOnly() ) { OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" is set to cache-only; skipping." << std::endl; } else if (!src) { OE_WARN << "Warning: Layer \"" << layer->getName() << "\" could not create TileSource; skipping." << std::endl; } //else if ( src->getCachePolicyHint(0L) == CachePolicy::NO_CACHE ) //{ // OE_WARN << LC << "Warning: Layer \"" << layer->getName() << "\" does not support seeding; skipping." << std::endl; //} else if ( !layer->getCache() ) { OE_WARN << LC << "Notice: Layer \"" << layer->getName() << "\" has no cache defined; skipping." << std::endl; } else { hasCaches = true; if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level) src_min_level = opt.minLevel().get(); if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level) src_max_level = opt.maxLevel().get(); } } if ( !hasCaches ) { OE_WARN << LC << "There are either no caches defined in the map, or no sources to cache; aborting." << std::endl; return; } if ( src_max_level > 0 && src_max_level < _maxLevel ) { _maxLevel = src_max_level; } OE_NOTICE << LC << "Maximum cache level will be " << _maxLevel << std::endl; osg::Timer_t startTime = osg::Timer::instance()->tick(); //Estimate the number of tiles _total = 0; for (unsigned int level = _minLevel; level <= _maxLevel; level++) { double coverageRatio = 0.0; if (_extents.empty()) { unsigned int wide, high; map->getProfile()->getNumTiles( level, wide, high ); _total += (wide * high); } else { for (std::vector< GeoExtent >::const_iterator itr = _extents.begin(); itr != _extents.end(); itr++) { const GeoExtent& extent = *itr; double boundsArea = extent.area(); TileKey ll = map->getProfile()->createTileKey(extent.xMin(), extent.yMin(), level); TileKey ur = map->getProfile()->createTileKey(extent.xMax(), extent.yMax(), level); if (!ll.valid() || !ur.valid()) continue; int tilesWide = ur.getTileX() - ll.getTileX() + 1; int tilesHigh = ll.getTileY() - ur.getTileY() + 1; int tilesAtLevel = tilesWide * tilesHigh; //OE_NOTICE << "Tiles at level " << level << "=" << tilesAtLevel << std::endl; /* bool hasData = false; for (ImageLayerVector::const_iterator itr = mapf.imageLayers().begin(); itr != mapf.imageLayers().end(); itr++) { TileSource* src = itr->get()->getTileSource(); if (src) { if (src->hasDataAtLOD( level )) { //Compute the percent coverage of this dataset on the current extent if (src->getDataExtents().size() > 0) { double cov = 0.0; for (unsigned int j = 0; j < src->getDataExtents().size(); j++) { GeoExtent b = src->getDataExtents()[j].transform( extent.getSRS()); GeoExtent intersection = b.intersectionSameSRS( extent ); if (intersection.isValid()) { double coverage = intersection.area() / boundsArea; cov += coverage; //Assumes the extents aren't overlapping } } if (coverageRatio < cov) coverageRatio = cov; } else { //We have no way of knowing how much coverage we have coverageRatio = 1.0; } hasData = true; break; } } } for (ElevationLayerVector::const_iterator itr = mapf.elevationLayers().begin(); itr != mapf.elevationLayers().end(); itr++) { TileSource* src = itr->get()->getTileSource(); if (src) { if (src->hasDataAtLOD( level )) { //Compute the percent coverage of this dataset on the current extent if (src->getDataExtents().size() > 0) { double cov = 0.0; for (unsigned int j = 0; j < src->getDataExtents().size(); j++) { GeoExtent b = src->getDataExtents()[j].transform( extent.getSRS()); GeoExtent intersection = b.intersectionSameSRS( extent ); if (intersection.isValid()) { double coverage = intersection.area() / boundsArea; cov += coverage; //Assumes the extents aren't overlapping } } if (coverageRatio < cov) coverageRatio = cov; } else { //We have no way of knowing how much coverage we have coverageRatio = 1.0; } hasData = true; break; } } } //Adjust the coverage ratio by a fudge factor to try to keep it from being too small, //tiles are either processed or not and the ratio is exact so will cover tiles partially //and potentially be too small double adjust = 4.0; coverageRatio = osg::clampBetween(coverageRatio * adjust, 0.0, 1.0); //OE_NOTICE << level << " CoverageRatio = " << coverageRatio << std::endl; if (hasData) { _total += (int)ceil(coverageRatio * (double)tilesAtLevel ); } */ _total += tilesAtLevel; } } } osg::Timer_t endTime = osg::Timer::instance()->tick(); //OE_NOTICE << "Counted tiles in " << osg::Timer::instance()->delta_s(startTime, endTime) << " s" << std::endl; OE_INFO << "Processing ~" << _total << " tiles" << std::endl; for (unsigned int i = 0; i < keys.size(); ++i) { processKey( mapf, keys[i] ); } _total = _completed; if ( _progress.valid()) _progress->reportProgress(_completed, _total, 0, 1, "Finished"); }