osgEarth示例分析——osgearth_geodetic_graticule

前言

osgearth_geodetic_graticule示例,是展示网格控制的案例。可以修改网格的显隐、经纬度label的显隐及颜色、以及是否让经纬度label靠边缘显示、整个网格图层的显隐控制。

cmd 命令框输入:

osgearth_geodetic_graticuled.exe earth_image\china-simple.earth

效果

左上角是5个ui按钮

osgEarth示例分析——osgearth_geodetic_graticule_第1张图片

 代码分析

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 

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()->fill()->color() = colors[gridColorIndex];
        graticule->options().gridLabelStyle() = gridLabelStyle;
		// 当label标签靠近边缘显示时,也同时改变边缘label的颜色
        Style edgeLabelStyle = graticule->options().edgeLabelStyle().get(); //graticule->getEdgeLabelStyle();
        edgeColorIndex = (edgeColorIndex+1)%4;
		edgeLabelStyle.getOrCreate()->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();
}

你可能感兴趣的:(osgEarth,c++)