开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 27 天
1 坐标系节点
坐标系节点(osg::CoordinateSystemNode)继承自 osg::Group节点,它的主要作用是使一个场景的 对象关联一个坐标系统。通常的坐标系统类型有WKT、PROJ4和USGS。它通常与osg::EllipsoidModel 节点一起使用,osg:EllipsoidModel 节点(椭圆体模型节点)主要用来模拟天体,如太阳、行星和月亮等,其默认情况下是地球体。
osg::EllipsoidModel 节点还有一个作用就是实现经纬度与坐标之间的转换,这样可以实现天体椭圆体模型子节点的精确定位。当读者建立地球数据库时,这个节点会非常有用,可以根据地球椭圆体模型实现子节点的精确定位。
对于WKT坐标系,可能很多人都不理解,它的定义包括以下几个方面:
- 一个全局的坐标系统名称。
- 一个地理坐标系统的名称。
- 一个数据识别器。
- 一个椭球体的名称、长半轴、扁率。
- 本初子午线的名称和它到格林尼治的偏移量。
- 投影类型(如横轴墨卡托投影)。
- 投影参数(如中央子午线)。
- 单位名称,到米或弧度的转换因数。
- 各轴的名称和顺序。
- 由授权单位(如EPSG)预先定义的大多数坐标系统的代码。
这样解释可能比较好理解,关于地理坐标系的知识,读者可以查阅相关资料。
osg::GoordinateSystemNode的继承关系图如下图所示。
2 坐标系节点示例
坐标系节点(osg::CoordinateSystemNode)示例的代码如程序清单所示。
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/CoordinateSystemNode>
#include <osg/ShapeDrawable>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include "utility.h"
#include <iostream>
// 绘制一个地球
osg::ref_ptr<osg::Node> createEarth()
{
// 创建一个球体
osg::ref_ptr<osg::ShapeDrawable> sd = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0, 0.0, 0.0), osg::WGS_84_RADIUS_POLAR));
// 添加到叶子节点
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(sd.get());
// 设置纹理
std::string filename(GetCurrentPath() + "\\Data\\Images\\land_shallow_topo_2048.jpg");
geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile(filename)));
// 创建坐标系节点
osg::ref_ptr<osg::CoordinateSystemNode> csn = new osg::CoordinateSystemNode;
// 设置椭圆体模型,默认的坐标系WGS_84
csn->setEllipsoidModel(new osg::EllipsoidModel);
// 添加子节点
csn->addChild(geode.get());
return csn.get();
}
int main()
{
// 创建Viewer对象,场景浏览器
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
// 创建场景组根节点
osg::ref_ptr<osg::Group> root = new osg::Group();
// 添加到场景
root->addChild(createEarth());
// 优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
// 设置窗口大小
setWindowSize(viewer.get(), 600, 500, "CoordinateSystemNode");
// 设置场景数据
viewer->setSceneData(root.get());
// 初始化并创建窗口
viewer->realize();
// 开始渲染
viewer->run();
return 0;
}
效果图
动态效果图