int purge( osg::ArgumentParser& args ) { osg::ref_ptr<osg::Node> node = osgDB::readNodeFiles( args ); if ( !node.valid() ) return usage( "Failed to read .earth file." ); MapNode* mapNode = MapNode::findMapNode( node.get() ); if ( !mapNode ) return usage( "Input file was not a .earth file" ); Map* map = mapNode->getMap(); if ( !map->getCache() ) return message( "Earth file does not contain a cache." ); std::vector<Entry> entries; ImageLayerVector imageLayers; map->getLayers( imageLayers ); for( ImageLayerVector::const_iterator i = imageLayers.begin(); i != imageLayers.end(); ++i ) { ImageLayer* layer = i->get(); bool useMFP = layer->getProfile() && layer->getProfile()->getSRS()->isSphericalMercator() && mapNode->getMapNodeOptions().getTerrainOptions().enableMercatorFastPath() == true; const Profile* cacheProfile = useMFP ? layer->getProfile() : map->getProfile(); CacheSettings* cacheSettings = layer->getCacheSettings(); if (cacheSettings) { CacheBin* bin = cacheSettings->getCacheBin(); if ( bin ) { entries.push_back(Entry()); entries.back()._isImage = true; entries.back()._name = i->get()->getName(); entries.back()._bin = bin; } } } ElevationLayerVector elevationLayers; map->getLayers( elevationLayers ); for( ElevationLayerVector::const_iterator i = elevationLayers.begin(); i != elevationLayers.end(); ++i ) { ElevationLayer* layer = i->get(); bool useMFP = layer->getProfile() && layer->getProfile()->getSRS()->isSphericalMercator() && mapNode->getMapNodeOptions().getTerrainOptions().enableMercatorFastPath() == true; const Profile* cacheProfile = useMFP ? layer->getProfile() : map->getProfile(); CacheSettings* cacheSettings = layer->getCacheSettings(); if (cacheSettings) { CacheBin* bin = cacheSettings->getCacheBin(); if (bin) { entries.push_back(Entry()); entries.back()._isImage = false; entries.back()._name = i->get()->getName(); entries.back()._bin = bin; } } } if ( entries.size() > 0 ) { std::cout << std::endl; for( unsigned i=0; i<entries.size(); ++i ) { std::cout << (i+1) << ") " << entries[i]._name << " (" << (entries[i]._isImage? "image" : "elevation" ) << ")" << std::endl; } std::cout << std::endl << "Enter number of cache to purge, or <enter> to quit: " << std::flush; std::string input; std::getline( std::cin, input ); if ( !input.empty() ) { unsigned k = as<unsigned>(input, 0L); if ( k > 0 && k <= entries.size() ) { Config meta = entries[k-1]._bin->readMetadata(); if ( !meta.empty() ) { std::cout << std::endl << "Cache METADATA:" << std::endl << meta.toJSON() << std::endl << std::endl; } std::cout << "Are you sure (y/N)? " << std::flush; std::getline( std::cin, input ); if ( input == "y" || input == "Y" ) { std::cout << "Purging.." << std::flush; entries[k-1]._bin->clear(); } else { std::cout << "No action taken." << std::endl; } } else { std::cout << "Invalid choice." << std::endl; } } else { std::cout << "No action taken." << std::endl; } } return 0; }
/** * Command-line tool that copies the contents of one TileSource * to another. All arguments are Config name/value pairs, so you need * to look in the header file for each driver's Options structure for * options :) * * Example: copy a GDAL file to an MBTiles repo: * * osgearth_conv * --in driver gdal * --in url world.tif * --out driver mbtiles * --out filename world.db * * The "in" properties come from the GDALOptions getConfig method. The * "out" properties come from the MBTilesOptions getConfig method. * * Other arguments: * * --elevation : convert as elevation data (instead of image data) * --profile [profile] : reproject to the target profile, e.g. "wgs84" * --min-level [int] : min level of detail to copy * --max-level [int] : max level of detail to copy * --threads [n] : threads to use (may crash. Careful.) * * --extents [minLat] [minLong] [maxLat] [maxLong] : Lat/Long extends to copy (*) * * Of course, the output driver must support writing (by implementing * the ReadWriteTileSource interface). */ int main(int argc, char** argv) { osg::ArgumentParser args(&argc,argv); if ( argc == 1 ) return usage(argv); typedef std::map<std::string,std::string> KeyValue; std::string key, value; // collect input configuration: Config inConf; while( args.read("--in", key, value) ) inConf.set(key, value); TileSourceOptions inOptions(inConf); osg::ref_ptr<TileSource> input = TileSourceFactory::create(inOptions); if ( !input.valid() ) { OE_WARN << LC << "Failed to open input" << std::endl; return -1; } TileSource::Status inputStatus = input->open(); if ( inputStatus.isError() ) { OE_WARN << LC << "Error initializing input" << std::endl; return -1; } // collect output configuration: Config outConf; while( args.read("--out", key, value) ) outConf.set(key, value); // heightfields? bool heightFields = args.read("--heightfield") || args.read("--hf") || args.read("--elevation"); if ( heightFields ) OE_INFO << LC << "Converting heightfield tiles" << std::endl; else OE_INFO << LC << "Converting image tiles" << std::endl; // are we changing profiles? osg::ref_ptr<const Profile> outputProfile = input->getProfile(); std::string profileString; bool isSameProfile = true; if ( args.read("--profile", profileString) ) { outputProfile = Profile::create(profileString); if ( !outputProfile.valid() || !outputProfile->isOK() ) { OE_WARN << LC << "Output profile is not recognized" << std::endl; return -1; } isSameProfile = outputProfile->isHorizEquivalentTo(input->getProfile()); } // set the output profile. ProfileOptions profileOptions = outputProfile->toProfileOptions(); outConf.add("profile", profileOptions.getConfig()); // open the output tile source: TileSourceOptions outOptions(outConf); osg::ref_ptr<TileSource> output = TileSourceFactory::create(outOptions); if ( !output.valid() ) { OE_WARN << LC << "Failed to open output" << std::endl; return -1; } TileSource::Status outputStatus = output->open(TileSource::MODE_WRITE | TileSource::MODE_CREATE); if ( outputStatus.isError() ) { OE_WARN << LC << "Error initializing output" << std::endl; return -1; } // Dump out some stuff... OE_NOTICE << LC << "FROM:\n" << inConf.toJSON(true) << std::endl; OE_NOTICE << LC << "TO:\n" << outConf.toJSON(true) << std::endl; // create the visitor. osg::ref_ptr<TileVisitor> visitor; unsigned numThreads = 1; if (args.read("--threads", numThreads)) { MultithreadedTileVisitor* mtv = new MultithreadedTileVisitor(); mtv->setNumThreads( numThreads < 1 ? 1 : numThreads ); visitor = mtv; } else { visitor = new TileVisitor(); } // If the profiles are identical, just use a tile copier. if ( isSameProfile ) { OE_NOTICE << LC << "Profiles match - initiating simple tile copy" << std::endl; visitor->setTileHandler( new TileSourceToTileSource(input.get(), output.get(), heightFields) ); } else { OE_NOTICE << LC << "Profiles differ - initiating tile transformation" << std::endl; if (heightFields) { ElevationLayer* layer = new ElevationLayer(ElevationLayerOptions(), input.get()); if ( !layer->getProfile() || !layer->getProfile()->isOK() ) { OE_WARN << LC << "Input profile is not valid" << std::endl; return -1; } visitor->setTileHandler( new ElevationLayerToTileSource(layer, output.get()) ); } else { ImageLayer* layer = new ImageLayer(ImageLayerOptions(), input.get()); if ( !layer->getProfile() || !layer->getProfile()->isOK() ) { OE_WARN << LC << "Input profile is not valid" << std::endl; return -1; } visitor->setTileHandler( new ImageLayerToTileSource(layer, output.get()) ); } } // Set the level limits: unsigned minLevel = ~0; bool minLevelSet = args.read("--min-level", minLevel); unsigned maxLevel = 0; bool maxLevelSet = args.read("--max-level", maxLevel); // figure out the max source level: if ( !minLevelSet || !maxLevelSet ) { for(DataExtentList::const_iterator i = input->getDataExtents().begin(); i != input->getDataExtents().end(); ++i) { if ( !maxLevelSet && i->maxLevel().isSet() && i->maxLevel().value() > maxLevel ) maxLevel = i->maxLevel().value(); if ( !minLevelSet && i->minLevel().isSet() && i->minLevel().value() < minLevel ) minLevel = i->minLevel().value(); } } if ( minLevel < ~0 ) { visitor->setMinLevel( minLevel ); } if ( maxLevel > 0 ) { maxLevel = outputProfile->getEquivalentLOD( input->getProfile(), maxLevel ); visitor->setMaxLevel( maxLevel ); OE_NOTICE << LC << "Calculated max level = " << maxLevel << std::endl; } // set the extents: double minlat, minlon, maxlat, maxlon; while( args.read("--extents", minlat, minlon, maxlat, maxlon) ) { GeoExtent extent(SpatialReference::get("wgs84"), minlon, minlat, maxlon, maxlat); visitor->addExtent( extent ); } // Ready!!! std::cout << "Working..." << std::endl; visitor->setProgressCallback( new ProgressReporter() ); osg::Timer_t t0 = osg::Timer::instance()->tick(); visitor->run( outputProfile.get() ); osg::Timer_t t1 = osg::Timer::instance()->tick(); std::cout << "Time = " << std::fixed << std::setprecision(1) << osg::Timer::instance()->delta_s(t0, t1) << " seconds." << std::endl; return 0; }
bool MapFrame::isCached( const osgEarth::TileKey& key ) const { const Profile* mapProfile = getProfile(); //Check the imagery layers for( ImageLayerVector::const_iterator i = imageLayers().begin(); i != imageLayers().end(); i++ ) { ImageLayer* layer = i->get(); osg::ref_ptr< Cache > cache = layer->getCache(); if ( !cache.valid() || !layer->getProfile() ) return false; std::vector< TileKey > keys; if ( mapProfile->isEquivalentTo( layer->getProfile() ) ) { keys.push_back( key ); } else { layer->getProfile()->getIntersectingTiles( key, keys ); } for (unsigned int j = 0; j < keys.size(); ++j) { if ( layer->isKeyValid( keys[j] ) ) { if ( !cache->isCached( keys[j], layer->getCacheSpec() ) ) { return false; } } } } for( ElevationLayerVector::const_iterator i = elevationLayers().begin(); i != elevationLayers().end(); ++i ) { ElevationLayer* layer = i->get(); osg::ref_ptr< Cache > cache = layer->getCache(); if ( !cache.valid() || !layer->getProfile() ) return false; std::vector<TileKey> keys; if ( mapProfile->isEquivalentTo( layer->getProfile() ) ) { keys.push_back( key ); } else { layer->getProfile()->getIntersectingTiles( key, keys ); } for (unsigned int j = 0; j < keys.size(); ++j) { if ( layer->isKeyValid( keys[j] ) ) { if ( !cache->isCached( keys[j], layer->getCacheSpec() ) ) { return false; } } } } return true; }