天天看點

osgEarth使用筆記1——顯示一個數字地球

介紹了如何通過ogEarth生成一個數字地球,包括三維球體與二維地圖。

目錄

  • 1. 概述
  • 2. 實作
    • 2.1. 三維顯示
    • 2.2. 二維顯示

osgEarth支援.earth格式的檔案,裡面儲存了數字地球相關資訊的配置XML,隻需要讀取這個配置檔案,就可以直接得到相應的數字地球相關效果。但實際使用中還是感覺到有些不便,有些效果沒辦法儲存下來,是以很多時候還是使用代碼實作比較好。osgEarth最基礎的就是顯示一個數字地球了。

具體的實作代碼如下:

#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中自帶的。運作的效果如下:

osgEarth使用筆記1——顯示一個數字地球

除了顯示三維數字地球之外,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坐标轉換》)。

顯示的效果如下所示:

osgEarth使用筆記1——顯示一個數字地球

顯然,跟Web墨卡托投影的特性一樣,橢球被投影成了方形的平面地圖。