1. 概述
osgEarth支持.earth格式的文件,里面保存了數字地球相關信息的配置XML,只需要讀取這個配置文件,就可以直接得到相應的數字地球相關效果。但實際使用中還是感覺到有些不便,有些效果沒辦法保存下來,所以很多時候還是使用代碼實現比較好。osgEarth最基礎的就是顯示一個數字地球了。
2. 實現
2.1. 三維顯示
具體的實現代碼如下:
#include <Windows.h>
#include <iostream>
#include <string>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgEarth/MapNode>
#include <osgEarthDrivers/gdal/GDALOptions>
#include <osgEarthDrivers/cache_filesystem/FileSystemCache>
#include <osgEarth/ImageLayer>
#include <osgEarthUtil/EarthManipulator>
using namespace std;
int main()
{
osgEarth::ProfileOptions profileOpts;
//地圖配置:設置緩存目錄
osgEarth::Drivers::FileSystemCacheOptions cacheOpts;
string cacheDir = "D:/Work/OSGNewBuild/tmp";
cacheOpts.rootPath() = cacheDir;
//
osgEarth::MapOptions mapOpts;
mapOpts.cache() = cacheOpts;
mapOpts.profile() = profileOpts;
//創建地圖節點
osg::ref_ptr<osgEarth::Map> map = new osgEarth::Map(mapOpts);
osg::ref_ptr<osgEarth::MapNode> mapNode = new osgEarth::MapNode(map);
osgEarth::Drivers::GDALOptions gdal;
gdal.url() = "D:/Work/OSGNewBuild/osgearth-2.10.1/data/world.tif";
osg::ref_ptr<osgEarth::ImageLayer> layer = new osgEarth::ImageLayer("BlueMarble", gdal);
map->addLayer(layer);
osgViewer::Viewer viewer;
viewer.setSceneData(mapNode);
osg::ref_ptr< osgEarth::Util::EarthManipulator> mainManipulator = new osgEarth::Util::EarthManipulator;
viewer.setCameraManipulator(mainManipulator);
viewer.setUpViewInWindow(100, 100, 800, 600);
return viewer.run();
}
這里有兩個點值得注意,其一是使用了緩存機制,可以在瀏覽的時候變瀏覽邊生成緩存,所以設置了一個緩存目錄;其二是加載了一個底圖數據,是osgEarth中自帶的。運行的效果如下:
2.2. 二維顯示
除了顯示三維數字地球之外,osgEarth其實還可以顯示成平面地圖,只需要設置具體的參數就可以了。例如這里顯示成web墨卡托投影的二維平面地圖:
#include <Windows.h>
#include <iostream>
#include <string>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgEarth/MapNode>
#include <osgEarthDrivers/gdal/GDALOptions>
#include <osgEarthDrivers/cache_filesystem/FileSystemCache>
#include <osgEarth/ImageLayer>
#include <osgEarthUtil/EarthManipulator>
#include <gdal_priv.h>
using namespace std;
int main()
{
CPLSetConfigOption("GDAL_DATA", "D:/Work/OSGNewBuild/OpenSceneGraph-3.6.4/3rdParty/x64/gdal-data");
string wktString = "EPSG:3857"; //web墨卡托投影
//string wktString = "EPSG:4326"; //wgs84
osgEarth::ProfileOptions profileOpts;
profileOpts.srsString() = wktString;
//osgEarth::Bounds bs(535139, 3365107, 545139, 3375107);
//osgEarth::Bounds bs(73, 3, 135, 53);
//profileOpts.bounds() = bs;
//地圖配置:設置緩存目錄
osgEarth::Drivers::FileSystemCacheOptions cacheOpts;
string cacheDir = "D:/Work/OSGNewBuild/tmp";
cacheOpts.rootPath() = cacheDir;
//
osgEarth::MapOptions mapOpts;
mapOpts.cache() = cacheOpts;
mapOpts.coordSysType() = osgEarth::MapOptions::CSTYPE_PROJECTED;
mapOpts.profile() = profileOpts;
//創建地圖節點
osg::ref_ptr<osgEarth::Map> map = new osgEarth::Map(mapOpts);
osg::ref_ptr<osgEarth::MapNode> mapNode = new osgEarth::MapNode(map);
osgEarth::Drivers::GDALOptions gdal;
gdal.url() = "D:/Work/OSGNewBuild/osgearth-2.10.1/data/world.tif";
osg::ref_ptr<osgEarth::ImageLayer> layer = new osgEarth::ImageLayer("BlueMarble", gdal);
map->addLayer(layer);
osgViewer::Viewer viewer;
viewer.setSceneData(mapNode);
osg::ref_ptr< osgEarth::Util::EarthManipulator> mainManipulator = new osgEarth::Util::EarthManipulator;
viewer.setCameraManipulator(mainManipulator);
viewer.setUpViewInWindow(100, 100, 800, 600);
return viewer.run();
}
Web墨卡托投影平面坐標系的EPSG代碼是3857,所以只需要直接傳入相應的代碼就行了。對於比較復雜或者自定義的坐標系,其實也可以直接傳入wkt字符串,因為osgEarth是通過GDAL來處理空間坐標參考的,GDAL又是通過proj4來處理空間坐標參考的,所以這個時候需要通過GDAL設置一下環境變量GDAL_DATA(具體可以參見《GDAL坐標轉換》)。
顯示的效果如下所示:
顯然,跟Web墨卡托投影的特性一樣,橢球被投影成了方形的平面地圖。