Status LandUseTileSource::initialize(const osgDB::Options* dbOptions) { _dbOptions = Registry::instance()->cloneOrCreateOptions(dbOptions); const Profile* profile = getProfile(); if ( !profile ) { profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile(); setProfile( profile ); } // load all the image layers: _imageLayers.assign( _options.imageLayerOptionsVector().size(), 0L ); _warps.assign( _options.imageLayerOptionsVector().size(), 0.0f ); for(unsigned i=0; i<_options.imageLayerOptionsVector().size(); ++i) { ImageLayerOptions ilo = _options.imageLayerOptionsVector()[i]; ilo.cachePolicy() = CachePolicy::NO_CACHE; ImageLayer* layer = new ImageLayer( ilo ); layer->setTargetProfileHint( profile ); layer->setReadOptions(_dbOptions.get()); layer->open(); _imageLayers[i] = layer; Config conf = ilo.getConfig(); _warps[i] = conf.value("warp", _options.warpFactor().get()); } // set up the noise generator. const float F[4] = { 4.0f, 16.0f, 4.0f, 8.0f }; const float P[4] = { 0.8f, 0.6f, 0.8f, 0.9f }; const float L[4] = { 2.2f, 1.7f, 3.0f, 4.0f }; // Configure the noise function: _noiseGen.setNormalize ( true ); _noiseGen.setRange ( 0.0, 1.0 ); _noiseGen.setFrequency ( F[0] ); _noiseGen.setPersistence( P[0] ); _noiseGen.setLacunarity ( L[0] ); _noiseGen.setOctaves ( 8 ); return STATUS_OK; }
/** * 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 format image/png * --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 (*) * * OSG arguments: * * -O <string> : OSG Options string (plugin options) * * 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); osg::ref_ptr<osgDB::Options> dbo = new osgDB::Options(); // plugin options, if the user passed them in: std::string str; while(args.read("--osg-options", str) || args.read("-O", str)) { dbo->setOptionString( str ); } 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; } Status inputStatus = input->open( input->MODE_READ, dbo.get() ); 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; } // Copy over the data extents to the output datasource. for (DataExtentList::const_iterator itr = input->getDataExtents().begin(); itr != input->getDataExtents().end(); ++itr) { // Convert the data extent to the profile that is actually used by the output tile source DataExtent dataExtent = *itr; GeoExtent ext = dataExtent.transform(outputProfile->getSRS()); unsigned int minLevel = 0; unsigned int maxLevel = outputProfile->getEquivalentLOD( input->getProfile(), *dataExtent.maxLevel() ); DataExtent outputExtent = DataExtent(ext, minLevel, maxLevel); output->getDataExtents().push_back( outputExtent ); } Status outputStatus = output->open( TileSource::MODE_WRITE | TileSource::MODE_CREATE, dbo.get() ); 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()); Status layerStatus = layer->open(); if (layerStatus.isError()) { OE_WARN << "Failed to create input ElevationLayer " << layerStatus.message() << std::endl; return -1; } 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()); Status layerStatus = layer->open(); if (layerStatus.isError()) { OE_WARN << "Failed to create input ImageLayer " << layerStatus.message() << std::endl; return -1; } 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; }