/** * How to create a simple osgEarth map and display it. */ int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc,argv); // create the empty map. Map* map = new Map(); // add a TMS imagery layer: TMSOptions imagery; imagery.url() = "http://readymap.org/readymap/tiles/1.0.0/22/"; map->addLayer( new ImageLayer("ReadyMap Imagery", imagery) ); // add a TMS elevation layer: TMSOptions elevation; elevation.url() = "http://readymap.org/readymap/tiles/1.0.0/116/"; map->addLayer( new ElevationLayer("ReadyMap Elevation", elevation) ); // Load command line arguments as videos. for(int pos=1;pos<arguments.argc();++pos) { if (!arguments.isOption(pos)) { std::string filename = arguments[ pos ]; OE_NOTICE << "Loading " << filename << std::endl; VideoLayerOptions opt; opt.url() = filename; VideoLayer* layer = new VideoLayer(opt); map->addLayer(layer); } } // make the map scene graph: MapNode* node = new MapNode( map ); // initialize a viewer: osgViewer::Viewer viewer(arguments); viewer.setCameraManipulator( new EarthManipulator ); viewer.setSceneData( node ); // add some stock OSG handlers: viewer.addEventHandler(new osgViewer::StatsHandler()); viewer.addEventHandler(new osgViewer::WindowSizeHandler()); viewer.addEventHandler(new osgViewer::ThreadingHandler()); viewer.addEventHandler(new osgViewer::LODScaleHandler()); viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage())); return viewer.run(); }
void GlobePlugin::elevationLayersChanged() { if ( mIsGlobeRunning ) { QgsDebugMsg( "elevationLayersChanged: Globe Running, executing" ); osg::ref_ptr<Map> map = mMapNode->getMap(); if ( map->getNumElevationLayers() > 1 ) { mOsgViewer->getDatabasePager()->clear(); } // Remove elevation layers ElevationLayerVector list; map->getElevationLayers( list ); for ( ElevationLayerVector::iterator i = list.begin(); i != list.end(); ++i ) { map->removeElevationLayer( *i ); } // Add elevation layers QSettings settings; QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString(); QTableWidget* table = mSettingsDialog->elevationDatasources(); for ( int i = 0; i < table->rowCount(); ++i ) { QString type = table->item( i, 0 )->text(); //bool cache = table->item( i, 1 )->checkState(); QString uri = table->item( i, 2 )->text(); ElevationLayer* layer = 0; if ( "Raster" == type ) { GDALOptions options; options.url() = uri.toStdString(); layer = new osgEarth::ElevationLayer( uri.toStdString(), options ); } else if ( "TMS" == type ) { TMSOptions options; options.url() = uri.toStdString(); layer = new osgEarth::ElevationLayer( uri.toStdString(), options ); } map->addElevationLayer( layer ); //if ( !cache || type == "Worldwind" ) layer->setCache( 0 ); //no tms cache for worldwind (use worldwind_cache) } #if OSGEARTH_VERSION_GREATER_OR_EQUAL( 2, 5, 0 ) double scale = QgsProject::instance()->readDoubleEntry( "Globe-Plugin", "/verticalScale", 1 ); setVerticalScale( scale ); #endif } else { QgsDebugMsg( "layersChanged: Globe NOT running, skipping" ); return; } }
void GlobePlugin::setBaseMap( QString url ) { if ( mMapNode ) { mMapNode->getMap()->removeImageLayer( mBaseLayer ); if ( url.isNull() ) { mBaseLayer = 0; } else { TMSOptions imagery; imagery.url() = url.toStdString(); mBaseLayer = new ImageLayer( "Imagery", imagery ); mMapNode->getMap()->insertImageLayer( mBaseLayer, 0 ); } } }
/** Packages an image layer as a TMS folder. */ int makeTMS( osg::ArgumentParser& args ) { // see if the user wants to override the type extension (imagery only) std::string extension; args.read( "--ext", extension ); // verbosity? bool verbose = !args.read( "--quiet" ); // find a .earth file on the command line std::string earthFile = findArgumentWithExtension( args, ".earth" ); /* if ( earthFile.empty() ) return usage( "Missing required .earth file" ); */ // folder to which to write the TMS archive. std::string rootFolder; if( !args.read( "--out", rootFolder ) ) rootFolder = Stringify() << earthFile << ".tms_repo"; // whether to overwrite existing tile files bool overwrite = false; if( args.read( "--overwrite" ) ) overwrite = true; // write out an earth file std::string outEarth; args.read( "--out-earth", outEarth ); std::string dbOptions; args.read( "--db-options", dbOptions ); std::string::size_type n = 0; while( (n = dbOptions.find( '"', n )) != dbOptions.npos ) { dbOptions.erase( n, 1 ); } osg::ref_ptr<osgDB::Options> options = new osgDB::Options( dbOptions ); std::vector< Bounds > bounds; // restrict packaging to user-specified bounds. double xmin = DBL_MAX, ymin = DBL_MAX, xmax = DBL_MIN, ymax = DBL_MIN; while( args.read( "--bounds", xmin, ymin, xmax, ymax ) ) { Bounds b; b.xMin() = xmin, b.yMin() = ymin, b.xMax() = xmax, b.yMax() = ymax; bounds.push_back( b ); } // max level to which to generate unsigned maxLevel = ~0; args.read( "--max-level", maxLevel ); // whether to keep 'empty' tiles bool keepEmpties = args.read( "--keep-empties" ); bool continueSingleColor = args.read( "--continue-single-color" ); // max level to which to generate unsigned elevationPixelDepth = 32; args.read( "--elevation-pixel-depth", elevationPixelDepth ); // load up the map osg::ref_ptr<MapNode> mapNode = MapNode::load( args ); if( !mapNode.valid() ) return usage( "Failed to load a valid .earth file" ); // create a folder for the output osgDB::makeDirectory( rootFolder ); if( !osgDB::fileExists( rootFolder ) ) return usage( "Failed to create root output folder" ); Map* map = mapNode->getMap(); // fire up a packager: TMSPackager packager( map->getProfile(), options ); packager.setVerbose( verbose ); packager.setOverwrite( overwrite ); packager.setKeepEmptyImageTiles( keepEmpties ); packager.setSubdivideSingleColorImageTiles( continueSingleColor ); packager.setElevationPixelDepth( elevationPixelDepth ); if( maxLevel != ~0 ) packager.setMaxLevel( maxLevel ); if( bounds.size() > 0 ) { for( unsigned int i = 0; i < bounds.size(); ++i ) { Bounds b = bounds[i]; if( b.isValid() ) packager.addExtent( GeoExtent( map->getProfile()->getSRS(), b ) ); } } // new map for an output earth file if necessary. osg::ref_ptr<Map> outMap = 0L; if( !outEarth.empty() ) { // copy the options from the source map first outMap = new Map( map->getInitialMapOptions() ); } // establish the output path of the earth file, if applicable: std::string outEarthFile = osgDB::concatPaths( rootFolder, osgDB::getSimpleFileName( outEarth ) ); // package any image layers that are enabled: ImageLayerVector imageLayers; map->getImageLayers( imageLayers ); unsigned counter = 0; for( ImageLayerVector::iterator i = imageLayers.begin(); i != imageLayers.end(); ++i, ++counter ) { ImageLayer* layer = i->get(); if( layer->getImageLayerOptions().enabled() == true ) { std::string layerFolder = toLegalFileName( layer->getName() ); if( layerFolder.empty() ) layerFolder = Stringify() << "image_layer_" << counter; if( verbose ) { OE_NOTICE << LC << "Packaging image layer \"" << layerFolder << "\"" << std::endl; } osg::ref_ptr< ConsoleProgressCallback > progress = new ConsoleProgressCallback(); std::string layerRoot = osgDB::concatPaths( rootFolder, layerFolder ); TMSPackager::Result r = packager.package( layer, layerRoot, progress, extension ); if( r.ok ) { // save to the output map if requested: if( outMap.valid() ) { // new TMS driver info: TMSOptions tms; tms.url() = URI( osgDB::concatPaths( layerFolder, "tms.xml" ), outEarthFile ); ImageLayerOptions layerOptions( layer->getName(), tms ); layerOptions.mergeConfig( layer->getInitialOptions().getConfig( true ) ); layerOptions.cachePolicy() = CachePolicy::NO_CACHE; outMap->addImageLayer( new ImageLayer( layerOptions ) ); } } else { OE_WARN << LC << r.message << std::endl; } } else if( verbose ) { OE_NOTICE << LC << "Skipping disabled layer \"" << layer->getName() << "\"" << std::endl; } } // package any elevation layers that are enabled: counter = 0; ElevationLayerVector elevationLayers; map->getElevationLayers( elevationLayers ); for( ElevationLayerVector::iterator i = elevationLayers.begin(); i != elevationLayers.end(); ++i, ++counter ) { ElevationLayer* layer = i->get(); if( layer->getElevationLayerOptions().enabled() == true ) { std::string layerFolder = toLegalFileName( layer->getName() ); if( layerFolder.empty() ) layerFolder = Stringify() << "elevation_layer_" << counter; if( verbose ) { OE_NOTICE << LC << "Packaging elevation layer \"" << layerFolder << "\"" << std::endl; } std::string layerRoot = osgDB::concatPaths( rootFolder, layerFolder ); TMSPackager::Result r = packager.package( layer, layerRoot ); if( r.ok ) { // save to the output map if requested: if( outMap.valid() ) { // new TMS driver info: TMSOptions tms; tms.url() = URI( osgDB::concatPaths( layerFolder, "tms.xml" ), outEarthFile ); ElevationLayerOptions layerOptions( layer->getName(), tms ); layerOptions.mergeConfig( layer->getInitialOptions().getConfig( true ) ); layerOptions.cachePolicy() = CachePolicy::NO_CACHE; outMap->addElevationLayer( new ElevationLayer( layerOptions ) ); } } else { OE_WARN << LC << r.message << std::endl; } } else if( verbose ) { OE_NOTICE << LC << "Skipping disabled layer \"" << layer->getName() << "\"" << std::endl; } } // Finally, write an earth file if requested: if( outMap.valid() ) { MapNodeOptions outNodeOptions = mapNode->getMapNodeOptions(); osg::ref_ptr<MapNode> outMapNode = new MapNode( outMap.get(), outNodeOptions ); if( !osgDB::writeNodeFile( *outMapNode.get(), outEarthFile ) ) { OE_WARN << LC << "Error writing earth file to \"" << outEarthFile << "\"" << std::endl; } else if( verbose ) { OE_NOTICE << LC << "Wrote earth file to \"" << outEarthFile << "\"" << std::endl; } } return 0; }
void GlobePlugin::layersChanged() { if ( mIsGlobeRunning ) { QgsDebugMsg( "layersChanged: Globe Running, executing" ); osg::ref_ptr<Map> map = mMapNode->getMap(); if ( map->getNumImageLayers() > 1 || map->getNumElevationLayers() > 1 ) { viewer.getDatabasePager()->clear(); } // Remove elevation layers ElevationLayerVector list; map->getElevationLayers( list ); for ( ElevationLayerVector::iterator i = list.begin(); i != list.end(); i++ ) { map->removeElevationLayer( *i ); } // Add elevation layers QSettings settings; QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString(); QTableWidget* table = mSettingsDialog.elevationDatasources(); for ( int i = 0; i < table->rowCount(); ++i ) { QString type = table->item( i, 0 )->text(); bool cache = table->item( i, 1 )->checkState(); QString uri = table->item( i, 2 )->text(); ElevationLayer* layer = 0; if ( "Raster" == type ) { GDALOptions options; options.url() = uri.toStdString(); layer = new osgEarth::ElevationLayer( uri.toStdString(), options ); } else if ( "Worldwind" == type ) { WorldWindOptions options; options.elevationCachePath() = cacheDirectory.toStdString() + "/globe/worldwind_srtm"; layer = new osgEarth::ElevationLayer( "WorldWind bil", options ); TerrainEngineNode* terrainEngineNode = mMapNode->getTerrainEngine(); terrainEngineNode->setVerticalScale( 2 ); terrainEngineNode->setElevationSamplingRatio( 0.25 ); } else if ( "TMS" == type ) { TMSOptions options; options.url() = uri.toStdString(); layer = new osgEarth::ElevationLayer( uri.toStdString(), options ); } map->addElevationLayer( layer ); if ( !cache || type == "Worldwind" ) layer->setCache( 0 ); //no tms cache for worldwind (use worldwind_cache) } //remove QGIS layer if ( mQgisMapLayer ) { QgsDebugMsg( "removeMapLayer" ); map->removeImageLayer( mQgisMapLayer ); } //add QGIS layer QgsDebugMsg( "addMapLayer" ); mTileSource = new QgsOsgEarthTileSource( mQGisIface ); mTileSource->initialize( "", 0 ); ImageLayerOptions options( "QGIS" ); mQgisMapLayer = new ImageLayer( options, mTileSource ); map->addImageLayer( mQgisMapLayer ); mQgisMapLayer->setCache( 0 ); //disable caching } else { QgsDebugMsg( "layersChanged: Globe NOT running, skipping" ); return; } }
/** Packages an image layer as a TMS folder. */ int makeTMS( osg::ArgumentParser& args ) { osgDB::Registry::instance()->getReaderWriterForExtension("png"); osgDB::Registry::instance()->getReaderWriterForExtension("jpg"); osgDB::Registry::instance()->getReaderWriterForExtension("tiff"); //Read the min level unsigned int minLevel = 0; while (args.read("--min-level", minLevel)); //Read the max level unsigned int maxLevel = 5; while (args.read("--max-level", maxLevel)); std::vector< Bounds > bounds; // restrict packaging to user-specified bounds. double xmin=DBL_MAX, ymin=DBL_MAX, xmax=DBL_MIN, ymax=DBL_MIN; while (args.read("--bounds", xmin, ymin, xmax, ymax )) { Bounds b; b.xMin() = xmin, b.yMin() = ymin, b.xMax() = xmax, b.yMax() = ymax; bounds.push_back( b ); } std::string tileList; while (args.read( "--tiles", tileList ) ); bool verbose = args.read("--verbose"); unsigned int batchSize = 0; args.read("--batchsize", batchSize); // Read the concurrency level unsigned int concurrency = 0; args.read("-c", concurrency); args.read("--concurrency", concurrency); bool writeXML = true; // load up the map osg::ref_ptr<MapNode> mapNode = MapNode::load( args ); if( !mapNode.valid() ) return usage( "Failed to load a valid .earth file" ); // Read in an index shapefile std::string index; while (args.read("--index", index)) { //Open the feature source OGRFeatureOptions featureOpt; featureOpt.url() = index; osg::ref_ptr< FeatureSource > features = FeatureSourceFactory::create( featureOpt ); features->initialize(); features->getFeatureProfile(); osg::ref_ptr< FeatureCursor > cursor = features->createFeatureCursor(); while (cursor.valid() && cursor->hasMore()) { osg::ref_ptr< Feature > feature = cursor->nextFeature(); osgEarth::Bounds featureBounds = feature->getGeometry()->getBounds(); GeoExtent ext( feature->getSRS(), featureBounds ); ext = ext.transform( mapNode->getMapSRS() ); bounds.push_back( ext.bounds() ); } } // see if the user wants to override the type extension (imagery only) std::string extension; args.read( "--ext", extension ); // find a .earth file on the command line std::string earthFile = findArgumentWithExtension( args, ".earth" ); // folder to which to write the TMS archive. std::string rootFolder; if( !args.read( "--out", rootFolder ) ) rootFolder = Stringify() << earthFile << ".tms_repo"; // whether to overwrite existing tile files //TODO: Support bool overwrite = false; if( args.read( "--overwrite" ) ) overwrite = true; // write out an earth file std::string outEarth; args.read( "--out-earth", outEarth ); std::string dbOptions; args.read( "--db-options", dbOptions ); std::string::size_type n = 0; while( (n = dbOptions.find( '"', n )) != dbOptions.npos ) { dbOptions.erase( n, 1 ); } osg::ref_ptr<osgDB::Options> options = new osgDB::Options( dbOptions ); // whether to keep 'empty' tiles bool keepEmpties = args.read( "--keep-empties" ); //TODO: Single color bool continueSingleColor = args.read( "--continue-single-color" ); // elevation pixel depth unsigned elevationPixelDepth = 32; args.read( "--elevation-pixel-depth", elevationPixelDepth ); // create a folder for the output osgDB::makeDirectory( rootFolder ); if( !osgDB::fileExists( rootFolder ) ) return usage( "Failed to create root output folder" ); int imageLayerIndex = -1; args.read("--image", imageLayerIndex); int elevationLayerIndex = -1; args.read("--elevation", elevationLayerIndex); Map* map = mapNode->getMap(); osg::ref_ptr< TileVisitor > visitor; // If we are given a task file, load it up and create a new TileKeyListVisitor if (!tileList.empty()) { TaskList tasks( mapNode->getMap()->getProfile() ); tasks.load( tileList ); TileKeyListVisitor* v = new TileKeyListVisitor(); v->setKeys( tasks.getKeys() ); visitor = v; // This process is a lowly worker, and shouldn't write out the XML file. writeXML = false; } // If we dont' have a visitor create one. if (!visitor.valid()) { if (args.read("--mt")) { // Create a multithreaded visitor MultithreadedTileVisitor* v = new MultithreadedTileVisitor(); if (concurrency > 0) { v->setNumThreads(concurrency); } visitor = v; } else if (args.read("--mp")) { // Create a multiprocess visitor MultiprocessTileVisitor* v = new MultiprocessTileVisitor(); if (concurrency > 0) { v->setNumProcesses(concurrency); OE_NOTICE << "Set num processes " << concurrency << std::endl; } if (batchSize > 0) { v->setBatchSize(batchSize); } // Try to find the earth file std::string earthFile; for(int pos=1;pos<args.argc();++pos) { if (!args.isOption(pos)) { earthFile = args[ pos ]; break; } } v->setEarthFile( earthFile ); visitor = v; } else { // Create a single thread visitor visitor = new TileVisitor(); } } osg::ref_ptr< ProgressCallback > progress = new ConsoleProgressCallback(); if (verbose) { visitor->setProgressCallback( progress ); } visitor->setMinLevel( minLevel ); visitor->setMaxLevel( maxLevel ); for (unsigned int i = 0; i < bounds.size(); i++) { GeoExtent extent(mapNode->getMapSRS(), bounds[i]); OE_DEBUG << "Adding extent " << extent.toString() << std::endl; visitor->addExtent( extent ); } // Setup a TMSPackager with all the options. TMSPackager packager; packager.setExtension(extension); packager.setVisitor(visitor); packager.setDestination(rootFolder); packager.setElevationPixelDepth(elevationPixelDepth); packager.setWriteOptions(options); packager.setOverwrite(overwrite); packager.setKeepEmpties(keepEmpties); // new map for an output earth file if necessary. osg::ref_ptr<Map> outMap = 0L; if( !outEarth.empty() ) { // copy the options from the source map first outMap = new Map( map->getInitialMapOptions() ); } std::string outEarthFile = osgDB::concatPaths( rootFolder, osgDB::getSimpleFileName( outEarth ) ); // Package an individual image layer if (imageLayerIndex >= 0) { ImageLayer* layer = map->getImageLayerAt(imageLayerIndex); if (layer) { packager.run(layer, map); if (writeXML) { packager.writeXML(layer, map); } } else { std::cout << "Failed to find an image layer at index " << imageLayerIndex << std::endl; return 1; } } // Package an individual elevation layer else if (elevationLayerIndex >= 0) { ElevationLayer* layer = map->getElevationLayerAt(elevationLayerIndex); if (layer) { packager.run(layer, map); if (writeXML) { packager.writeXML(layer, map ); } } else { std::cout << "Failed to find an elevation layer at index " << elevationLayerIndex << std::endl; return 1; } } else { // Package all the ImageLayer's for (unsigned int i = 0; i < map->getNumImageLayers(); i++) { ImageLayer* layer = map->getImageLayerAt(i); OE_NOTICE << "Packaging " << layer->getName() << std::endl; osg::Timer_t start = osg::Timer::instance()->tick(); packager.run(layer, map); osg::Timer_t end = osg::Timer::instance()->tick(); if (verbose) { OE_NOTICE << "Completed seeding layer " << layer->getName() << " in " << prettyPrintTime( osg::Timer::instance()->delta_s( start, end ) ) << std::endl; } if (writeXML) { packager.writeXML(layer, map); } // save to the output map if requested: if( outMap.valid() ) { std::string layerFolder = toLegalFileName( packager.getLayerName() ); // new TMS driver info: TMSOptions tms; tms.url() = URI( osgDB::concatPaths( layerFolder, "tms.xml" ), outEarthFile ); ImageLayerOptions layerOptions( packager.getLayerName(), tms ); layerOptions.mergeConfig( layer->getInitialOptions().getConfig( true ) ); layerOptions.cachePolicy() = CachePolicy::NO_CACHE; outMap->addImageLayer( new ImageLayer( layerOptions ) ); } } // Package all the ElevationLayer's for (unsigned int i = 0; i < map->getNumElevationLayers(); i++) { ElevationLayer* layer = map->getElevationLayerAt(i); OE_NOTICE << "Packaging " << layer->getName() << std::endl; osg::Timer_t start = osg::Timer::instance()->tick(); packager.run(layer, map); osg::Timer_t end = osg::Timer::instance()->tick(); if (verbose) { OE_NOTICE << "Completed seeding layer " << layer->getName() << " in " << prettyPrintTime( osg::Timer::instance()->delta_s( start, end ) ) << std::endl; } if (writeXML) { packager.writeXML(layer, map); } // save to the output map if requested: if( outMap.valid() ) { std::string layerFolder = toLegalFileName( packager.getLayerName() ); // new TMS driver info: TMSOptions tms; tms.url() = URI( osgDB::concatPaths( layerFolder, "tms.xml" ), outEarthFile ); ElevationLayerOptions layerOptions( packager.getLayerName(), tms ); layerOptions.mergeConfig( layer->getInitialOptions().getConfig( true ) ); layerOptions.cachePolicy() = CachePolicy::NO_CACHE; outMap->addElevationLayer( new ElevationLayer( layerOptions ) ); } } } // Write out an earth file if it was requested // Finally, write an earth file if requested: if( outMap.valid() ) { MapNodeOptions outNodeOptions = mapNode->getMapNodeOptions(); osg::ref_ptr<MapNode> outMapNode = new MapNode( outMap.get(), outNodeOptions ); if( !osgDB::writeNodeFile( *outMapNode.get(), outEarthFile ) ) { OE_WARN << LC << "Error writing earth file to \"" << outEarthFile << "\"" << std::endl; } else if( verbose ) { OE_NOTICE << LC << "Wrote earth file to \"" << outEarthFile << "\"" << std::endl; } } return 0; }
// Creates a visible imagery layer that we will modulate. ImageLayer* createImageryLayer() { TMSOptions tms; tms.url() = "http://readymap.org/readymap/tiles/1.0.0/7/"; return new ImageLayer( "imagery", tms ); }
void GlobePlugin::setupMap() { QSettings settings; /* QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString(); TMSCacheOptions cacheOptions; cacheOptions.setPath( cacheDirectory.toStdString() ); */ MapOptions mapOptions; //mapOptions.cache() = cacheOptions; osgEarth::Map *map = new osgEarth::Map( mapOptions ); //Default image layer /* GDALOptions driverOptions; driverOptions.url() = QDir::cleanPath( QgsApplication::pkgDataPath() + "/globe/world.tif" ).toStdString(); ImageLayerOptions layerOptions( "world", driverOptions ); map->addImageLayer( new osgEarth::ImageLayer( layerOptions ) ); */ TMSOptions imagery; imagery.url() = "http://readymap.org/readymap/tiles/1.0.0/7/"; map->addImageLayer( new ImageLayer( "Imagery", imagery ) ); MapNodeOptions nodeOptions; //nodeOptions.proxySettings() = //nodeOptions.enableLighting() = false; //LoadingPolicy loadingPolicy( LoadingPolicy::MODE_SEQUENTIAL ); TerrainOptions terrainOptions; //terrainOptions.loadingPolicy() = loadingPolicy; terrainOptions.compositingTechnique() = TerrainOptions::COMPOSITING_MULTITEXTURE_FFP; //terrainOptions.lodFallOff() = 6.0; nodeOptions.setTerrainOptions( terrainOptions ); // The MapNode will render the Map object in the scene graph. mMapNode = new osgEarth::MapNode( map, nodeOptions ); mRootNode = new osg::Group(); mRootNode->addChild( mMapNode ); // Add layers to the map imageLayersChanged(); elevationLayersChanged(); // model placement utils #ifdef HAVE_OSGEARTH_ELEVATION_QUERY #else mElevationManager = new osgEarth::Util::ElevationManager( mMapNode->getMap() ); mElevationManager->setTechnique( osgEarth::Util::ElevationManager::TECHNIQUE_GEOMETRIC ); mElevationManager->setMaxTilesToCache( 50 ); mObjectPlacer = new osgEarth::Util::ObjectPlacer( mMapNode ); // place 3D model on point layer if ( mSettingsDialog->modelLayer() && !mSettingsDialog->modelPath().isEmpty() ) { osg::Node* model = osgDB::readNodeFile( mSettingsDialog->modelPath().toStdString() ); if ( model ) { QgsVectorLayer* layer = mSettingsDialog->modelLayer(); QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ); //TODO: select only visible features QgsFeature feature; while ( fit.nextFeature( feature ) ) { QgsPoint point = feature.geometry()->asPoint(); placeNode( model, point.y(), point.x() ); } } } #endif }
/** Packages image and elevation layers as a TMS. */ int TMSExporter::exportTMS(MapNode* mapNode, const std::string& earthFilePath, const std::string& path, std::vector< osgEarth::Bounds >& bounds, const std::string& outEarth, bool overwrite, const std::string& extension) { _totalTimeS = 0.0; osg::Timer_t startTime = osg::Timer::instance()->tick(); Map* map = mapNode->getMap(); // new map for an output earth file if necessary. osg::ref_ptr<Map> outMap = 0L; if ( !outEarth.empty() ) { // copy the options from the source map first outMap = new Map(map->getInitialMapOptions()); } // establish the output path of the earth file, if applicable: std::string outEarthName = osgDB::getSimpleFileName(outEarth); if (outEarthName.length() > 0 && osgEarth::toLower(osgDB::getFileExtension(outEarthName)) != "earth") outEarthName += ".earth"; std::string outEarthFile = osgDB::concatPaths(path, outEarthName); // Create the TMS packager. TMSPackager packager; std::string tmpEarth; // Setup the visitor with the concurrency level and processing mode if it's set. if (_concurrency > 1) { if (_mode == MODE_MULTIPROCESS) { // Write out a temp earth file so the processes can work on it. // Determine the output path. If we loaded from an earth file write out the temp file right next to it so relative paths will work the same. // Otherwise use the temp path OE_NOTICE << "Earth file path " << earthFilePath << std::endl; if (!earthFilePath.empty()) { std::string root = osgDB::getFilePath(earthFilePath); root += "/"; tmpEarth = getTempName(root, ".earth"); } else { tmpEarth = getTempName(getTempPath(), ".earth"); } OE_INFO << "Writing to " << tmpEarth << std::endl; osgDB::writeNodeFile(*mapNode, tmpEarth ); MultiprocessTileVisitor* v = new MultiprocessTileVisitor(); v->setEarthFile(tmpEarth); v->setNumProcesses(_concurrency); packager.setVisitor(v); } else if (_mode == MODE_MULTITHREADED) { MultithreadedTileVisitor* v = new MultithreadedTileVisitor(); v->setNumThreads(_concurrency); packager.setVisitor(v); } } // Make the output directory if it doesn't exist osgDB::makeDirectory(path); packager.setDestination(path); // Setup the osgDB options for the packager. osg::ref_ptr<osgDB::Options> options = new osgDB::Options(_dbOptions); packager.setWriteOptions( options.get() ); // Add all the bounds for (unsigned int i = 0; i < bounds.size(); i++) { packager.getTileVisitor()->addExtent( osgEarth::GeoExtent(map->getProfile()->getSRS(), bounds[i])); } packager.setExtension(extension); packager.setOverwrite(overwrite); packager.getTileVisitor()->setProgressCallback( _progress.get() ); packager.getTileVisitor()->setMaxLevel(_maxLevel); // Compute the total number of layers we are going to operate on. unsigned int totalLayers = map->getNumImageLayers() + map->getNumElevationLayers(); unsigned int layerNum = 1; // Package each image layer for (unsigned int i = 0; i < map->getNumImageLayers(); i++) { // Don't continue if the export has been canceled if (_progress->isCanceled()) { break; } osg::ref_ptr< ImageLayer > layer = map->getImageLayerAt(i); std::stringstream buf; buf << "Packaging " << layer->getName() << " (" << layerNum << " of " << totalLayers << ")"; OE_NOTICE << buf.str() << std::endl; _progress->setStatus(buf.str()); packager.run(layer.get(), map); packager.writeXML(layer.get(), map); if (outMap) { std::string layerFolder = toLegalFileName( packager.getLayerName() ); // new TMS driver info: TMSOptions tms; tms.url() = URI( osgDB::concatPaths( layerFolder, "tms.xml" ), outEarthFile ); ImageLayerOptions layerOptions( packager.getLayerName(), tms ); layerOptions.mergeConfig( layer->getInitialOptions().getConfig( true ) ); layerOptions.cachePolicy() = CachePolicy::NO_CACHE; outMap->addImageLayer( new ImageLayer( layerOptions ) ); } layerNum++; } // Package each elevation layer for (unsigned int i = 0; i < map->getNumElevationLayers(); i++) { // Don't continue if the export has been canceled if (_progress->isCanceled()) { break; } osg::ref_ptr< ElevationLayer > layer = map->getElevationLayerAt(i); std::stringstream buf; buf << "Packaging " << layer->getName() << " (" << layerNum << " of " << totalLayers << ")"; OE_NOTICE << buf.str() << std::endl; _progress->setStatus(buf.str()); packager.run(layer.get(), map); packager.writeXML(layer.get(), map); if( outMap.valid() ) { std::string layerFolder = toLegalFileName( packager.getLayerName() ); // new TMS driver info: TMSOptions tms; tms.url() = URI( osgDB::concatPaths( layerFolder, "tms.xml" ), outEarthFile ); ElevationLayerOptions layerOptions( packager.getLayerName(), tms ); layerOptions.mergeConfig( layer->getInitialOptions().getConfig( true ) ); layerOptions.cachePolicy() = CachePolicy::NO_CACHE; outMap->addElevationLayer( new ElevationLayer( layerOptions ) ); } layerNum++; } // Don't continue if the export has been canceled if (!_progress->isCanceled()) { // Write out an earth file if it was requested // Finally, write an earth file if requested: if( outMap.valid() ) { MapNodeOptions outNodeOptions = mapNode->getMapNodeOptions(); osg::ref_ptr<MapNode> outMapNode = new MapNode( outMap.get(), outNodeOptions ); if( !osgDB::writeNodeFile( *outMapNode.get(), outEarthFile ) ) { OE_WARN << LC << "Error writing earth file to \"" << outEarthFile << "\"" << std::endl; } } } osg::Timer_t endTime = osg::Timer::instance()->tick(); _totalTimeS = osg::Timer::instance()->delta_s(startTime, endTime ); // Tell the progress dialog that we're finished and it can close _progress->complete(); // Remove the temp earth file. if (!tmpEarth.empty()) { remove(tmpEarth.c_str()); } return 0; }
/** * This code example effectively duplicates the "boston.earth" sample, * demonstrating how to create a 3D city model in osgEarth. * * Run this from the tests folder. */ int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc,argv); // create the map. Map* map = new Map(); // add a TMS imagery layer: TMSOptions imagery; imagery.url() = "http://readymap.org/readymap/tiles/1.0.0/22/"; map->addImageLayer( new ImageLayer("ReadyMap imagery", imagery) ); // create a feature source to load the building footprint shapefile. OGRFeatureOptions feature_opt; feature_opt.name() = "buildings"; feature_opt.url() = "../data/boston_buildings_utm19.shp"; feature_opt.buildSpatialIndex() = true; // a style for the building data: Style buildingStyle; buildingStyle.setName( "default" ); ExtrusionSymbol* extrusion = buildingStyle.getOrCreate<ExtrusionSymbol>(); extrusion->heightExpression() = NumericExpression( "3.5 * max( [story_ht_], 1 )" ); extrusion->flatten() = true; extrusion->wallStyleName() = "building-wall"; extrusion->roofStyleName() = "building-roof"; // a style for the wall textures: Style wallStyle; wallStyle.setName( "building-wall" ); SkinSymbol* wallSkin = wallStyle.getOrCreate<SkinSymbol>(); wallSkin->libraryName() = "us_resources"; wallSkin->addTag( "building" ); wallSkin->randomSeed() = 1; // a style for the rooftop textures: Style roofStyle; roofStyle.setName( "building-roof" ); SkinSymbol* roofSkin = roofStyle.getOrCreate<SkinSymbol>(); roofSkin->libraryName() = "us_resources"; roofSkin->addTag( "rooftop" ); roofSkin->randomSeed() = 1; roofSkin->isTiled() = true; // assemble a stylesheet and add our styles to it: StyleSheet* styleSheet = new StyleSheet(); styleSheet->addStyle( buildingStyle ); styleSheet->addStyle( wallStyle ); styleSheet->addStyle( roofStyle ); // load a resource library that contains the building textures. ResourceLibrary* reslib = new ResourceLibrary( "us_resources", "../data/resources/textures_us/catalog.xml" ); styleSheet->addResourceLibrary( reslib ); // set up a paging layout for incremental loading. FeatureDisplayLayout layout; layout.tileSizeFactor() = 45.0; layout.addLevel( FeatureLevel(0.0f, 20000.0f) ); // create a model layer that will render the buildings according to our style sheet. FeatureGeomModelOptions fgm_opt; fgm_opt.featureOptions() = feature_opt; fgm_opt.styles() = styleSheet; fgm_opt.layout() = layout; map->addModelLayer( new ModelLayer( "buildings", fgm_opt ) ); // initialize a viewer: osgViewer::Viewer viewer(arguments); EarthManipulator* manip = new EarthManipulator(); viewer.setCameraManipulator( manip ); // make the map scene graph: osg::Group* root = new osg::Group(); viewer.setSceneData( root ); MapNode* mapNode = new MapNode( map ); root->addChild( mapNode ); // Process cmdline args MapNodeHelper helper; helper.configureView( &viewer ); helper.parse(mapNode, arguments, &viewer, root, new LabelControl("City Demo")); // zoom to a good startup position manip->setViewpoint( Viewpoint(-71.0763, 42.34425, 0, 24.261, -21.6, 3450.0), 5.0 ); viewer.getDatabasePager()->setDoPreCompile( true ); viewer.getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode) ); return viewer.run(); }
/** Packages image and elevation layers as a TMS. */ int TMSExporter::exportTMS(MapNode* mapNode, const std::string& path, std::vector< osgEarth::Bounds >& bounds, const std::string& outEarth, bool overwrite, const std::string& extension) { if ( !mapNode ) { _errorMessage = "Invalid MapNode"; if (_progress.valid()) _progress->onCompleted(); return 0; } // folder to which to write the TMS archive. std::string rootFolder = path; osg::ref_ptr<osgDB::Options> options = new osgDB::Options(_dbOptions); // create a folder for the output osgDB::makeDirectory(rootFolder); if ( !osgDB::fileExists(rootFolder) ) { _errorMessage = "Failed to create root output folder"; if (_progress.valid()) _progress->onCompleted(); return 0; } Map* map = mapNode->getMap(); // new map for an output earth file if necessary. osg::ref_ptr<Map> outMap = 0L; if ( !outEarth.empty() ) { // copy the options from the source map first outMap = new Map(map->getInitialMapOptions()); } // establish the output path of the earth file, if applicable: std::string outEarthName = osgDB::getSimpleFileName(outEarth); if (outEarthName.length() > 0 && osgEarth::toLower(osgDB::getFileExtension(outEarthName)) != "earth") outEarthName += ".earth"; std::string outEarthFile = osgDB::concatPaths(rootFolder, outEarthName); // semaphore and tasks collection for multithreading osgEarth::Threading::MultiEvent semaphore; osgEarth::TaskRequestVector tasks; int taskCount = 0; // package any image layers that are enabled and visible ImageLayerVector imageLayers; map->getImageLayers( imageLayers ); unsigned imageCount = 0; for( ImageLayerVector::iterator i = imageLayers.begin(); i != imageLayers.end(); ++i, ++imageCount ) { ImageLayer* layer = i->get(); if ( layer->getEnabled() && layer->getVisible() ) { std::string layerFolder = toLegalFileName( layer->getName() ); if ( layerFolder.empty() ) layerFolder = Stringify() << "image_layer_" << imageCount; ParallelTask<PackageLayer>* task = new ParallelTask<PackageLayer>( &semaphore ); task->init(map, layer, options, rootFolder, layerFolder, true, overwrite, _keepEmpties, _maxLevel, extension, bounds); task->setProgressCallback(new PackageLayerProgressCallback(this)); tasks.push_back(task); taskCount++; } } // package any elevation layers that are enabled and visible ElevationLayerVector elevationLayers; map->getElevationLayers( elevationLayers ); int elevCount = 0; for( ElevationLayerVector::iterator i = elevationLayers.begin(); i != elevationLayers.end(); ++i, ++elevCount ) { ElevationLayer* layer = i->get(); if ( layer->getEnabled() && layer->getVisible() ) { std::string layerFolder = toLegalFileName( layer->getName() ); if ( layerFolder.empty() ) layerFolder = Stringify() << "elevation_layer_" << elevCount; ParallelTask<PackageLayer>* task = new ParallelTask<PackageLayer>( &semaphore ); task->init(map, layer, options, rootFolder, layerFolder, true, overwrite, _keepEmpties, _maxLevel, extension, bounds); task->setProgressCallback(new PackageLayerProgressCallback(this)); tasks.push_back(task); taskCount++; } } // Run all the tasks in parallel _totalTasks = taskCount; _completedTasks = 0; semaphore.reset( _totalTasks ); for( TaskRequestVector::iterator i = tasks.begin(); i != tasks.end(); ++i ) _taskService->add( i->get() ); // Wait for them to complete semaphore.wait(); // Add successfully packaged layers to the new map object and // write out the .earth file (if requested) if (outMap.valid()) { for( TaskRequestVector::iterator i = tasks.begin(); i != tasks.end(); ++i ) { PackageLayer* p = dynamic_cast<PackageLayer*>(i->get()); if (p) { if (p->_packageResult.ok) { TMSOptions tms; tms.url() = URI(osgDB::concatPaths(p->_layerFolder, "tms.xml"), outEarthFile ); if (p->_imageLayer.valid()) { ImageLayerOptions layerOptions( p->_imageLayer->getName(), tms ); layerOptions.mergeConfig( p->_imageLayer->getInitialOptions().getConfig(true) ); layerOptions.cachePolicy() = CachePolicy::NO_CACHE; outMap->addImageLayer( new ImageLayer(layerOptions) ); } else { ElevationLayerOptions layerOptions( p->_elevationLayer->getName(), tms ); layerOptions.mergeConfig( p->_elevationLayer->getInitialOptions().getConfig(true) ); layerOptions.cachePolicy() = CachePolicy::NO_CACHE; outMap->addElevationLayer( new ElevationLayer(layerOptions) ); } } else { OE_WARN << LC << p->_packageResult.message << std::endl; } } } } if ( outMap.valid() ) { MapNodeOptions outNodeOptions = mapNode->getMapNodeOptions(); osg::ref_ptr<MapNode> outMapNode = new MapNode(outMap.get(), outNodeOptions); if ( !osgDB::writeNodeFile(*outMapNode.get(), outEarthFile) ) { OE_WARN << LC << "Error writing earth file to \"" << outEarthFile << "\"" << std::endl; } else { OE_NOTICE << LC << "Wrote earth file to \"" << outEarthFile << "\"" << std::endl; } } // Mark the progress callback as completed if (_progress.valid()) _progress->onCompleted(); return elevCount + imageCount; }