前言
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();
}