Bootstrap

osgEarth示例分析——osgearth_measure

前言

osgearth_measure测量示例,展示了如何测量两点间距离。当点击第一个点后,随着鼠标移动,红线跟着移动,直到点下第二个点。

执行命令:osgearth_measured.exe earth_image\china-simple.earth

效果

  • Distance,实时变化。
  • Path 勾选后,则绘制连续测量直线。
  • Greate Circle 勾选后,绘制大圆弧线,否则绘制两点直线。
  • Mouse,实时更新鼠标坐标。

代码分析

MouseCoordsTool类、 MouseCoordsLabelCallback类,在 osgearth_graticule 示例中,也有用到。当前示例仅获取一种格式的坐标信息。osgearth_graticule示例中,允许设置多种坐标格式。

#include <osg/Notify>
#include <osgGA/StateSetManipulator>
#include <osgGA/GUIEventHandler>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgEarth/MapNode>
#include <osgEarth/XmlUtils>
#include <osgEarth/Registry>
#include <osgEarth/Viewpoint>
#include <osgEarth/CullingUtils>
#include <osgEarth/GLUtils>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/AutoClipPlaneHandler>
#include <osgEarthUtil/Controls>
#include <osgEarthUtil/MouseCoordsTool>
#include <osgEarthUtil/ExampleResources>
#include <osgEarthSymbology/Color>

#include <osgEarthUtil/MeasureTool>

using namespace osgEarth::Util;
using namespace osgEarth::Util::Controls;
using namespace osgEarth::Symbology;

// 自定义测量工具回调类
class MyMeasureToolCallback : public MeasureToolHandler::MeasureToolEventHandler
{
public:
    MyMeasureToolCallback(LabelControl* label):
      _label(label)
    {
    }

	// 在标签上显示距离
    virtual void onDistanceChanged(MeasureToolHandler* sender, double distance)
    {
        std::stringstream ss;
        ss << "Distance = " << std::setprecision(10) << distance << "m" << std::endl; 
        std::string str;
        str = ss.str();
        _label->setText( str );
    }
    LabelControl* _label;
};

// 切换路径测量还是点对点测量
struct TogglePathHandler : public ControlEventHandler
{
    TogglePathHandler( MeasureToolHandler* tool) :
    _tool( tool )
    { }

    virtual void onValueChanged(Control* control, bool value) {
        _tool->setIsPath( value );// 是否路径测量
    }

    osg::ref_ptr<MeasureToolHandler> _tool;
};

// 切换大圆弧测量还是直线测量
struct ToggleModeHandler : public ControlEventHandler
{
    ToggleModeHandler( MeasureToolHandler* tool) :
    _tool( tool )
    { }

    virtual void onValueChanged(Control* control, bool value)
    {
        if (_tool->getGeoInterpolation() == GEOINTERP_GREAT_CIRCLE)
        {
            _tool->setGeoInterpolation( GEOINTERP_RHUMB_LINE);
        }
        else
        {
            _tool->setGeoInterpolation( GEOINTERP_GREAT_CIRCLE);
        }        
    }

    osg::ref_ptr<MeasureToolHandler> _tool;
};



int
main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);
    osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 );

    osgViewer::Viewer viewer(arguments);

    // load the .earth file from the command line.加载earth文件
    osg::Node* earthNode = MapNodeHelper().load( arguments, &viewer );
    if (!earthNode)
    {
        OE_NOTICE << "Unable to load earth model." << std::endl;
        return 1;
    }

    MapNode* mapNode = MapNode::findMapNode( earthNode );
    if ( !mapNode )
    {
        OE_NOTICE << "Input file was not a .earth file" << std::endl;
        return 1;
    }

    earthNode->setNodeMask( 0x1 );// 地图可见
    
    osgEarth::Util::EarthManipulator* earthManip = new EarthManipulator();
    viewer.setCameraManipulator( earthManip );// 添加操作器

    osg::Group* root = new osg::Group();
    root->addChild( earthNode );
    
    //Create the MeasureToolHandler 创建测量工具处理器
    MeasureToolHandler* measureTool = new MeasureToolHandler(mapNode);
    measureTool->setIntersectionMask( 0x1 );
    viewer.addEventHandler( measureTool );

    //Create some controls to interact with the measuretool
	// 创建一些控件以与测量工具交互。
    ControlCanvas* canvas = new ControlCanvas();
    root->addChild( canvas );
    canvas->setNodeMask( 0x1 << 1 );

	// 网格布局
    Grid* grid = new Grid();
    grid->setBackColor(0,0,0,0.5);
    grid->setMargin( 10 );
    grid->setPadding( 10 );
    grid->setChildSpacing( 10 );
    grid->setChildVertAlign( Control::ALIGN_CENTER );
    grid->setAbsorbEvents( true );
    grid->setVertAlign( Control::ALIGN_TOP );   

    canvas->addControl( grid );

    //Add a label to display the distance
    // Add a text label:
    grid->setControl( 0, 0, new LabelControl("Distance:") );// 静态标签
    LabelControl* label = new LabelControl();// 动态显示距离值的标签
    label->setFont( osgEarth::Registry::instance()->getDefaultFont() );
    label->setFontSize( 24.0f );
    label->setHorizAlign( Control::ALIGN_LEFT ); // 水平居左   
    label->setText("click to measure");
    grid->setControl( 1, 0, label );

    //Add a callback to update the label when the distance changes
    measureTool->addEventHandler( new MyMeasureToolCallback(label) );
    
	// 设置线风格
    Style style = measureTool->getLineStyle();
    style.getOrCreate<LineSymbol>()->stroke()->color() = Color::Red;
    style.getOrCreate<LineSymbol>()->stroke()->width() = 4.0f;
    measureTool->setLineStyle(style);

    //Add a checkbox to control if we are doing path based measurement or just point to point
	// 添加一个复选框,以控制我们是进行基于路径的测量还是仅进行点对点的测量。
    grid->setControl( 0, 1, new LabelControl("Path"));
    CheckBoxControl* checkBox = new CheckBoxControl(false);
    checkBox->setHorizAlign(Control::ALIGN_LEFT);
    checkBox->addEventHandler( new TogglePathHandler(measureTool));
    grid->setControl( 1, 1, checkBox);

    //Add a toggle to set the mode of the measuring tool
	// 切换大圆弧测量还是直线测量
    grid->setControl( 0, 2, new LabelControl("Great Circle"));
    CheckBoxControl* mode = new CheckBoxControl(true);
    mode->setHorizAlign(Control::ALIGN_LEFT);
    mode->addEventHandler( new ToggleModeHandler(measureTool));
    grid->setControl( 1, 2, mode);

    //Add a mouse coords readout: 输出鼠标坐标信息
    LabelControl* mouseLabel = new LabelControl();
    grid->setControl( 0, 3, new LabelControl("Mouse:"));
    grid->setControl( 1, 3, mouseLabel );
    viewer.addEventHandler(new MouseCoordsTool(mapNode, mouseLabel) );

    viewer.setSceneData( root );

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

    return viewer.run();
}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;