osgEarth示例分析——osgearth_tracks
创始人
2024-03-19 22:33:26
0

前言

osgearth_tracks示例,演示了所有图标沿着路径进行移动(路径是不可见的)。

执行效果

执行命令:osgearth_tracksd.exe earth_image\world.earth

右下角的控制面板功能:

Declutter

是否开启 【清理器】 功能。

即当两个图标靠近时,其中一个会逐渐变小并消失;

当两个图标远离时,那个变小的图标会逐渐变大并出现。

Show locations是否显示坐标信息,即图标下方黄色文本。
Sim loop duration

设置图标云顶一个周期的时间。

由于距离是一定的,周期越大,则运行速度越慢。

Min scale

图标变小时,最小的缩放值。

此值设置越小,图标变小的终极状态也会越小。

Min alpha图标变小时,透明度的变化。
Activate time(s)

图标从最小状态,变化到最大状态的时间。

此值设置太小,则图标会一下子变大。

Deactivate time(s)

图标从正常变小,到终极最小状态的时间。

此值设置太小,则图标会一下子变小。

【注】最后两个值,有时候观察也不是太明显。

代码分析

此示例中,涉及到一些新的类和方法。下面简单进行分析。

1、控制面板功能的重要类

osgEarth::ScreenSpaceLayoutOptions 通过选项控制annotation清除的引擎类。比如上面表格中说的:scale、alpha、activate、deactivate等内容的控制。

osgEarth::ScreenSpaceLayout::setOptions ( ScreenSpaceLayout::getOptions() ) 控制activate、 deactivate、 enable(是否开启)等内容。

以上两个类是同时使用的。

2、坐标系

在此显示状态时,坐标系并非是我们熟知的经纬度,而是 osgEarth::Util::s_format(MGRSFormatter::PRECISION_10000M)

3、轨迹模拟器

通过osg的方式,实现的。struct TrackSim : public osg::Referenced,重写 update() 方法。struct TrackSimUpdate : public osg::Operation,重写 operator() 方法。

4、绘制标签和图标的方式

typedef std::map TrackNodeFieldSchema schema;

schema[FIELD_NAME] = TrackNodeField(TextSymbol* nameSymbol, false);// 通过键值对构造

osgEarth::Annotation::TrackNode * track = new TrackNode(pos, image.get(), schema);

osgEarth::Annotation::TrackNodeField 

5、控制面板的ui界面,本节仅有的新内容,是通过仅设置一个方法,就能为多个滑块添加事件。

6、

    // attach the simulator to the viewer. 将仿真器和视景器关联起来
    viewer.addUpdateOperation( new TrackSimUpdate(trackSims) );
    viewer.setRunFrameScheme( viewer.CONTINUOUS );

完整代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include #include 
#include 
#include using namespace osgEarth;
using namespace osgEarth::Util;
using namespace osgEarth::Util::Controls;
using namespace osgEarth::Annotation;
using namespace osgEarth::Symbology;#define LC "[osgearth_tracks] "/*** Demonstrates use of the TrackNode to display entity track symbols.*/// field names for the track labelsL
#define FIELD_NAME     "name"
#define FIELD_POSITION "position"
#define FIELD_NUMBER   "number"// icon to use, and size in pixels
#define ICON_URL       "m2525_air.png"
#define ICON_SIZE      40// format coordinates as MGRS 坐标系格式MGRS
static MGRSFormatter s_format(MGRSFormatter::PRECISION_10000M);// globals for this demo
bool                g_showCoords        = true;
optional     g_duration          = 60.0;
unsigned            g_numTracks         = 500;
// 用于控制 清除引擎(图标和其他内容变小消失) 的选项。
ScreenSpaceLayoutOptions g_dcOptions;/** Prints an error message */
int
usage( const std::string& message )
{OE_WARN << LC << message << std::endl;return -1;
}/** A little track simulator that goes a simple great circle interpolation */
// 一个小小的轨迹模拟器,可以进行简单的大圆插值。
struct TrackSim : public osg::Referenced
{TrackNode* _track;GeoPoint _start, _end;void update( double t ){osg::Vec3d pos;GeoPoint geo = _start.interpolate(_end, t);geo.alt() = 10000.0; // 高度默认// update the position label._track->setPosition(geo);if ( g_showCoords )// 此参数通过checkbox控制是否需要显示{_track->setFieldValue( FIELD_POSITION, s_format(geo) );// s_format 转化坐标格式}else_track->setFieldValue( FIELD_POSITION, "" );}
};
typedef std::list< osg::ref_ptr > TrackSims;/** Update operation that runs the simulators. */
// 运行的模拟器的更新操作
struct TrackSimUpdate : public osg::Operation
{TrackSimUpdate(TrackSims& sims) : osg::Operation( "tasksim", true ), _sims(sims) { }void operator()( osg::Object* obj ) {osg::View* view = dynamic_cast(obj);double t = fmod(view->getFrameStamp()->getSimulationTime(), (double)g_duration.get()) / (double)g_duration.get();for( TrackSims::iterator i = _sims.begin(); i != _sims.end(); ++i )i->get()->update( t );// 更新每一个TrackSim}TrackSims& _sims;
};/*** Creates a field schema that we'll later use as a labeling template for* TrackNode instances.*/
// 创建一个字段模式,稍后将用作TrackNode实例的标签模板。
// typedef std::map TrackNodeFieldSchema;
// TrackNodeField:定义与TrackNode关联的标签字段。TrackNode可以有零个或多个“字段”,每个字段都是与节点图标一起呈现的文本标签。
void
createFieldSchema( TrackNodeFieldSchema& schema )
{const float R = 2.0f;// 三个字段,分别显示名称、坐标、当前编号,分别位于图标的上、下、左侧。// 关于位置的设定,->pixelOffset()与->alignment() 的属性设置,需要放在一起看,才能更明白。// draw the track name above the icon:TextSymbol* nameSymbol = new TextSymbol();nameSymbol->pixelOffset()->set( 0, R+ICON_SIZE/2 );// 文本偏移nameSymbol->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM;// 文本位置nameSymbol->halo()->color() = Color::Black;nameSymbol->size() = nameSymbol->size()->eval() + 2.0f;schema[FIELD_NAME] = TrackNodeField(nameSymbol, false); // false => static label (won't change after set)// draw the track coordinates below the icon:TextSymbol* posSymbol = new TextSymbol();posSymbol->pixelOffset()->set( 0, -R-ICON_SIZE/2 );posSymbol->alignment() = TextSymbol::ALIGN_CENTER_TOP;posSymbol->fill()->color() = Color::Yellow;posSymbol->size() = posSymbol->size()->eval() - 2.0f;schema[FIELD_POSITION] = TrackNodeField(posSymbol, true); // true => may change at runtime,位置改变// draw some other field to the left:TextSymbol* numberSymbol = new TextSymbol();numberSymbol->pixelOffset()->set( -R-ICON_SIZE/2, 0 );numberSymbol->alignment() = TextSymbol::ALIGN_RIGHT_CENTER;schema[FIELD_NUMBER] = TrackNodeField(numberSymbol, false);
}/** Builds a bunch of tracks. */
// 创建一堆轨道
void
createTrackNodes(const SpatialReference* mapSRS, osg::Group* parent, const TrackNodeFieldSchema& schema, TrackSims& sims )
{// load an icon to use:osg::ref_ptr srcImage = osgDB::readRefImageFile( ICON_URL );osg::ref_ptr image;// 输入文件,格式化后,变为输出文件imageImageUtils::resizeImage( srcImage.get(), ICON_SIZE, ICON_SIZE, image );// make some tracks, choosing a random simulation for each.Random prng;// 随机数// 获取地理坐标系const SpatialReference* geoSRS = mapSRS->getGeographicSRS();// g_numTracks = 500for( unsigned i=0; isetFieldValue( FIELD_NAME,     Stringify() << "Track:" << i );track->setFieldValue( FIELD_POSITION, Stringify() << s_format(pos) );// 转化坐标格式track->setFieldValue( FIELD_NUMBER,   Stringify() << (1 + prng.next(9)) );// add a prioritytrack->setPriority( float(i) );parent->addChild( track );// add a simulator for this guydouble lon1 = -180.0 + prng.next() * 360.0;double lat1 = -80.0 + prng.next() * 160.0;TrackSim* sim = new TrackSim();// 创建轨道模拟器sim->_track = track;  sim->_start.set(mapSRS, lon0, lat0, 0.0, ALTMODE_ABSOLUTE);sim->_end.set(mapSRS, lon1, lat1, 0.0, ALTMODE_ABSOLUTE);sims.push_back( sim );}
}/** creates some UI controls for adjusting the decluttering parameters. */
// 创建ui面板
Container*
createControls( osgViewer::View* view )
{//ControlCanvas* canvas = ControlCanvas::getOrCreate(view);// title bar 垂直boxVBox* vbox = new VBox(Control::ALIGN_NONE, Control::ALIGN_BOTTOM, 2, 1 );vbox->setBackColor( Color(Color::Black, 0.5) );// 添加一个label控件vbox->addControl( new LabelControl("osgEarth Tracks Demo", Color::Yellow) );// checkbox that toggles decluttering of tracks// 通过复选框,切换 是否开启 清理功能(也就是当两个图标移动靠近时,会有一个逐渐变小以至于隐藏,避免图标覆盖遮挡)struct ToggleDecluttering : public ControlEventHandler {void onValueChanged( Control* c, bool on ) {ScreenSpaceLayout::setDeclutteringEnabled( on );}};HBox* dcToggle = vbox->addControl( new HBox() );dcToggle->addControl( new CheckBoxControl(true, new ToggleDecluttering()) );dcToggle->addControl( new LabelControl("Declutter") );// checkbox that toggles the coordinate display// 切换是否显示图标下方的坐标信息struct ToggleCoords : public ControlEventHandler {void onValueChanged( Control* c, bool on ) {g_showCoords = on;// 是否显示坐标系}};HBox* coordsToggle = vbox->addControl( new HBox() );coordsToggle->addControl( new CheckBoxControl(true, new ToggleCoords()) );coordsToggle->addControl( new LabelControl("Show locations") );// grid for the slider controls so they look nice// 添加网格,然后在网格中绘制滑块,看起来更美观Grid* grid = vbox->addControl( new Grid() );grid->setHorizFill( true );grid->setChildHorizAlign( Control::ALIGN_LEFT );grid->setChildSpacing( 6 );// 子控件的间距unsigned r=0;// event handler for changing decluttering optionsstruct ChangeFloatOption : public ControlEventHandler {optional& _param;LabelControl* _label;ChangeFloatOption( optional& param, LabelControl* label ) : _param(param), _label(label) { }void onValueChanged( Control* c, float value ) {_param = value;_label->setText( Stringify() << std::fixed << std::setprecision(1) << value );// 修改滑块值,此值会显示在label上ScreenSpaceLayout::setOptions( g_dcOptions );// 通过 g_dcOptions 参数设置引擎}};// 设置循环一圈的时间,时间越小,速度越快grid->setControl( 0, r, new LabelControl("Sim loop duration:") );LabelControl* speedLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_duration) );HSliderControl* speedSlider = grid->setControl( 1, r, new HSliderControl( 600.0, 30.0, *g_duration, new ChangeFloatOption(g_duration, speedLabel) ) );// 控制 g_durationspeedSlider->setHorizFill( true, 200 );// 控制最小值,即两个标签靠近时,有一个标签逐渐变小,以至于变到最小的值grid->setControl( 0, ++r, new LabelControl("Min scale:") );LabelControl* minAnimationScaleLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.minAnimationScale()) );grid->setControl( 1, r, new HSliderControl( 0.0, 1.0, *g_dcOptions.minAnimationScale(), new ChangeFloatOption(g_dcOptions.minAnimationScale(), minAnimationScaleLabel) ) );// 更改透明度grid->setControl( 0, ++r, new LabelControl("Min alpha:") );LabelControl* alphaLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.minAnimationAlpha()) );grid->setControl( 1, r, new HSliderControl( 0.0, 1.0, *g_dcOptions.minAnimationAlpha(), new ChangeFloatOption(g_dcOptions.minAnimationAlpha(), alphaLabel) ) );// 激活时间grid->setControl( 0, ++r, new LabelControl("Activate time (s):") );LabelControl* actLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.inAnimationTime()) );grid->setControl( 1, r, new HSliderControl( 0.0, 2.0, *g_dcOptions.inAnimationTime(), new ChangeFloatOption(g_dcOptions.inAnimationTime(), actLabel) ) );// 停止时间grid->setControl( 0, ++r, new LabelControl("Deactivate time (s):") );LabelControl* deactLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.outAnimationTime()) );grid->setControl( 1, r, new HSliderControl( 0.0, 2.0, *g_dcOptions.outAnimationTime(), new ChangeFloatOption(g_dcOptions.outAnimationTime(), deactLabel) ) );return vbox;
}/*** Main application.* Creates some simulated track data and runs the simulation.*/
int
main(int argc, char** argv)
{osg::ArgumentParser arguments(&argc,argv);// initialize a viewer.osgViewer::Viewer viewer( arguments );viewer.setCameraManipulator( new EarthManipulator );// load a map from an earth file.读取earth文件,并且创建界面控制面板osg::Node* earth = MapNodeHelper().load(arguments, &viewer, createControls(&viewer));MapNode* mapNode = MapNode::findMapNode(earth);if ( !mapNode )return usage("Missing required .earth file" );// count on the cmd line? 从控制台输入个数,默认500个arguments.read("--count", g_numTracks);viewer.setSceneData( earth );// build a track field schema.// 创建一个map列表 ,typedef std::map TrackNodeFieldSchema;TrackNodeFieldSchema schema;// 初始化 schema 对象createFieldSchema( schema );// create some track nodes.创建一些跟踪节点TrackSims trackSims;osg::Group* tracks = new osg::Group();createTrackNodes( mapNode->getMapSRS(), tracks, schema, trackSims );mapNode->addChild( tracks );// Set up the automatic decluttering. setEnabled() activates decluttering for// all drawables under that state set. We are also activating priority-based// sorting, which looks at the AnnotationData::priority field for each drawable.// (By default, objects are sorted by disatnce-to-camera.) Finally, we customize // a couple of the decluttering options to get the animation effects we want.g_dcOptions = ScreenSpaceLayout::getOptions();g_dcOptions.inAnimationTime()  = 1.0f;g_dcOptions.outAnimationTime() = 1.0f;g_dcOptions.sortByPriority()   = true;ScreenSpaceLayout::setOptions( g_dcOptions );// attach the simulator to the viewer. 将仿真器和视景器关联起来viewer.addUpdateOperation( new TrackSimUpdate(trackSims) );viewer.setRunFrameScheme( viewer.CONTINUOUS );viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);viewer.run();
}

相关内容

热门资讯

文投控股:因与索宝公司合同纠纷... 观点网讯:12月25日,文投控股公告披露,公司因与索宝(北京)国际影业投资有限公司的合同纠纷被诉,涉...
江西上高县泗溪镇创新推进基层政... 近日,在江西省宜春市上高县泗溪镇便农贸市场,一场特殊的宣讲活动正在热闹进行。“泗溪乡音宣讲队”的成员...
欣旺达子公司面临23.14亿元... 12月26日,欣旺达(300207)发布公告,公司的子公司欣旺达动力科技股份有限公司因买卖合同纠纷被...
央行报告:金融系统将实施更加积... 中国人民银行12月26日消息,近日中国人民银行发布的《中国金融稳定报告(2025)》提出,展望未来,...
亿晶光电(600537)披露累... 截至2025年12月26日收盘,亿晶光电(600537)报收于4.33元,较前一交易日上涨9.9%,...
ST德豪:董事会成员构成符合法... 证券之星消息,ST德豪(002005)12月25日在投资者关系平台上答复投资者关心的问题。 投资者提...
交付的电芯存在严重质量问题?欣... 截至目前,国内罕有因交付电芯出现质量问题而和客户对簿公堂的动力电池制造商。老牌锂电企业欣旺达电子股份...
警惕“上门防水补漏”陷阱!广州... 南都讯 记者赵青 通讯员唐明伯 近日,广州法院审结一起以“上门防水补漏”为幌子的恶势力组织犯罪案件。...
天风证券融券余额599.37万... 雷达财经雷助吧出品 文|肖文竹 编|深海 东财Choice数据显示,2025年12月25日,天风证券...
突发涨停!氧化铝的“政策牛”能... 界面新闻记者 | 田鹤琪 在 “跌跌不休” 的持续低迷后,国内氧化铝期货突发涨停。 12月26日,...