• osgEarth示例分析——osgearth_tracks


    前言

    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 );

    完整代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. #include
    17. #include
    18. using namespace osgEarth;
    19. using namespace osgEarth::Util;
    20. using namespace osgEarth::Util::Controls;
    21. using namespace osgEarth::Annotation;
    22. using namespace osgEarth::Symbology;
    23. #define LC "[osgearth_tracks] "
    24. /**
    25. * Demonstrates use of the TrackNode to display entity track symbols.
    26. */
    27. // field names for the track labelsL
    28. #define FIELD_NAME "name"
    29. #define FIELD_POSITION "position"
    30. #define FIELD_NUMBER "number"
    31. // icon to use, and size in pixels
    32. #define ICON_URL "m2525_air.png"
    33. #define ICON_SIZE 40
    34. // format coordinates as MGRS 坐标系格式MGRS
    35. static MGRSFormatter s_format(MGRSFormatter::PRECISION_10000M);
    36. // globals for this demo
    37. bool g_showCoords = true;
    38. optional<float> g_duration = 60.0;
    39. unsigned g_numTracks = 500;
    40. // 用于控制 清除引擎(图标和其他内容变小消失) 的选项。
    41. ScreenSpaceLayoutOptions g_dcOptions;
    42. /** Prints an error message */
    43. int
    44. usage( const std::string& message )
    45. {
    46. OE_WARN << LC << message << std::endl;
    47. return -1;
    48. }
    49. /** A little track simulator that goes a simple great circle interpolation */
    50. // 一个小小的轨迹模拟器,可以进行简单的大圆插值。
    51. struct TrackSim : public osg::Referenced
    52. {
    53. TrackNode* _track;
    54. GeoPoint _start, _end;
    55. void update( double t )
    56. {
    57. osg::Vec3d pos;
    58. GeoPoint geo = _start.interpolate(_end, t);
    59. geo.alt() = 10000.0; // 高度默认
    60. // update the position label.
    61. _track->setPosition(geo);
    62. if ( g_showCoords )// 此参数通过checkbox控制是否需要显示
    63. {
    64. _track->setFieldValue( FIELD_POSITION, s_format(geo) );// s_format 转化坐标格式
    65. }
    66. else
    67. _track->setFieldValue( FIELD_POSITION, "" );
    68. }
    69. };
    70. typedef std::list< osg::ref_ptr > TrackSims;
    71. /** Update operation that runs the simulators. */
    72. // 运行的模拟器的更新操作
    73. struct TrackSimUpdate : public osg::Operation
    74. {
    75. TrackSimUpdate(TrackSims& sims) : osg::Operation( "tasksim", true ), _sims(sims) { }
    76. void operator()( osg::Object* obj ) {
    77. osg::View* view = dynamic_cast(obj);
    78. double t = fmod(view->getFrameStamp()->getSimulationTime(), (double)g_duration.get()) / (double)g_duration.get();
    79. for( TrackSims::iterator i = _sims.begin(); i != _sims.end(); ++i )
    80. i->get()->update( t );// 更新每一个TrackSim
    81. }
    82. TrackSims& _sims;
    83. };
    84. /**
    85. * Creates a field schema that we'll later use as a labeling template for
    86. * TrackNode instances.
    87. */
    88. // 创建一个字段模式,稍后将用作TrackNode实例的标签模板。
    89. // typedef std::map TrackNodeFieldSchema;
    90. // TrackNodeField:定义与TrackNode关联的标签字段。TrackNode可以有零个或多个“字段”,每个字段都是与节点图标一起呈现的文本标签。
    91. void
    92. createFieldSchema( TrackNodeFieldSchema& schema )
    93. {
    94. const float R = 2.0f;
    95. // 三个字段,分别显示名称、坐标、当前编号,分别位于图标的上、下、左侧。
    96. // 关于位置的设定,->pixelOffset()与->alignment() 的属性设置,需要放在一起看,才能更明白。
    97. // draw the track name above the icon:
    98. TextSymbol* nameSymbol = new TextSymbol();
    99. nameSymbol->pixelOffset()->set( 0, R+ICON_SIZE/2 );// 文本偏移
    100. nameSymbol->alignment() = TextSymbol::ALIGN_CENTER_BOTTOM;// 文本位置
    101. nameSymbol->halo()->color() = Color::Black;
    102. nameSymbol->size() = nameSymbol->size()->eval() + 2.0f;
    103. schema[FIELD_NAME] = TrackNodeField(nameSymbol, false); // false => static label (won't change after set)
    104. // draw the track coordinates below the icon:
    105. TextSymbol* posSymbol = new TextSymbol();
    106. posSymbol->pixelOffset()->set( 0, -R-ICON_SIZE/2 );
    107. posSymbol->alignment() = TextSymbol::ALIGN_CENTER_TOP;
    108. posSymbol->fill()->color() = Color::Yellow;
    109. posSymbol->size() = posSymbol->size()->eval() - 2.0f;
    110. schema[FIELD_POSITION] = TrackNodeField(posSymbol, true); // true => may change at runtime,位置改变
    111. // draw some other field to the left:
    112. TextSymbol* numberSymbol = new TextSymbol();
    113. numberSymbol->pixelOffset()->set( -R-ICON_SIZE/2, 0 );
    114. numberSymbol->alignment() = TextSymbol::ALIGN_RIGHT_CENTER;
    115. schema[FIELD_NUMBER] = TrackNodeField(numberSymbol, false);
    116. }
    117. /** Builds a bunch of tracks. */
    118. // 创建一堆轨道
    119. void
    120. createTrackNodes(const SpatialReference* mapSRS, osg::Group* parent, const TrackNodeFieldSchema& schema, TrackSims& sims )
    121. {
    122. // load an icon to use:
    123. osg::ref_ptr srcImage = osgDB::readRefImageFile( ICON_URL );
    124. osg::ref_ptr image;
    125. // 输入文件,格式化后,变为输出文件image
    126. ImageUtils::resizeImage( srcImage.get(), ICON_SIZE, ICON_SIZE, image );
    127. // make some tracks, choosing a random simulation for each.
    128. Random prng;// 随机数
    129. // 获取地理坐标系
    130. const SpatialReference* geoSRS = mapSRS->getGeographicSRS();
    131. // g_numTracks = 500
    132. for( unsigned i=0; i
    133. {
    134. // prng.next():a double in the range [0..1]
    135. double lon0 = -180.0 + prng.next() * 360.0;
    136. double lat0 = -80.0 + prng.next() * 160.0;
    137. GeoPoint pos(geoSRS, lon0, lat0);
    138. TrackNode* track = new TrackNode(pos, image.get(), schema);
    139. track->setFieldValue( FIELD_NAME, Stringify() << "Track:" << i );
    140. track->setFieldValue( FIELD_POSITION, Stringify() << s_format(pos) );// 转化坐标格式
    141. track->setFieldValue( FIELD_NUMBER, Stringify() << (1 + prng.next(9)) );
    142. // add a priority
    143. track->setPriority( float(i) );
    144. parent->addChild( track );
    145. // add a simulator for this guy
    146. double lon1 = -180.0 + prng.next() * 360.0;
    147. double lat1 = -80.0 + prng.next() * 160.0;
    148. TrackSim* sim = new TrackSim();// 创建轨道模拟器
    149. sim->_track = track;
    150. sim->_start.set(mapSRS, lon0, lat0, 0.0, ALTMODE_ABSOLUTE);
    151. sim->_end.set(mapSRS, lon1, lat1, 0.0, ALTMODE_ABSOLUTE);
    152. sims.push_back( sim );
    153. }
    154. }
    155. /** creates some UI controls for adjusting the decluttering parameters. */
    156. // 创建ui面板
    157. Container*
    158. createControls( osgViewer::View* view )
    159. {
    160. //ControlCanvas* canvas = ControlCanvas::getOrCreate(view);
    161. // title bar 垂直box
    162. VBox* vbox = new VBox(Control::ALIGN_NONE, Control::ALIGN_BOTTOM, 2, 1 );
    163. vbox->setBackColor( Color(Color::Black, 0.5) );
    164. // 添加一个label控件
    165. vbox->addControl( new LabelControl("osgEarth Tracks Demo", Color::Yellow) );
    166. // checkbox that toggles decluttering of tracks
    167. // 通过复选框,切换 是否开启 清理功能(也就是当两个图标移动靠近时,会有一个逐渐变小以至于隐藏,避免图标覆盖遮挡)
    168. struct ToggleDecluttering : public ControlEventHandler {
    169. void onValueChanged( Control* c, bool on ) {
    170. ScreenSpaceLayout::setDeclutteringEnabled( on );
    171. }
    172. };
    173. HBox* dcToggle = vbox->addControl( new HBox() );
    174. dcToggle->addControl( new CheckBoxControl(true, new ToggleDecluttering()) );
    175. dcToggle->addControl( new LabelControl("Declutter") );
    176. // checkbox that toggles the coordinate display
    177. // 切换是否显示图标下方的坐标信息
    178. struct ToggleCoords : public ControlEventHandler {
    179. void onValueChanged( Control* c, bool on ) {
    180. g_showCoords = on;// 是否显示坐标系
    181. }
    182. };
    183. HBox* coordsToggle = vbox->addControl( new HBox() );
    184. coordsToggle->addControl( new CheckBoxControl(true, new ToggleCoords()) );
    185. coordsToggle->addControl( new LabelControl("Show locations") );
    186. // grid for the slider controls so they look nice
    187. // 添加网格,然后在网格中绘制滑块,看起来更美观
    188. Grid* grid = vbox->addControl( new Grid() );
    189. grid->setHorizFill( true );
    190. grid->setChildHorizAlign( Control::ALIGN_LEFT );
    191. grid->setChildSpacing( 6 );// 子控件的间距
    192. unsigned r=0;
    193. // event handler for changing decluttering options
    194. struct ChangeFloatOption : public ControlEventHandler {
    195. optional<float>& _param;
    196. LabelControl* _label;
    197. ChangeFloatOption( optional<float>& param, LabelControl* label ) : _param(param), _label(label) { }
    198. void onValueChanged( Control* c, float value ) {
    199. _param = value;
    200. _label->setText( Stringify() << std::fixed << std::setprecision(1) << value );// 修改滑块值,此值会显示在label上
    201. ScreenSpaceLayout::setOptions( g_dcOptions );// 通过 g_dcOptions 参数设置引擎
    202. }
    203. };
    204. // 设置循环一圈的时间,时间越小,速度越快
    205. grid->setControl( 0, r, new LabelControl("Sim loop duration:") );
    206. LabelControl* speedLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_duration) );
    207. HSliderControl* speedSlider = grid->setControl( 1, r, new HSliderControl(
    208. 600.0, 30.0, *g_duration, new ChangeFloatOption(g_duration, speedLabel) ) );// 控制 g_duration
    209. speedSlider->setHorizFill( true, 200 );
    210. // 控制最小值,即两个标签靠近时,有一个标签逐渐变小,以至于变到最小的值
    211. grid->setControl( 0, ++r, new LabelControl("Min scale:") );
    212. LabelControl* minAnimationScaleLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.minAnimationScale()) );
    213. grid->setControl( 1, r, new HSliderControl(
    214. 0.0, 1.0, *g_dcOptions.minAnimationScale(), new ChangeFloatOption(g_dcOptions.minAnimationScale(), minAnimationScaleLabel) ) );
    215. // 更改透明度
    216. grid->setControl( 0, ++r, new LabelControl("Min alpha:") );
    217. LabelControl* alphaLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.minAnimationAlpha()) );
    218. grid->setControl( 1, r, new HSliderControl(
    219. 0.0, 1.0, *g_dcOptions.minAnimationAlpha(), new ChangeFloatOption(g_dcOptions.minAnimationAlpha(), alphaLabel) ) );
    220. // 激活时间
    221. grid->setControl( 0, ++r, new LabelControl("Activate time (s):") );
    222. LabelControl* actLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.inAnimationTime()) );
    223. grid->setControl( 1, r, new HSliderControl(
    224. 0.0, 2.0, *g_dcOptions.inAnimationTime(), new ChangeFloatOption(g_dcOptions.inAnimationTime(), actLabel) ) );
    225. // 停止时间
    226. grid->setControl( 0, ++r, new LabelControl("Deactivate time (s):") );
    227. LabelControl* deactLabel = grid->setControl( 2, r, new LabelControl(Stringify() << std::fixed << std::setprecision(1) << *g_dcOptions.outAnimationTime()) );
    228. grid->setControl( 1, r, new HSliderControl(
    229. 0.0, 2.0, *g_dcOptions.outAnimationTime(), new ChangeFloatOption(g_dcOptions.outAnimationTime(), deactLabel) ) );
    230. return vbox;
    231. }
    232. /**
    233. * Main application.
    234. * Creates some simulated track data and runs the simulation.
    235. */
    236. int
    237. main(int argc, char** argv)
    238. {
    239. osg::ArgumentParser arguments(&argc,argv);
    240. // initialize a viewer.
    241. osgViewer::Viewer viewer( arguments );
    242. viewer.setCameraManipulator( new EarthManipulator );
    243. // load a map from an earth file.读取earth文件,并且创建界面控制面板
    244. osg::Node* earth = MapNodeHelper().load(arguments, &viewer, createControls(&viewer));
    245. MapNode* mapNode = MapNode::findMapNode(earth);
    246. if ( !mapNode )
    247. return usage("Missing required .earth file" );
    248. // count on the cmd line? 从控制台输入个数,默认500个
    249. arguments.read("--count", g_numTracks);
    250. viewer.setSceneData( earth );
    251. // build a track field schema.
    252. // 创建一个map列表 ,typedef std::map TrackNodeFieldSchema;
    253. TrackNodeFieldSchema schema;
    254. // 初始化 schema 对象
    255. createFieldSchema( schema );
    256. // create some track nodes.创建一些跟踪节点
    257. TrackSims trackSims;
    258. osg::Group* tracks = new osg::Group();
    259. createTrackNodes( mapNode->getMapSRS(), tracks, schema, trackSims );
    260. mapNode->addChild( tracks );
    261. // Set up the automatic decluttering. setEnabled() activates decluttering for
    262. // all drawables under that state set. We are also activating priority-based
    263. // sorting, which looks at the AnnotationData::priority field for each drawable.
    264. // (By default, objects are sorted by disatnce-to-camera.) Finally, we customize
    265. // a couple of the decluttering options to get the animation effects we want.
    266. g_dcOptions = ScreenSpaceLayout::getOptions();
    267. g_dcOptions.inAnimationTime() = 1.0f;
    268. g_dcOptions.outAnimationTime() = 1.0f;
    269. g_dcOptions.sortByPriority() = true;
    270. ScreenSpaceLayout::setOptions( g_dcOptions );
    271. // attach the simulator to the viewer. 将仿真器和视景器关联起来
    272. viewer.addUpdateOperation( new TrackSimUpdate(trackSims) );
    273. viewer.setRunFrameScheme( viewer.CONTINUOUS );
    274. viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
    275. viewer.run();
    276. }

  • 相关阅读:
    代码解析 最短路径 排序
    英语小作文写作模板及步骤(1)
    关于虚拟货币内容发布规则的调整通知
    Camera | 5.Linux v4l2架构(基于rk3568)
    springboot+vue基于Spark的共享单车数据存储系统的设计与实现【内含源码+文档+部署教程】
    【Linux】CentOS-6.8超详细安装教程
    ruoyi-nbcio-plus基于vue3的多租户机制
    神经网络模型的参数量和计算量
    作为运维你还在想要不要学Python?听听运维老司机怎么说
    在线ios免签是干什么的?
  • 原文地址:https://blog.csdn.net/qq_34732729/article/details/128187900