• osgEarth示例分析——osgearth_infinitescroll


    前言

    osgearth_infinitescroll示例,是一个可以将二维地图无限拖动的示例。在示例中,可以控制黄色的线一直显示,两张覆盖图默认显示,但拖动地图的时候,有时候显示有时候不显示。

    之前一直没有找到如何通过earth文件的方式加载二维地图,真是众里寻他千百度,那earth文件竟在此处呀。

     earth文件如下:两个地方重点,一个是 map 的 type,一个是options标签。之前一直加不上,是因为没有设置 options标签。其他的annotations图元,就可以照葫芦画瓢的添加了。

    1. <map name="Globe" type="projected" version = "2">
    2. <options>
    3. <profile>plate-carreprofile>
    4. options>
    5. <image name="GlobeImage" driver="gdal">
    6. <url>./globe/globel.tifurl>
    7. image>
    8. <annotations>
    9. <feature name="Flight Path">
    10. <srs>wgs84srs>
    11. <geometry>
    12. LINESTRING(140.385 35.765 0, 141.1 35.4917 3944.77, 142.163 35.1617 9645.92, 142.665 35.38 12496.8, 143.872 35.8933 12496.8, 145.667 37.1967 12496.8, 149.825 39.1533 12496.8, 155.668 42.9817 12496.8, 162.31 46.415 13716, 168.783 48.675 13716, 180 50 13716, 190 50 13716, 200 49 13716, 210 48 13716, 220 46 13716, 233 40.625 14935.2, 236.725 39.0533 14935.2, 238.828 37.8333 14935.2, 240.842 36.0417 14935.2, 240.98 35.9133 13819.4, 241.125 35.5133 11087.5, 241.245 35.1833 8832.26, 241.298 35.0317 7798.3, 241.423 34.6833 5419.12, 241.532 34.4967 4063.71, 241.583 34.41 3430.97, 241.73 34.1567 1591.04, 241.59 33.9433 0)
    13. geometry>
    14. <style type="text/css">
    15. stroke: #ffff00;
    16. stroke-width: 3;
    17. render-lighting: false;
    18. style>
    19. feature>
    20. <imageoverlay>
    21. <url>../fractal.pngurl>
    22. <geometry>POLYGON((170 26, 190 26, 190 56, 170 56))geometry>
    23. imageoverlay>
    24. <imageoverlay>
    25. <url>../fractal.pngurl>
    26. <geometry>POLYGON((-81 26, -40.5 45, -40.5 75.5, -81 60))geometry>
    27. imageoverlay>
    28. annotations>
    29. map>

    执行命令: osgearth_infinitescrolld.exe earth_image\world_projected.earth

    效果

    左移和右移的打印输入部分内容:

    1. 测试移动:direction:-1, offset: -4.0075e+07
    2. 测试移动:direction:-1, offset: -4.0075e+07
    3. 测试移动:direction:1, offset: 4.0075e+07
    4. 测试移动:direction:1, offset: 4.0075e+07
    5. 测试移动:direction:1, offset: 4.0075e+07

     代码分析

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #define LC "[viewer] "
    10. using namespace osgEarth;
    11. using namespace osgEarth::Util;
    12. int
    13. usage(const char* name)
    14. {
    15. OE_NOTICE
    16. << "\nUsage: " << name << " file.earth" << std::endl
    17. << MapNodeHelper().usage() << std::endl;
    18. return 0;
    19. }
    20. int
    21. main(int argc, char** argv)
    22. {
    23. osg::ArgumentParser arguments(&argc,argv);
    24. // help?
    25. if ( arguments.read("--help") )
    26. return usage(argv[0]);
    27. // 通过vfov,设置视角大小。
    28. // 增大fov值以提供更沉浸的体验。vfov:视野(Field of View),通常设置45度
    29. float vfov = -1.0f;
    30. arguments.read("--vfov", vfov);
    31. // create a viewer:
    32. osgViewer::Viewer viewer(arguments);
    33. // Tell the database pager to not modify the unref settings
    34. // 保持 database pager 默认设置
    35. viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( true, false );
    36. // thread-safe initialization of the OSG wrapper manager. Calling this here
    37. // prevents the "unsupported wrapper" messages from OSG
    38. // OSG包装器管理器的线程安全初始化。
    39. // 在这里调用它可以防止来自OSG的“不支持的包装器”消息
    40. osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
    41. // install our default manipulator (do this before calling load)
    42. // 安装默认操作器
    43. osg::ref_ptr< EarthManipulator > manipulator = new EarthManipulator(arguments);
    44. viewer.setCameraManipulator( manipulator );
    45. // disable the small-feature culling
    46. viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
    47. // set a near/far ratio that is smaller than the default. This allows us to get
    48. // closer to the ground without near clipping. If you need more, use --logdepth
    49. // 设置 近远率
    50. viewer.getCamera()->setNearFarRatio(0.0001);
    51. if ( vfov > 0.0 )
    52. {
    53. // 设置 透视投影矩阵
    54. double fov, ar, n, f;
    55. viewer.getCamera()->getProjectionMatrixAsPerspective(fov, ar, n, f);
    56. viewer.getCamera()->setProjectionMatrixAsPerspective(vfov, ar, n, f);
    57. }
    58. // load an earth file, and support all or our example command-line options
    59. // and earth file tags
    60. osg::ref_ptr< osg::Node > node = MapNodeHelper().load(arguments, &viewer);
    61. osg::ref_ptr< MapNode > mapNode = MapNode::findMapNode(node.get());
    62. if ( mapNode.valid() )
    63. {
    64. // 如果是地球类型,则报错退出
    65. if (mapNode->isGeocentric())
    66. {
    67. OE_NOTICE << "Please run this example with a projected earth file" << std::endl;
    68. return 1;
    69. }
    70. // GeoExtent 轴对齐的地理空间范围。与空间参照的坐标系对齐的边界框。
    71. // 不是特清楚 GeoExtent 类具体的意义。在这里先假设 mapExtene是二维坐标空间。
    72. GeoExtent mapExtent = mapNode->getMap()->getProfile()->getExtent();
    73. //Disable the middle mouse by default, which is rotate. This will keep us in 2D mode.
    74. // 禁止中轮的旋转操作
    75. manipulator->getSettings()->bindMouse(osgEarth::Util::EarthManipulator::ACTION_NULL, osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON, 0);
    76. // Compute a sensible max range so that the user can't zoom out too far to where we need more than 3 transforms.
    77. // 计算一个合理的最大范围,这样用户就不会缩缩放太远以至于需要3次以上变换才能回到合适位置。
    78. // width():东西跨度。 height():南北跨度
    79. double maxDim = osg::maximum(mapExtent.width(), mapExtent.height());// 返回二者中较大的
    80. double range = ((0.5 * maxDim) / 0.267949849);// 暂时不理解这个计算,总之 range > maxDim
    81. manipulator->getSettings()->setMinMaxDistance(0.0, range);
    82. osg::Group* root = new osg::Group;
    83. // We're going to draw the map three times so that we can provide an infinite view scrolling left to right.
    84. // 我们将绘制三份地图,以便提供从左向右滚动的无限视图。
    85. // The centerMatrix is centered around the eye point.
    86. // 以视点为中心的矩阵
    87. osg::MatrixTransform* centerMatrix = new osg::MatrixTransform;
    88. centerMatrix->addChild( mapNode );
    89. root->addChild( centerMatrix );
    90. // The left matrix is to the left of the center matrix
    91. // 中心左侧的矩阵
    92. osg::MatrixTransform* leftMatrix = new osg::MatrixTransform;
    93. leftMatrix->addChild( mapNode );
    94. root->addChild( leftMatrix );
    95. // The right matrix is to the right of the center matrix
    96. // 中心右侧矩阵
    97. osg::MatrixTransform* rightMatrix = new osg::MatrixTransform;
    98. rightMatrix->addChild( mapNode );
    99. root->addChild( rightMatrix );
    100. viewer.setSceneData( root );
    101. while (!viewer.done())
    102. {
    103. // Get the current viewpoint from the EarthManipulator
    104. // 获取操作器的视点信息
    105. Viewpoint vp = manipulator->getViewpoint();
    106. double eyeX = vp.focalPoint()->x();
    107. // focalPoint() 相机所指向的地理空间位置。
    108. GeoPoint focalPoint = *vp.focalPoint();
    109. // Adjust the focal point if the user is trying to too far north or south.
    110. // 如果用户拖动地图太北或者太南,则调整焦点
    111. if (focalPoint.y() > mapExtent.yMax())
    112. {
    113. focalPoint.y() = mapExtent.yMax();
    114. vp.focalPoint() = focalPoint;
    115. manipulator->setViewpoint( vp );
    116. }
    117. else if (focalPoint.y() < mapExtent.yMin())
    118. {
    119. focalPoint.y() = mapExtent.yMin();
    120. vp.focalPoint() = focalPoint;
    121. manipulator->setViewpoint( vp );
    122. }
    123. // 这是为中心图的坐标空间??
    124. GeoExtent centerExtent = mapExtent;
    125. // Figure out which direction we need to shift the map extent
    126. // 找出我们需要改变地图范围的方向
    127. float direction = 0.0;
    128. if (eyeX < mapExtent.xMin())// 视点在坐标范围的左侧,则图左移。
    129. {
    130. // Move to the left
    131. direction = -1.0;
    132. }
    133. else if (eyeX > mapExtent.xMax())
    134. {
    135. // Move to the right
    136. direction = 1.0;
    137. }
    138. // Shift the center extent so that it's centered around the eye point.
    139. // 转换中心坐标,以至于总能 让视点与 center extent坐标系一致
    140. float offset = 0.0;
    141. if (direction != 0.0)
    142. {
    143. // 不太理解这一部分的处理方法
    144. while (true)// 左右移动时,X方向,一直调整,直到调整到合适位置
    145. {
    146. centerExtent = GeoExtent(centerExtent.getSRS(),
    147. mapExtent.xMin() + offset, mapExtent.yMin(),
    148. mapExtent.xMax() + offset, mapExtent.yMax());
    149. if (eyeX >= centerExtent.xMin() && eyeX <= centerExtent.xMax())
    150. {
    151. break;
    152. }
    153. offset += direction * centerExtent.width();
    154. // std::cout << "测试移动:direction:" << direction << ", offset: " << offset << std::endl;
    155. }
    156. }
    157. // Update the matrix transforms. 更新矩阵。三个矩阵上,各有一份地图
    158. centerMatrix->setMatrix(osg::Matrixd::translate(offset, 0.0, 0.0));
    159. leftMatrix->setMatrix(osg::Matrixd::translate(offset - mapExtent.width(), 0.0, 0.0));
    160. rightMatrix->setMatrix(osg::Matrixd::translate(offset + mapExtent.width(), 0.0, 0.0));
    161. viewer.frame();
    162. }
    163. }
    164. else
    165. {
    166. return usage(argv[0]);
    167. }
    168. return 0;
    169. }

  • 相关阅读:
    基于反步积分滑模摩擦补偿的光电伺服转台控制
    CIPU落地专有云:是“小众需求”还是“机会之门”?
    AI 律助 Alpha GPT 线上实操发布会,重磅发布!
    带你手撕八大排序
    Windows环境下Scala编程环境搭建
    CAD新手必练图形三
    2023年【G1工业锅炉司炉】报名考试及G1工业锅炉司炉理论考试
    基于SpringBoot的个性化推荐的图书借阅管理系统前后台设计
    求解答 能想的都想了但是还是不对
    c++STL容器(看这一篇就够)
  • 原文地址:https://blog.csdn.net/qq_34732729/article/details/128207908