osgEarth示例分析——osgearth_splat

news2024/11/15 17:46:14

前言

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文件,加载纹理图的方式。

完整代码:

#include <osgViewer/Viewer>

#include <osgEarth/MapNode>
#include <osgEarth/Registry>
#include <osgEarth/LandCoverLayer>

#include <osgEarthSplat/SplatLayer>
#include <osgEarthSplat/GroundCoverLayer>

#include <osgEarthDrivers/gdal/GDALOptions>

#include <osgEarthUtil/ExampleResources>
#include <osgEarthUtil/EarthManipulator>

#include <osgEarthSymbology/BillboardSymbol>

#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>


#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.php
    GDALOptions 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<osg::Image> 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);//控制地面覆盖物外观的接口。

	// 新增一个区域,绘制trees
    Zone* 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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/69423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云计算与传统计算的区别有哪些?

目前&#xff0c;许多企业依赖传统计算&#xff0c;而一些企业也正在迁移到云计算。原因是两者都有各自的优势点&#xff0c;这就是为什么对企业来说&#xff0c;在两者之间进行选择可能会变得有点困难。 什么是传统计算? 传统计算的概念是不言而喻的。传统上&#xff0c;物理…

[附源码]Python计算机毕业设计Django兴达五金日杂批发商店管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

微服务框架 SpringCloud微服务架构 21 RestClient 操作文档 21.5 批量导入文档

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构21 RestClient 操作文档21.5 批量导入文档21.5.1 批量导入文档21 RestClie…

【Java面试】说一说JDK1.6之后对synchronized的优化

文章目录为什么synchronized性能低下&#xff1f;JDK1.6对synchronized的优化偏向锁(无锁状态)轻量级锁(自旋)重量级锁(阻塞)这些锁的优缺点早期JDK对synchronized的实现是重量级的&#xff0c;每一次的获取锁都需要请求OS。 而在大部分情况下&#xff0c;同步方法是运行在单线…

若依权限校验源码分析

若依的权限校验实现原理就是AOP自定义注解&#xff0c;代码并不多&#xff0c;debug跟一遍之后很容易理解&#xff0c;详细流程整理如下 用到的类 注解类RequiresLogin、RequiresPermissions、RequiresRoles&#xff0c;分别用于登录认证、权限认证和角色认证切面类PreAuthor…

极米H5评测:极米H5投影仪参数如何?极米H5值得入手吗?

作为家用智能投影领域的佼佼者&#xff0c;极米在上个月结束的双11活动中&#xff0c;实现了全网成交总额破8亿&#xff0c;并获得天猫、京东和抖音投影品类销量和GMV双第一的成绩&#xff0c;同时这也是极米连续第九次成为投影品类冠军。能够实现如此优秀的成绩&#xff0c;也…

JS逆向之webpack 通用扣取思路

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰,更不会影响计算机信息系统的正常运行。不得将代码用于非法用途,如侵立删!标题 环境 win10chrome106目标站:aHR0cHM6Ly93d3cuZ205OS5jb20v 加密参数 password: K6YEmQrNy%2FQgdnac…

安卓玩机搞机技巧综合资源------EROFS分区格式 小米红米机型分区类型 刷写recovery方法列举【三】

接上篇 安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 【一】 安卓玩机搞机技巧综合资源------开机英文提示解决dm-verity corruption your device is corrupt. 设备内部报错 AB分区等等【二】 &#x1f49d;&#x1f49d;&#x1f49d;&#x1f49d…

高性能数据访问中间件 OBProxy(七):安全、协议和监控

经过本系列前六篇文章的分布式特性介绍&#xff0c;相信大家已经了解了 OBProxy 在 OceanBase 数据库整体架构下的作用。本篇文章我们将换一个视角&#xff0c;介绍一些偏“中间件”的功能&#xff1a;安全、协议和监控功能。 从 OBProxy 整体来看&#xff0c;安全、协议和监控…

Scratch少儿编程英语教程

Scratch少儿编程英语教程 在 Scratch 中学习编程、创建游戏、玩得开心&#xff01;致未来编码员的家长和老师 课程英文名&#xff1a;Programming for Kids and Beginners Learn to Code in Scratch 此视频教程共5.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印…

网上图书商城小程序毕业设计,微信图书商城小程序系统设计与实现,微信小程序毕业设计论文怎么写毕设源码开题报告需求分析怎么做

功能清单 【后台管理员功能】 会员列表&#xff1a;查看所有注册会员信息&#xff0c;支持删除 录入资讯&#xff1a;录入资讯标题、内容等信息 管理资讯&#xff1a;查看已录入资讯列表&#xff0c;支持删除和修改 广告设置&#xff1a;上传图片和设置小程序首页轮播图广告地…

QT(3)-QTableView

QTableView1 说明2 常用函数2.1 clearSpans2.2 setSpan2.3 columnAt2.4 rowAt2.5 columnSpan2.6 rowSpan2.7 columnViewportPosition2.8 rowViewportPosition2.9 列宽、行高2.9.1 columnWidth2.9.2 rowHeight2.9.3 setColumnWidth2.9.4 setRowHeight2.9.5 resizeColumnToConten…

gitlab结合semantic-release自动化发布npm插件(二)

前言 在内部组织架构开发npm包时&#xff0c;很多人会想到规范问题&#xff0c;难道按前文gitlab结合semantic-release自动化规范git流程(一)所描述根据git的CI/CD就可以了吗&#xff0c;每次发布都会版本对应的新增&#xff0c;而往往新增的版本不是我们所需要的&#xff0c;…

如何去掉视频上的水印文字?视频去水印方法大分享

我们在网上看到喜欢的视频&#xff0c;都会保存下来&#xff0c;经常能够看到保存下来的这些视频中都带有水印。这些带有水印的视频在后期的观看过程中&#xff0c;会很影响整个画面&#xff0c;所以我们在保存下来后&#xff0c;可以选择将视频中的水印去除。那么视频如何去水…

物料管理系统最基本的功能有哪些?

随着企业信息化的快速发展&#xff0c;传统企业的企业快速增长与管理水平、手段滞后之间的矛盾已成为影响企业发展的重要因素和阻碍企业战略目标实现的主要矛盾。尤其是对于一些传统的中小型制造企业企业而言&#xff0c;以往的信息化系统所做的相应规划已经完全不能适用于高速…

【论文阅读32】《Texture Defragmentation for Photo-Reconstructed 3D Models》

目录 1 introduction 2 overview 3 Related work 3.1 Single-patch Mesh Parametrization 3.2 Global Mesh Parametrization 3.3 Signal-Specialized UV Maps 3.4 Mesh repairing 3.5 Alleviating the effect of seams 3.6 Packing of texture charts 4 Phases of the algorith…

初阶数据结构学习记录——열넷 排序(3)

归并排序 归并的思路其实和二叉树&#xff0c;快排都有点像。归并希望左、右半区间有序。和快排不同&#xff0c;先分裂后排序&#xff0c;一半一半分&#xff0c;分到最后每个区间只剩一个1个数字&#xff0c;这个区间一定是有序的&#xff0c;因为只有一个数字&#xff0c;往…

kubernetes的基本使用

文章目录kubernetes的基本使用1、部署方式1、部署方式的演进图2、各部署方式的特点2、架构的简单说明1、架构简图2、各组件说明1、控制平面组件&#xff08;Control Plane Components&#xff09;1、kube-apiserver2、etcd3、kube-scheduler4、kube-controller-manager5、cloud…

Apache HTTPD 换行解析漏洞

漏洞介绍&#xff1a; Apache HTTPD是一款HTTP服务器&#xff0c;它可以通过mod_php来运行PHP网页。 影响版本&#xff1a;Apache 2.4.0~2.4.29 存在一个解析漏洞&#xff1b;在解析PHP时&#xff0c;1.php\x0A将被按照PHP后缀进行解析&#xff0c;导致绕过一些服务器的安全策…

Windows中cmd命令窗口一些有用的小技巧命令

使用小功能记录 命令功能help显示所有dos命令&#xff0c;help >> cmd.txt,会把命令输出成文档altprtscreen快速截取命令行窗口esc清除当前命令行tab补全路径&#xff0c;若知道路径开头可快速补全&#xff0c;包含隐藏文件&#xff0c;但文件夹多又不知道路径开始字符时…