osgearth_infinitescroll示例,是一个可以将二维地图无限拖动的示例。在示例中,可以控制黄色的线一直显示,两张覆盖图默认显示,但拖动地图的时候,有时候显示有时候不显示。
之前一直没有找到如何通过earth文件的方式加载二维地图,真是众里寻他千百度,那earth文件竟在此处呀。
earth文件如下:两个地方重点,一个是 map 的 type,一个是options标签。之前一直加不上,是因为没有设置 options标签。其他的annotations图元,就可以照葫芦画瓢的添加了。
执行命令: osgearth_infinitescrolld.exe earth_image\world_projected.earth
左移和右移的打印输入部分内容:
测试移动:direction:-1, offset: -4.0075e+07
测试移动:direction:-1, offset: -4.0075e+07
测试移动:direction:1, offset: 4.0075e+07
测试移动:direction:1, offset: 4.0075e+07
测试移动:direction:1, offset: 4.0075e+07
#include
#include
#include
#include
#include
#include
#include
#include
#define LC "[viewer] "
using namespace osgEarth;
using namespace osgEarth::Util;
int
usage(const char* name)
{
OE_NOTICE
<< "\nUsage: " << name << " file.earth" << std::endl
<< MapNodeHelper().usage() << std::endl;
return 0;
}
int
main(int argc, char** argv)
{
osg::ArgumentParser arguments(&argc,argv);
// help?
if ( arguments.read("--help") )
return usage(argv[0]);
// 通过vfov,设置视角大小。
// 增大fov值以提供更沉浸的体验。vfov:视野(Field of View),通常设置45度
float vfov = -1.0f;
arguments.read("--vfov", vfov);
// create a viewer:
osgViewer::Viewer viewer(arguments);
// Tell the database pager to not modify the unref settings
// 保持 database pager 默认设置
viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( true, false );
// thread-safe initialization of the OSG wrapper manager. Calling this here
// prevents the "unsupported wrapper" messages from OSG
// OSG包装器管理器的线程安全初始化。
// 在这里调用它可以防止来自OSG的“不支持的包装器”消息
osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
// install our default manipulator (do this before calling load)
// 安装默认操作器
osg::ref_ptr< EarthManipulator > manipulator = new EarthManipulator(arguments);
viewer.setCameraManipulator( manipulator );
// disable the small-feature culling
viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
// set a near/far ratio that is smaller than the default. This allows us to get
// closer to the ground without near clipping. If you need more, use --logdepth
// 设置 近远率
viewer.getCamera()->setNearFarRatio(0.0001);
if ( vfov > 0.0 )
{
// 设置 透视投影矩阵
double fov, ar, n, f;
viewer.getCamera()->getProjectionMatrixAsPerspective(fov, ar, n, f);
viewer.getCamera()->setProjectionMatrixAsPerspective(vfov, ar, n, f);
}
// load an earth file, and support all or our example command-line options
// and earth file tags
osg::ref_ptr< osg::Node > node = MapNodeHelper().load(arguments, &viewer);
osg::ref_ptr< MapNode > mapNode = MapNode::findMapNode(node.get());
if ( mapNode.valid() )
{
// 如果是地球类型,则报错退出
if (mapNode->isGeocentric())
{
OE_NOTICE << "Please run this example with a projected earth file" << std::endl;
return 1;
}
// GeoExtent 轴对齐的地理空间范围。与空间参照的坐标系对齐的边界框。
// 不是特清楚 GeoExtent 类具体的意义。在这里先假设 mapExtene是二维坐标空间。
GeoExtent mapExtent = mapNode->getMap()->getProfile()->getExtent();
//Disable the middle mouse by default, which is rotate. This will keep us in 2D mode.
// 禁止中轮的旋转操作
manipulator->getSettings()->bindMouse(osgEarth::Util::EarthManipulator::ACTION_NULL, osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON, 0);
// Compute a sensible max range so that the user can't zoom out too far to where we need more than 3 transforms.
// 计算一个合理的最大范围,这样用户就不会缩缩放太远以至于需要3次以上变换才能回到合适位置。
// width():东西跨度。 height():南北跨度
double maxDim = osg::maximum(mapExtent.width(), mapExtent.height());// 返回二者中较大的
double range = ((0.5 * maxDim) / 0.267949849);// 暂时不理解这个计算,总之 range > maxDim
manipulator->getSettings()->setMinMaxDistance(0.0, range);
osg::Group* root = new osg::Group;
// We're going to draw the map three times so that we can provide an infinite view scrolling left to right.
// 我们将绘制三份地图,以便提供从左向右滚动的无限视图。
// The centerMatrix is centered around the eye point.
// 以视点为中心的矩阵
osg::MatrixTransform* centerMatrix = new osg::MatrixTransform;
centerMatrix->addChild( mapNode );
root->addChild( centerMatrix );
// The left matrix is to the left of the center matrix
// 中心左侧的矩阵
osg::MatrixTransform* leftMatrix = new osg::MatrixTransform;
leftMatrix->addChild( mapNode );
root->addChild( leftMatrix );
// The right matrix is to the right of the center matrix
// 中心右侧矩阵
osg::MatrixTransform* rightMatrix = new osg::MatrixTransform;
rightMatrix->addChild( mapNode );
root->addChild( rightMatrix );
viewer.setSceneData( root );
while (!viewer.done())
{
// Get the current viewpoint from the EarthManipulator
// 获取操作器的视点信息
Viewpoint vp = manipulator->getViewpoint();
double eyeX = vp.focalPoint()->x();
// focalPoint() 相机所指向的地理空间位置。
GeoPoint focalPoint = *vp.focalPoint();
// Adjust the focal point if the user is trying to too far north or south.
// 如果用户拖动地图太北或者太南,则调整焦点
if (focalPoint.y() > mapExtent.yMax())
{
focalPoint.y() = mapExtent.yMax();
vp.focalPoint() = focalPoint;
manipulator->setViewpoint( vp );
}
else if (focalPoint.y() < mapExtent.yMin())
{
focalPoint.y() = mapExtent.yMin();
vp.focalPoint() = focalPoint;
manipulator->setViewpoint( vp );
}
// 这是为中心图的坐标空间??
GeoExtent centerExtent = mapExtent;
// Figure out which direction we need to shift the map extent
// 找出我们需要改变地图范围的方向
float direction = 0.0;
if (eyeX < mapExtent.xMin())// 视点在坐标范围的左侧,则图左移。
{
// Move to the left
direction = -1.0;
}
else if (eyeX > mapExtent.xMax())
{
// Move to the right
direction = 1.0;
}
// Shift the center extent so that it's centered around the eye point.
// 转换中心坐标,以至于总能 让视点与 center extent坐标系一致
float offset = 0.0;
if (direction != 0.0)
{
// 不太理解这一部分的处理方法
while (true)// 左右移动时,X方向,一直调整,直到调整到合适位置
{
centerExtent = GeoExtent(centerExtent.getSRS(),
mapExtent.xMin() + offset, mapExtent.yMin(),
mapExtent.xMax() + offset, mapExtent.yMax());
if (eyeX >= centerExtent.xMin() && eyeX <= centerExtent.xMax())
{
break;
}
offset += direction * centerExtent.width();
// std::cout << "测试移动:direction:" << direction << ", offset: " << offset << std::endl;
}
}
// Update the matrix transforms. 更新矩阵。三个矩阵上,各有一份地图
centerMatrix->setMatrix(osg::Matrixd::translate(offset, 0.0, 0.0));
leftMatrix->setMatrix(osg::Matrixd::translate(offset - mapExtent.width(), 0.0, 0.0));
rightMatrix->setMatrix(osg::Matrixd::translate(offset + mapExtent.width(), 0.0, 0.0));
viewer.frame();
}
}
else
{
return usage(argv[0]);
}
return 0;
}