前言
osgearth_geodetic_graticule示例,是展示网格控制的案例。可以修改网格的显隐、经纬度label的显隐及颜色、以及是否让经纬度label靠边缘显示、整个网格图层的显隐控制。
cmd 命令框输入:
osgearth_geodetic_graticuled.exe earth_image\china-simple.earth
效果
左上角是5个ui按钮
代码分析
#include <osg/Notify>
#include <osgViewer/Viewer>
#include <osgEarth/MapNode>
#include <osgEarth/GLUtils>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/GeodeticGraticule>
#include <osgEarthUtil/Controls>
#include <osgEarthUtil/ExampleResources>
#include <osgEarthSymbology/Style>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>
using namespace osgEarth;
using namespace osgEarth::Util;
using namespace osgEarth::Symbology;
namespace ui = osgEarth::Util::Controls;
// osgearth\src\osgEarthUtil\ExampleResources 文件中的宏定义如下:
#define OE_UI_HANDLER(X) \
struct X : public osgEarth::Util::Controls::ControlEventHandler { \
App& _app; X(App& app):_app(app) { } \
void onValueChanged(osgEarth::Util::Controls::Control*) { _app. X (); } \
void onClick(osgEarth::Util::Controls::Control*) { _app. X (); } }
int
usage( char** argv, const std::string& msg )
{
OE_NOTICE
<< msg << std::endl
<< "USAGE: " << argv[0] << " file.earth" << std::endl;
return -1;
}
const osg::Vec4 colors[4] = { osg::Vec4(1,1,1,1), osg::Vec4(1,0,0,1), osg::Vec4(1,1,0,1), osg::Vec4(0,1,0,1) };
struct App
{
// 显示经纬线,并自动放置label
GeodeticGraticule* graticule;
int gridColorIndex;
int edgeColorIndex;
App(GeodeticGraticule* g)
{
graticule = g;
gridColorIndex = 0;// 网格颜色索引,用于更改网格颜色
edgeColorIndex = 1;// 是否靠边显示经纬度的label
}
// 改变经纬度标签的颜色
void cycleStyles()
{
// Could also use the get/setGridLabelStyle API here, but this demonstrates
// changing the options and calling dirty() or apply().
// 改变label标签颜色
Style gridLabelStyle = graticule->options().gridLabelStyle().get();
gridColorIndex = (gridColorIndex+1)%4;
gridLabelStyle.getOrCreate<TextSymbol>()->fill()->color() = colors[gridColorIndex];
graticule->options().gridLabelStyle() = gridLabelStyle;
// 当label标签靠近边缘显示时,也同时改变边缘label的颜色
Style edgeLabelStyle = graticule->options().edgeLabelStyle().get(); //graticule->getEdgeLabelStyle();
edgeColorIndex = (edgeColorIndex+1)%4;
edgeLabelStyle.getOrCreate<TextSymbol>()->fill()->color() = colors[edgeColorIndex];
graticule->options().edgeLabelStyle() = edgeLabelStyle;
graticule->dirty();
}
// 切换网格标签可见性
void toggleGridLabels()
{
bool vis = graticule->getGridLabelsVisible();
graticule->setGridLabelsVisible(!vis);
}
// 切换标签到边缘显示或者网格上显示
void toggleEdgeLabels()
{
// 需要先判断是否地球放大到可以在边缘显示label
bool vis = graticule->getEdgeLabelsVisible();
graticule->setEdgeLabelsVisible(!vis);
}
// 切换网格可见性
void toggleGrid()
{
bool vis = graticule->getGridLinesVisible();
graticule->setGridLinesVisible(!vis);
}
// 切换图层可见性(网格和标签一起控制)
void toggleLayer()
{
bool vis = graticule->getVisible();
graticule->setVisible(!vis);
}
};
// 定义一个宏,继承osgEarth::Util::Controls::ControlEventHandler,
// 实现以下结构体的点击方法
// new 每一个结构体时,需要传入app,且app对应的方法与该结构体同名。
OE_UI_HANDLER(cycleStyles);
OE_UI_HANDLER(toggleGridLabels);
OE_UI_HANDLER(toggleEdgeLabels);
OE_UI_HANDLER(toggleGrid);
OE_UI_HANDLER(toggleLayer);
ui::Control* makeUI(App& app)
{
ui::VBox* b = new ui::VBox();// 垂直布局
b->addChild(new ui::ButtonControl("Change styles", new cycleStyles(app)));// 改变经纬度标签的颜色
b->addChild(new ui::ButtonControl("Toggle grid labels", new toggleGridLabels(app)));// 切换经纬度label显隐
b->addChild(new ui::ButtonControl("Toggle edge labels", new toggleEdgeLabels(app)));// 当地球放大后,可以实现切换label在边缘显示和中间显示
b->addChild(new ui::ButtonControl("Toggle grid visibility", new toggleGrid(app)));// 切换经纬网格显隐,label保留
b->addChild(new ui::ButtonControl("Toggle layer visibility", new toggleLayer(app)));// 经纬网格和label一起显隐,即整个图层的显隐
return b;
}
int
main(int argc, char** argv)
{
osg::ArgumentParser arguments(&argc,argv);
osgViewer::Viewer viewer(arguments);
// 初始化默认状态
GLUtils::setGlobalDefaults(viewer.getCamera()->getOrCreateStateSet());
// 设置图形操作以调用查看器图形窗口的实现。
viewer.setRealizeOperation(new GL3RealizeOperation());
// 所有示例均设置为-1.0,猜测应该是禁用 最小特征剔除像素尺寸 功能
viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
// load the .earth file from the command line.
MapNode* mapNode = MapNode::load(arguments);
if ( !mapNode )
return usage( argv, "Failed to load a map from the .earth file" );
viewer.setSceneData(mapNode);
viewer.setCameraManipulator( new EarthManipulator() );
// 经纬网格类
GeodeticGraticule* graticule = new GeodeticGraticule();
// 将此类加入到map图层中
mapNode->getMap()->addLayer(graticule);
// ui控制
App app(graticule);
// 将控件与OSG视图关联。
ui::ControlCanvas* canvas = ui::ControlCanvas::getOrCreate(&viewer);
// 将ui控件组加入到canvas中
canvas->addControl(makeUI(app));
// 设置事件处理器和操作器
viewer.addEventHandler(new osgViewer::StatsHandler());
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
return viewer.run();
}