其他分享
首页 > 其他分享> > osgearth加载mapbox在线高程数据

osgearth加载mapbox在线高程数据

作者:互联网

osgearth加载在线地图这里就不介绍了,比如osm、mapbox、天地图等,如果有哪位同学需要,我可以下次介绍一下~~~

众所周知,高程数据一直是比较珍贵的,之前是加载谷歌地球的高程,但是近期由于谷歌地址均无法访问,所以考虑加载mapbox的在线高程数据,说到这里,不得不感谢一下mapbox,不仅提供了丰富的可编辑的在线地图数据,还提供了高程数据~~~  https://www.mapbox.com/

首先先看一张mapbox的高程图:

可以看到,mapbox的高程数据数据是rgba四通道的png格式栅格图像数据,而一般的高程数据HeightField是单通道的,

因此,在请求到源数据之后只需要做一次osg::Image -> osg::HeightField 的转换即可。

转换公式官网就有,很贴心:

height = -10000 + ((R * 256 * 256 + G * 256 + B) * 0.1)

通过继承 TileSource 重写 createImage 和 createHeightField 即可实现功能,继承了QObject是想后续完善功能,将数据保存至数据库中,便于后续离线读取,QObject可有可无,详细可参考 Plugin osgearth_tileindex:

using namespace osgEarth;
using namespace osgEarth::Drivers;

class XYZExSource : public QObject, public TileSource
{
	Q_OBJECT

public:
	XYZExSource(const TileSourceOptions& options);
	Status initialize(const osgDB::Options* dbOptions);
	osg::Image* createImage(const TileKey& key, ProgressCallback*  progress);
	virtual std::string getExtension() const
	{
		return _format;
	}

	osg::HeightField* createHeightField(const TileKey& key, ProgressCallback* progress);
private:
	const XYZExOptions       _options;
	std::string            _format;
	std::string            _template;
	std::string            _rotateChoices;
	std::string            _rotateString;
	std::string::size_type _rotateStart, _rotateEnd;
	OpenThreads::Atomic    _rotate_iter;

	osg::ref_ptr<osgDB::Options> _dbOptions;
};

createImage函数与xyz驱动基本一致,照抄即可,这里介绍createHeightField函数:

osg::HeightField* XYZExSource::createHeightField(const TileKey& key, ProgressCallback* progress)
{
	// MapBox encoded elevation PNG.
		// https://www.mapbox.com/blog/terrain-rgb/
	if (1/*_options.elevationEncoding().value() == "mapbox"*/)
	{
		if (getStatus().isError())
			return 0L;

		osg::HeightField *hf = 0;
		osg::ref_ptr<osg::Image> image = createImage(key, progress);
		if (image.valid())
		{
			// Allocate the heightfield.
			hf = new osg::HeightField();
			hf->allocate(image->s(), image->t());

			ImageUtils::PixelReader reader(image.get());
			for (unsigned int c = 0; c < image->s(); c++)
			{
				for (unsigned int r = 0; r < image->t(); r++)
				{
					osg::Vec4 pixel = reader(c, r);
					pixel.r() *= 255.0;
					pixel.g() *= 255.0;
					pixel.b() *= 255.0;
					float h = -10000.0f + ((pixel.r() * 256.0f * 256.0f + pixel.g() * 256.0f + pixel.b()) * 0.1f);
					hf->setHeight(c, r, h);
				}
			}
		}
		return hf;
	}
	else
	{
		return TileSource::createHeightField(key, progress);
	}
}

使用:

osgEarth::Drivers::XYZExOptions exyz;
exyz.url() = "http://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=pk.eyJ1IjoicnpvbGxlciIsImEiOiIzQ1V3clI4In0.2TF5_QTXSR3T7F_dyPd1rg";
exyz.profile()->namedProfile() = "spherical-mercator";
XYZExSource* etileSource = new XYZExSource(exyz);
auto eStatus = etileSource->open();
ElevationLayerOptions eoptions("mapboxEle");
map->addLayer(new ElevationLayer(eoptions, etileSource));

access_token可在mapbox官网自行申请~~~

最后看一下效果:

标签:const,image,osgearth,mapbox,HeightField,pixel,osg,加载
来源: https://blog.csdn.net/luoyongweis/article/details/115313801