osgearth_splat示例,展示如何加载图片贴在地球上,且通过分类,贴文理绘制森林、草地等。
执行命令:osgearth_splatd.exe
整个地球的影像,加载的一张贴图。黑白点点,是不同的贴图。当拉进放大后,才可以看清楚加载的是哪张纹理图。代码设置了15级。
1. 创建 土地覆盖字典选项 LandCoverDictionaryOptions options;
将xml文件中的字典配置,读入options中,主要是name。
2. 用options初始化土地覆盖字典 LandCoverDictionary dictionary;
3. 设置gdal驱动 GDALOptions coverageDriver;,加载地形。
4. 创建LandCover的可序列化配置选项 LandCoverCoverageLayerOptions coverage;
主要包括驱动 coverageDriver 以及 map表(从xml读入,指定某位置放某类贴图)。
5. 为地图创建土地覆盖层:LandCoverLayer *landCover; 并将coverage设置到此土地覆盖层,指定最大层级。
6. 加载实际纹理映射定义,即map表中对应的分类,需要覆盖哪张图。创建 Surface* surface;通过 SplatCatalog* catalog 加载xml文件,完成name与纹理图的实际对应。
7. 创建Zone* splatZone;来指定surface图要覆盖到地图的哪个区域。
8. 创建 SplatLayer* splatLayer;将dictionary、landCover、splatZone设置到splatLayer 图层.
9. 有了上面的基础内容,可以通过直接加载image的方式创建图层。读取图片osg::ref_ptr
10. 创建土地覆盖种群选项,GroundCoverBiomeOptions forestBiome;
将 新物种 treeSymbol ,放置到 "forest" 种群中。
11. 创建 GroundCoverOptions treeOptions 地面覆盖选项,将生物种群 forestBiome 加入到 treeOptions中。同时设置 GroundCover* trees = new GroundCover(treeOptions);
12. 为要添加的 树 ,新增一个区域 Zone* treeZone; treeZone->setGroundCover(trees);
13. 为这些树,创建地面覆盖图层 GroundCoverLayer* treeLayer;并将内容设置进去。
14. 最后将上述设置,组装到map中。
【注】其中9-13步骤,是概述不通过xml文件,加载纹理图的方式。
完整代码:
#include #include
#include
#include #include
#include #include #include
#include #include #include
#include #define LC "[splat] "using namespace osgEarth;
using namespace osgEarth::Util;
using namespace osgEarth::Splat;
using namespace osgEarth::Drivers;
using namespace osgEarth::Symbology;int
failed(const std::string& s) {OE_WARN << "FAILED: " << s << "\n";return -1;
}int
main(int argc, char** argv)
{osg::ArgumentParser arguments(&argc,argv);bool fromXML = arguments.find("--xml") >= 0;// Create a land cover dictionary.创建 陆地覆盖词典 对象LandCoverDictionary* dictionary;if (fromXML){LandCoverDictionaryOptions options;if (options.loadFromXML("D:/FreeXGIS/osgearth_gch/data/land_cover_dictionary.xml") == false)return failed("Cannot find XML land cover dictionary");dictionary = new LandCoverDictionary(options);}else{// 如果没有找到,则新建一个对象。下面的内容同xml中标签一致dictionary = new LandCoverDictionary();dictionary->setName("Land Cover Dictionary");dictionary->addClass("forest");dictionary->addClass("cropland");dictionary->addClass("grassland");dictionary->addClass("savanna");dictionary->addClass("swamp");dictionary->addClass("desert");dictionary->addClass("rock");dictionary->addClass("water"); dictionary->addClass("tundra");dictionary->addClass("urban");}// Create the data source for our land cover data and// map each value to a class in the dictionary.// This example uses the ESA GLOBCOVER data set from// http://due.esrin.esa.int/page_globcover.phpGDALOptions coverageDriver;// gdal驱动//coverageDriver.url() = "D:/FreeXGIS/osgearth_gch/data/splat/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif"; // 未找到,换一个coverageDriver.url() = "earth_image/heightfield/30m.tif";// 30m高程数据//coverageDriver.url() = "earth_image/globe/globel.tif";// 加载影像,拉进的过程中,控制台会输出错误信息coverageDriver.profile() = ProfileOptions("global-geodetic");// 创建地球// landCover 可序列化配置选项LandCoverCoverageLayerOptions coverage;coverage.driver() = coverageDriver;// 指定驱动coverage.warp() = 0.035;// 弯曲率?if (fromXML){if (coverage.loadMappingsFromXML("D:/FreeXGIS/osgearth_gch/data/land_cover_ESA_GLOBCOVER.xml") == false)return failed("Cannot find coverage mappings XML\n");}else{// 如果读取不到xml数据则创建。以下name值与dictionary的class值保持一致coverage.map(11, "cropland");// 农田coverage.map(14, "cropland");coverage.map(20, "cropland");coverage.map(30, "cropland");coverage.map(40, "forest");// 森林coverage.map(50, "forest");coverage.map(60, "forest");coverage.map(70, "forest");coverage.map(80, "forest");coverage.map(90, "forest");coverage.map(100, "forest");coverage.map(110, "grassland");// 草场coverage.map(120, "grassland");coverage.map(130, "savanna");// 稀树草原coverage.map(140, "savanna");coverage.map(150, "savanna");coverage.map(160, "swamp");// 沼泽coverage.map(170, "swamp");coverage.map(180, "swamp");coverage.map(190, "urban");// 城市coverage.map(200, "desert");// 沙漠coverage.map(210, "water");// 水coverage.map(220, "tundra");// 冻土带coverage.map(230, "water");}// Create the land cover layer for the map:// 为地图创建土地覆盖层:LandCoverLayer* landCover = new LandCoverLayer();landCover->setName("LandCover");landCover->options().cachePolicy() = CachePolicy::NO_CACHE;landCover->options().coverages().push_back(coverage);landCover->options().maxDataLevel() = 15u;// 最大层级// Next, load the definitions that map land cover classes to actual textures.// 接下来,加载将土地覆盖类映射到实际纹理的定义。Surface* surface = new Surface();// 在catalog中,指明了 每一个class对应的图,比如forest对应森林图SplatCatalog* catalog = SplatCatalog::read("D:/FreeXGIS/osgearth_gch/data/splat/splat_catalog.xml");if (catalog == 0L)return failed("Reading splat catalog");// 将读取到的策略,应用到surface中surface->setCatalog(catalog);// The zone designates the geographic area over which to apply the surface.// At least one zone is required and by default it covers the entire map.// 区域指定要应用曲面的地理区域。// 至少需要一个区域,默认情况下它覆盖整个地图。Zone* splatZone = new Zone();//定义一个区域,将特定表面或土地覆盖层限制在一组地理边界内。splatZone->setSurface(surface);// Create an imagery splatting layer that uses the configured land cover.// 使用配置的土地覆盖图 创建 图像splatting层。即将纹理贴在地形上SplatLayer* splatLayer = new SplatLayer();splatLayer->setName("Splat imagery");splatLayer->options().cachePolicy() = CachePolicy::NO_CACHE;splatLayer->setLandCoverDictionary(dictionary);splatLayer->setLandCoverLayer(landCover);splatLayer->zones().push_back(splatZone);// Now, the trees:// Load a tree image and make a billboard symbol from it:osg::ref_ptr tree = URI("D:/FreeXGIS/osgearth_gch/data/splat/pine2.png").getImage();if (tree.valid() == false)return failed("Loading tree image");// 标牌BillboardSymbol* treeSymbol = new BillboardSymbol();treeSymbol->setImage(tree.get());treeSymbol->width() = 12.0f;treeSymbol->height() = 16.0f;// Add this symbol to a "frest" biome.// 将此符号添加到“新”生物群落中。GroundCoverBiomeOptions forestBiome;forestBiome.biomeClasses() = "forest";forestBiome.symbols().push_back(treeSymbol);// Assemble the ground cover coniguration:// 组装覆盖地面的配置GroundCoverOptions treeOptions;treeOptions.biomes().push_back(forestBiome);treeOptions.maxDistance() = 15000.0;treeOptions.density() = 4.0;treeOptions.fill() = 0.85;treeOptions.brightness() = 2.0;// 亮度treeOptions.contrast() = 1.0;// 对比度GroundCover* trees = new GroundCover(treeOptions);//控制地面覆盖物外观的接口。// 新增一个区域,绘制treesZone* treeZone = new Zone();treeZone->setGroundCover(trees);// Now, create a ground cover layer for some trees.// 现在,为这些树创建地面覆盖层。GroundCoverLayer* treeLayer = new GroundCoverLayer();treeLayer->setName("Ground cover");treeLayer->options().lod() = 13;treeLayer->setLandCoverDictionary(dictionary);treeLayer->setLandCoverLayer(landCover);treeLayer->zones().push_back(treeZone);// Assemble the Map.组装地图Map* map = new Map();map->addLayer(dictionary);map->addLayer(landCover);map->addLayer(splatLayer);map->addLayer(treeLayer);// Activate the REX terrain engine (required for splatting)激活REX地形引擎osgEarth::Registry::instance()->overrideTerrainEngineDriverName() = "rex";// create a viewer:osgViewer::Viewer viewer(arguments);viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );viewer.setCameraManipulator( new EarthManipulator(arguments) );viewer.setSceneData(new MapNode(map));viewer.addEventHandler(new osgViewer::StatsHandler());viewer.addEventHandler(new osgViewer::WindowSizeHandler());return viewer.run();
}