(二)水平基准面
根据地理空间测量方法的不同,基准面便会不同。同一个地方也可以有不同的基准标准。因为地球并不是一个完美的球体,甚至不是一个完美的椭球,所以为了拟合地球的形状,特定的地方会选用特定的水平基准面。一般而言,在北美会使用WGS84和NAD83,在欧洲会使用ETR89。
在osgEarth中,默认的水平基准面是WGS84,如果没有为数据设定相应的水平基准信息,osgEarth会默认设置WGS84的相关参数。 (三)高程基准面
高程基准是为了测量高程的。有许多类的高程基准,osgEarth支持两种高程基准:大地基准面(基于椭球)和大地水准面(基于地球上一些高程点)。
osgEarth内置以下四种高程基准面: ①Geodetic(大地基准面)。此为默认高程基准面,osgEarth使用水平基准面椭球来作参考。
②EGM84 geoid(大地水准面) ③EGM96 geoid(大地水准面),一般被称为MSL,在DTED和KML数据中会被使用
④EGM2008 geoid(大地水准面)
在osgEarth中,默认的高程基准面是geodetic高程水准面,海拔依据HAE(height above ellipsoid)来测量。 (四)投影
SRS同时也提供投影信息,即将三维点投影到二维平面的方法。 因为osgEarth依赖GDAL和OGR两个工具库,所以它能支持上千种投影方法,如有名的UTM投影,兰伯特投影。
SRS使用WKT(Well Known Text),PROJ4或EPSG方式来表达SRS空间参考系。这三种方式都是国际上比较通用的方式,这也增加了osgEarth的通用性。本文就不详细介绍这三种空间参考系表达方法了。
2.2 数据组织及位置确定
在前文的数据预处理中有提到过,osgEarth是实时建立分层瓦片集来进行实时渲染。简单而言,osgEarth就是通过记录了SRS和范围信息的profile属性,创建瓦片数据TileSource,并通过TileKey来进行四叉树进行管理。
(-180,90)
(180,90)
西半球
东半球
第一层
lod:0
(-180,-90) (-180,90)
TileKey
第二层
lod:1
x 0 1
2 3
0 1 2 3 4 5 6 7 第三层
y
lod:2
………… TileKey(2,5,1)
图3.14 瓦片分层LOD
如图3.14所示,osgEarth中的世界范围是以经纬度来表示,若将球形表面剖开铺成平面,其最左为西经180度,最右为东经180度,最上为北纬90度,最下为南纬90度。
实时加载时,osgEarth会根据map或数据的profile属性实时进行分层瓦片化。表3.1列出的是profile中关于瓦片分层的一些属性,其中的数值是一个全球影像数据的属性值。下面将会详细解说osgEarth如何利用这些数据将数据分层瓦片化,并确定数据的位置。
extent srs west east south north numTilesWideAtLod0 numTilesHighAtLod0 fullSignature horizSignature 空间参考系 -180 180 -90 90 2 1 3be5346 3be5346 profile 表3.1 map对象profile属性 numTilesWideAtLod0和 numTilesHighAtLod0是确定最高一层的宽度与高度,即行数与列数。默认是宽度为2,高度为1。这个默认值正好将第一层的全球数据分成东西半球。然后osgEarth将继续向下分层瓦片,随着一层层的深入,地形
块就变得越来越小。当地形块大小比视点到块的距离还小时,便不再继续深入了。
每向下深入一层,每一个瓦片TileSource便会等分成四块。每一个瓦片TileSource均有一个TileKey进行管理,上一层的TileKey会有下一层的4个子key,由此体现了四叉树组织的思想。
在osgEarth中,瓦片的左上角是原点,TileKey便是从左上角开始编码。一般为TileKey(lod,x,y),如图10中第三层瓦片所示。其中阴影部分所对应的key为TileKey(2,5,1)。
随着瓦片的细化,每一块瓦片的范围也会逐渐变小。如图10中第三层瓦片里的阴影区域,其坐标范围便是西至东经45度,东至东经90度,南至赤道,北至北纬45度的瓦片块。这些数值将被记录到这个瓦片的extent属性中,如表2所示,其对应值分别为west,east、south和north。
当数据源在此范围内有数据时,此瓦片便会加载,否则不会加载。这样总的加载块数也不会那么多。同时根据这个范围,osgEarth将会确定了数据所处位置。
2.3 缓存编码
osgEarth支持缓存机制,可以提前将网络数据缓存在本地,使快速访问。图3.15便是一个缓存文件夹的示例。
第一层
第二层
第三层 第四层
图3.15 缓存文件夹
图3.15中,第一层的文件夹名称是缓存的名称编号。一般一个cache只加载一个数据源。图3.15中显示的缓存包括三个数据源的数据。第二层,第三层和第四层,就分别按TileKey的(lod,x,y)来进行编码,最里层的osgb是osg的一种二进制文件,便存储了每个瓦片tileSource的数据。在每一个数据源的缓存文件夹中,包括了一个记载数据源属性的json文件。从图3.15可知,第一层的数据源缓存文件夹编码似乎是乱码,其实其为利用哈希算法压缩过的conf配置属性。
如图3.15中的缓存文件夹617891fe_3be5346,可以分为两段来理解。第一段是下划线前面的字符串61781fe,代表着cacheId,第二段是下划线后面的字符串3be5346,代表HorizSignature,水平署名。
第一段的cacheId是在分解conf属性,构建map对象的时候计算的。它只取得map的layer中的tilesource的conf属性,将其写成Json文件,然后对此文件使用MumurHash算法,进行哈希压缩,最后形成cacheId的字符串。具体流程见图3.16。
Layer->setCache(this->getCache());Config layerConf = _runtimeOptions->getConfig( true );Config driverConf = _runtimeOptions->driver()->getConfig();Config hashConf = driverConf - layerConf;只获取tilesource的config,然后将之转换成JSON格式,使用MumurHash算法将其进行哈希字符串处理,转换成十六进制的cacheId。hashConf.remove( \hashConf.remove( \hashConf.remove( \hashConf.remove( \cacheId = Stringify() << std::hex << osgEarth::hashString(hashConf.toJSON());
图3.16 cacheId计算流程
第二段的horizSignature(表2中也有此属性),是在用map构造mapNode时获取map的profile属性时计算。此时,获取map中可以确定空间信息的水平基准面、垂直基准面、地图范围、numTileWideAtLod0、numTilesHighAtLod0属性,这些属性构成的conf属性,同cacheId一样,先转换成Json文件,然后对此文件使用MumurHash算法,进行哈希压缩,最后形成horizSignature的字符串。 所以,缓存的文件名并不是乱码,也是包含了数据源tilesource与map的空间信息的。