osgEarth示例分析——osgearth_imageoverlay

前言

imageroverlay示例,在地球上贴图,并且添加控制面板,控制面板上有:mini图标、复选框(控制图片显隐)、图标名称的name、图片的透明度、Edit(控制编辑点的显隐)。

在原有的基础上,本示例又添加了changeImage(更换图片) 和 坐标位置(拖动编辑点,实时更新中心点的坐标)。

执行命令如下。图片参数,直接写入代码中。

osgearth_imageoverlayd.exe earth_image\china-simple.earth

执行效果

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

osgEarth示例分析——osgearth_imageoverlay_第2张图片

 

结构分析

osgEarth示例分析——osgearth_imageoverlay_第3张图片

代码分析

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

#include 
#include 

#include 
#include 

using namespace osgEarth;
using namespace osgEarth::Annotation;
using namespace osgEarth::Util;
using namespace osgEarth::Util::Controls;

// 布局根结点
static Grid* s_layerBox = NULL;

// 创建布局
osg::Node*
createControlPanel( osgViewer::View* view )
{
    ControlCanvas* canvas = ControlCanvas::getOrCreate( view );

    // the outer container:
    s_layerBox = new Grid();
    s_layerBox->setBackColor(0,0,0,0.5);// 设置布局背景色
    s_layerBox->setMargin( 10 ); // 外边距
    s_layerBox->setPadding( 10 );// 内边距
    s_layerBox->setChildSpacing( 10 );// 布局内子类的间距
    s_layerBox->setChildVertAlign( Control::ALIGN_CENTER );// 子类水平居中
    s_layerBox->setAbsorbEvents( true );// 设置接收事件
    s_layerBox->setVertAlign( Control::ALIGN_BOTTOM );// 垂直底部

    canvas->addControl( s_layerBox );    
    return canvas;
}

int
usage( const std::string& msg )
{
    OE_NOTICE << msg << std::endl;
    OE_NOTICE << "USAGE: osgearth_imageoverlay file.earth" << std::endl;
    OE_NOTICE << "   --image  xmin ymin xmax ymax : An image to overlay and it's bounds" << std::endl;        
    OE_NOTICE << "   --vert                             : Move individual verts when editing" << std::endl;

        
    return -1;
}

// 透明度控制
struct OpacityHandler : public ControlEventHandler
{
    OpacityHandler( ImageOverlay* overlay ) : _overlay(overlay) { }
    void onValueChanged( Control* control, float value ) {
        _overlay->setAlpha( value );
    }
    ImageOverlay* _overlay;
};

// checkbox的值更改
struct EnabledHandler : public ControlEventHandler
{
    EnabledHandler( ImageOverlay* overlay ) :  _overlay(overlay) { }
    void onValueChanged( Control* control, bool value ) {
        _overlay->setNodeMask( value ? ~0 : 0 );
    }
    ImageOverlay* _overlay;
};

// label标签编辑事件,滑块右侧的edit的标签,进行编辑点显隐的切换
struct EditHandler : public ControlEventHandler
{
    EditHandler( ImageOverlay* overlay, osgViewer::Viewer* viewer, osg::Node* editor) :
      _overlay(overlay),
      _viewer(viewer),
      _editor(editor){ }

    void onClick( Control* control, int mouseButtonMask ) {        
        if (_editor->getNodeMask() != ~0)
        {
            static_cast(control)->setText( "Finish" );
            _editor->setNodeMask(~0);
        }
        else
        {
            static_cast(control)->setText( "Edit" );
            _editor->setNodeMask(0);
        }
    }

    ImageOverlay* _overlay;
    osgViewer::Viewer* _viewer;
    osg::Node* _editor;
};

// 获取点击鼠标事件,然后将用image替换原来的图片
struct ChangeImageHandler : public ControlEventHandler
{
    ChangeImageHandler( osg::Image* image, ImageOverlay* overlay, ImageControl* preview) :
      _image(image),
      _overlay(overlay),
      _preview(preview){ }

    void onClick( Control* control, int mouseButtonMask ) {
        _overlay->setImage( _image.get() );
        _preview->setImage( _image.get() );
    }
    ImageOverlay* _overlay;
    osg::ref_ptr< osg::Image > _image;
    osg::ref_ptr< ImageControl> _preview;
};

// 覆盖图更新位置回调方法
struct UpdateLabelCallback : public ImageOverlay::ImageOverlayCallback
{
    UpdateLabelCallback(LabelControl* label, ImageOverlay* overlay, ImageOverlay::ControlPoint controlPoint):
      _label(label),
      _overlay(overlay),
      _controlPoint(controlPoint)
    {

    }
	// 当覆盖图被移动时,会打印输出位置信息到label标签上
    virtual void onOverlayChanged()
    {
        osg::Vec2d location = _overlay->getControlPoint( _controlPoint );
        std::stringstream ss;
        ss << location.y() << ", " << location.x();
        std::string str;
        str = ss.str();
        _label->setText( str );
    }
    

    osg::ref_ptr< LabelControl > _label;
    osg::ref_ptr< ImageOverlay > _overlay;
    ImageOverlay::ControlPoint _controlPoint;
};



int
main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);
	// osg::DisplaySettings 封装所需和已设置的视觉效果以及立体观看的状态类
    osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );


    std::vector< std::string > imageFiles;
    std::vector< Bounds > imageBounds;

    //Read in the image files
	// 可以通过命令窗口输入文件路径,图片尺寸,并且尺寸是经纬度
    std::string filename;
    Bounds bounds;// 继承自包围盒类
    while (arguments.read("--image", filename, bounds.xMin(), bounds.yMin(), bounds.xMax(), bounds.yMax()))
    {
        imageFiles.push_back( filename );
        imageBounds.push_back( bounds );
    }
	// 
    if (imageFiles.empty())
    {
      imageFiles.push_back("../data/m2525_air.png");// 仅支持png ,加载gif jpg,会显示黑图
      imageBounds.push_back( Bounds(-100, 30, -90, 40) );

	  // 继续追加一张图
	  imageFiles.push_back("../data/m2525_air.png");
	  imageBounds.push_back(Bounds(-120, 30, -110, 40));
    }
 

    bool moveVert = arguments.read("--vert");

    // load the .earth file from the command line.加载map地图
    osg::ref_ptr earthNode = osgDB::readNodeFiles( arguments );
    if (!earthNode.valid())
        return usage( "Unable to load earth model." );

    osgViewer::Viewer viewer(arguments);
    // 创建操作器并添加到视景器viewer
    EarthManipulator* manip = new EarthManipulator();
    viewer.setCameraManipulator( manip );

    osg::Group* root = new osg::Group();
    root->addChild( earthNode.get() );

    //Create the control panel 创建控制面板
    root->addChild( createControlPanel(&viewer) );

    viewer.setSceneData( root );
    // 获取mapNode
    osgEarth::MapNode* mapNode = osgEarth::MapNode::findMapNode( earthNode.get() );
    if ( mapNode )
    {
		// 当处理多张图时,会添加多组控件
        for (unsigned int i = 0; i < imageFiles.size(); i++)
        {
            std::string imageFile = imageFiles[i];
            //Read the image file and play it if it's a movie 如果传入的图多个,则读取并播放
            osg::ref_ptr image = osgDB::readRefImageFile(imageFile);
            if (image.valid())
            {
                osg::ImageStream* is = dynamic_cast(image.get());
                if (is)
                {
					std::cout << "is->play()" << std::endl;
                    is->play();
                }
            }

            //Create a new ImageOverlay and set it's bounds,创建覆盖图并设置图的边界
            //ImageOverlay* overlay = new ImageOverlay(mapNode->getMap()->getProfile()->getSRS()->getEllipsoid(), image);        
            ImageOverlay* overlay = new ImageOverlay(mapNode);
            overlay->setImage( image.get() );
            overlay->setBounds(imageBounds[i]);
            // 覆盖图加入到mapNode
            mapNode->addChild( overlay );


            //Create a new ImageOverlayEditor and set it's node mask to 0 to hide it initially
			// 遮盖图编辑器
            osg::Node* editor = new ImageOverlayEditor( overlay, moveVert);
            editor->setNodeMask( 1 );//编辑器的绿色点是否可见
            mapNode->addChild( editor );      
            
            // Add an image preview 预览图
            ImageControl* imageCon = new ImageControl( image.get() );
            imageCon->setSize( 64, 64 );
            imageCon->setVertAlign( Control::ALIGN_CENTER );
            s_layerBox->setControl( 0, i, imageCon );            


            //Add some controls    复选框控件    
            CheckBoxControl* enabled = new CheckBoxControl( true );
            enabled->addEventHandler( new EnabledHandler(overlay) );// checkbox控件的事件处理器,仅控制地图上的覆盖图显隐
            enabled->setVertAlign( Control::ALIGN_CENTER );
            s_layerBox->setControl( 1, i, enabled );

            //The overlay name 获取到图片的名称
            LabelControl* name = new LabelControl( osgDB::getSimpleFileName( imageFile) );      
            name->setVertAlign( Control::ALIGN_CENTER );
			name->addEventHandler(new EnabledHandler(overlay));
			//name->addEventHandler(new ChangeImageHandler(image, overlay, imageCon));// 同时控制地图上的覆盖图和预览图显隐
            s_layerBox->setControl( 2, i, name );

            // an opacity slider 滑块,更改透明度
            HSliderControl* opacity = new HSliderControl( 0.0f, 1.0f, overlay->getAlpha() );// 设置范围
            opacity->setWidth( 125 );
            opacity->setHeight( 12 );
            opacity->setVertAlign( Control::ALIGN_CENTER );
            opacity->addEventHandler( new OpacityHandler(overlay) );// 添加事件处理器
            s_layerBox->setControl( 3, i, opacity );

            // Add a text label:
            LabelControl* edit = new LabelControl( "Edit" );        
            edit->setVertAlign( Control::ALIGN_CENTER );
            edit->addEventHandler(new EditHandler(overlay, &viewer, editor));
            s_layerBox->setControl(4, i, edit );

			// 替换遮盖图和预览图标。LabelControl不支持中文
			LabelControl *change = new LabelControl("changeImage");
			change->setVertAlign(Control::ALIGN_CENTER);
			osg::ref_ptr image2 = osgDB::readRefImageFile("../data/fractal.png");// 替换一张图片
			change->addEventHandler(new ChangeImageHandler(image2.get(), overlay, imageCon));
			s_layerBox->setControl(5, i, change);

			// 拖动图片编辑点,打印输出点的位置信息
			LabelControl *position = new LabelControl("position");// 用于显示坐标信息
			position->setVertAlign(Control::ALIGN_CENTER);
			ImageOverlay::ControlPoint controlPoint(ImageOverlay::ControlPoint::CONTROLPOINT_CENTER);// 获取中心点的坐标
			overlay->addCallback(new UpdateLabelCallback(position, overlay, controlPoint));// 为覆盖图添加回调方法
			s_layerBox->setControl(6, i, position);
        }        
    }

    // add some stock OSG handlers:
    viewer.addEventHandler(new osgViewer::StatsHandler());
    viewer.addEventHandler(new osgViewer::WindowSizeHandler());    
    viewer.addEventHandler(new osgViewer::LODScaleHandler());
    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
    viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
        
    return viewer.run();
}

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