当前位置:   article > 正文

osgEarth示例分析——osgearth_splat

osgearth

前言

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<osg::Image> tree; 创建标牌 BillboardSymbol* treeSymbol ;将tree传入treeSymbol; 

10. 创建土地覆盖种群选项,GroundCoverBiomeOptions forestBiome;
将 新物种 treeSymbol ,放置到 "forest" 种群中。

11. 创建 GroundCoverOptions treeOptions 地面覆盖选项,将生物种群 forestBiome 加入到 treeOptions中。同时设置 GroundCover* trees = new GroundCover(treeOptions);

12. 为要添加的 树 ,新增一个区域 Zone* treeZone; treeZone->setGroundCover(trees);

13. 为这些树,创建地面覆盖图层 GroundCoverLayer* treeLayer;并将内容设置进去。

  •     treeLayer->setLandCoverDictionary(dictionary);
  •     treeLayer->setLandCoverLayer(landCover);
  •     treeLayer->zones().push_back(treeZone);


14. 最后将上述设置,组装到map中。    

  •     Map* map = new Map();
  •     map->addLayer(dictionary);
  •     map->addLayer(landCover);
  •     map->addLayer(splatLayer);

 
【注】其中9-13步骤,是概述不通过xml文件,加载纹理图的方式。

完整代码:

  1. #include <osgViewer/Viewer>
  2. #include <osgEarth/MapNode>
  3. #include <osgEarth/Registry>
  4. #include <osgEarth/LandCoverLayer>
  5. #include <osgEarthSplat/SplatLayer>
  6. #include <osgEarthSplat/GroundCoverLayer>
  7. #include <osgEarthDrivers/gdal/GDALOptions>
  8. #include <osgEarthUtil/ExampleResources>
  9. #include <osgEarthUtil/EarthManipulator>
  10. #include <osgEarthSymbology/BillboardSymbol>
  11. #include <osgGA/StateSetManipulator>
  12. #include <osgViewer/ViewerEventHandlers>
  13. #define LC "[splat] "
  14. using namespace osgEarth;
  15. using namespace osgEarth::Util;
  16. using namespace osgEarth::Splat;
  17. using namespace osgEarth::Drivers;
  18. using namespace osgEarth::Symbology;
  19. int
  20. failed(const std::string& s) {
  21. OE_WARN << "FAILED: " << s << "\n";
  22. return -1;
  23. }
  24. int
  25. main(int argc, char** argv)
  26. {
  27. osg::ArgumentParser arguments(&argc,argv);
  28. bool fromXML = arguments.find("--xml") >= 0;
  29. // Create a land cover dictionary.创建 陆地覆盖词典 对象
  30. LandCoverDictionary* dictionary;
  31. if (fromXML)
  32. {
  33. LandCoverDictionaryOptions options;
  34. if (options.loadFromXML("D:/FreeXGIS/osgearth_gch/data/land_cover_dictionary.xml") == false)
  35. return failed("Cannot find XML land cover dictionary");
  36. dictionary = new LandCoverDictionary(options);
  37. }
  38. else
  39. {
  40. // 如果没有找到,则新建一个对象。下面的内容同xml中标签一致
  41. dictionary = new LandCoverDictionary();
  42. dictionary->setName("Land Cover Dictionary");
  43. dictionary->addClass("forest");
  44. dictionary->addClass("cropland");
  45. dictionary->addClass("grassland");
  46. dictionary->addClass("savanna");
  47. dictionary->addClass("swamp");
  48. dictionary->addClass("desert");
  49. dictionary->addClass("rock");
  50. dictionary->addClass("water");
  51. dictionary->addClass("tundra");
  52. dictionary->addClass("urban");
  53. }
  54. // Create the data source for our land cover data and
  55. // map each value to a class in the dictionary.
  56. // This example uses the ESA GLOBCOVER data set from
  57. // http://due.esrin.esa.int/page_globcover.php
  58. GDALOptions coverageDriver;// gdal驱动
  59. //coverageDriver.url() = "D:/FreeXGIS/osgearth_gch/data/splat/GLOBCOVER_L4_200901_200912_V2.3_Ant_tiled.tif"; // 未找到,换一个
  60. coverageDriver.url() = "earth_image/heightfield/30m.tif";// 30m高程数据
  61. //coverageDriver.url() = "earth_image/globe/globel.tif";// 加载影像,拉进的过程中,控制台会输出错误信息
  62. coverageDriver.profile() = ProfileOptions("global-geodetic");// 创建地球
  63. // landCover 可序列化配置选项
  64. LandCoverCoverageLayerOptions coverage;
  65. coverage.driver() = coverageDriver;// 指定驱动
  66. coverage.warp() = 0.035;// 弯曲率?
  67. if (fromXML)
  68. {
  69. if (coverage.loadMappingsFromXML("D:/FreeXGIS/osgearth_gch/data/land_cover_ESA_GLOBCOVER.xml") == false)
  70. return failed("Cannot find coverage mappings XML\n");
  71. }
  72. else
  73. {
  74. // 如果读取不到xml数据则创建。以下name值与dictionary的class值保持一致
  75. coverage.map(11, "cropland");// 农田
  76. coverage.map(14, "cropland");
  77. coverage.map(20, "cropland");
  78. coverage.map(30, "cropland");
  79. coverage.map(40, "forest");// 森林
  80. coverage.map(50, "forest");
  81. coverage.map(60, "forest");
  82. coverage.map(70, "forest");
  83. coverage.map(80, "forest");
  84. coverage.map(90, "forest");
  85. coverage.map(100, "forest");
  86. coverage.map(110, "grassland");// 草场
  87. coverage.map(120, "grassland");
  88. coverage.map(130, "savanna");// 稀树草原
  89. coverage.map(140, "savanna");
  90. coverage.map(150, "savanna");
  91. coverage.map(160, "swamp");// 沼泽
  92. coverage.map(170, "swamp");
  93. coverage.map(180, "swamp");
  94. coverage.map(190, "urban");// 城市
  95. coverage.map(200, "desert");// 沙漠
  96. coverage.map(210, "water");// 水
  97. coverage.map(220, "tundra");// 冻土带
  98. coverage.map(230, "water");
  99. }
  100. // Create the land cover layer for the map:
  101. // 为地图创建土地覆盖层:
  102. LandCoverLayer* landCover = new LandCoverLayer();
  103. landCover->setName("LandCover");
  104. landCover->options().cachePolicy() = CachePolicy::NO_CACHE;
  105. landCover->options().coverages().push_back(coverage);
  106. landCover->options().maxDataLevel() = 15u;// 最大层级
  107. // Next, load the definitions that map land cover classes to actual textures.
  108. // 接下来,加载将土地覆盖类映射到实际纹理的定义。
  109. Surface* surface = new Surface();
  110. // 在catalog中,指明了 每一个class对应的图,比如forest对应森林图
  111. SplatCatalog* catalog = SplatCatalog::read("D:/FreeXGIS/osgearth_gch/data/splat/splat_catalog.xml");
  112. if (catalog == 0L)
  113. return failed("Reading splat catalog");
  114. // 将读取到的策略,应用到surface中
  115. surface->setCatalog(catalog);
  116. // The zone designates the geographic area over which to apply the surface.
  117. // At least one zone is required and by default it covers the entire map.
  118. // 区域指定要应用曲面的地理区域。
  119. // 至少需要一个区域,默认情况下它覆盖整个地图。
  120. Zone* splatZone = new Zone();//定义一个区域,将特定表面或土地覆盖层限制在一组地理边界内。
  121. splatZone->setSurface(surface);
  122. // Create an imagery splatting layer that uses the configured land cover.
  123. // 使用配置的土地覆盖图 创建 图像splatting层。即将纹理贴在地形上
  124. SplatLayer* splatLayer = new SplatLayer();
  125. splatLayer->setName("Splat imagery");
  126. splatLayer->options().cachePolicy() = CachePolicy::NO_CACHE;
  127. splatLayer->setLandCoverDictionary(dictionary);
  128. splatLayer->setLandCoverLayer(landCover);
  129. splatLayer->zones().push_back(splatZone);
  130. // Now, the trees:
  131. // Load a tree image and make a billboard symbol from it:
  132. osg::ref_ptr<osg::Image> tree = URI("D:/FreeXGIS/osgearth_gch/data/splat/pine2.png").getImage();
  133. if (tree.valid() == false)
  134. return failed("Loading tree image");
  135. // 标牌
  136. BillboardSymbol* treeSymbol = new BillboardSymbol();
  137. treeSymbol->setImage(tree.get());
  138. treeSymbol->width() = 12.0f;
  139. treeSymbol->height() = 16.0f;
  140. // Add this symbol to a "frest" biome.
  141. // 将此符号添加到“新”生物群落中。
  142. GroundCoverBiomeOptions forestBiome;
  143. forestBiome.biomeClasses() = "forest";
  144. forestBiome.symbols().push_back(treeSymbol);
  145. // Assemble the ground cover coniguration:
  146. // 组装覆盖地面的配置
  147. GroundCoverOptions treeOptions;
  148. treeOptions.biomes().push_back(forestBiome);
  149. treeOptions.maxDistance() = 15000.0;
  150. treeOptions.density() = 4.0;
  151. treeOptions.fill() = 0.85;
  152. treeOptions.brightness() = 2.0;// 亮度
  153. treeOptions.contrast() = 1.0;// 对比度
  154. GroundCover* trees = new GroundCover(treeOptions);//控制地面覆盖物外观的接口。
  155. // 新增一个区域,绘制trees
  156. Zone* treeZone = new Zone();
  157. treeZone->setGroundCover(trees);
  158. // Now, create a ground cover layer for some trees.
  159. // 现在,为这些树创建地面覆盖层。
  160. GroundCoverLayer* treeLayer = new GroundCoverLayer();
  161. treeLayer->setName("Ground cover");
  162. treeLayer->options().lod() = 13;
  163. treeLayer->setLandCoverDictionary(dictionary);
  164. treeLayer->setLandCoverLayer(landCover);
  165. treeLayer->zones().push_back(treeZone);
  166. // Assemble the Map.组装地图
  167. Map* map = new Map();
  168. map->addLayer(dictionary);
  169. map->addLayer(landCover);
  170. map->addLayer(splatLayer);
  171. map->addLayer(treeLayer);
  172. // Activate the REX terrain engine (required for splatting)激活REX地形引擎
  173. osgEarth::Registry::instance()->overrideTerrainEngineDriverName() = "rex";
  174. // create a viewer:
  175. osgViewer::Viewer viewer(arguments);
  176. viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
  177. viewer.setCameraManipulator( new EarthManipulator(arguments) );
  178. viewer.setSceneData(new MapNode(map));
  179. viewer.addEventHandler(new osgViewer::StatsHandler());
  180. viewer.addEventHandler(new osgViewer::WindowSizeHandler());
  181. return viewer.run();
  182. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/612234
推荐阅读
相关标签
  

闽ICP备14008679号