TANKENQI.cn

November 26, 2024

GeoTrellis 如何对全球范围影像数据进行切片

GIS3.9 min to read

记录一次排查 GeoTrellis 进行影像切片时的错误排查,主要是探讨 GeoTrellis 提供的两种默认切片布局:

WebMercator 和 Latlng,如何切全球范围的影像数据,并通过 Cesium 进行可视化。

1 常见的两种 TMS 瓦片布局

这里我主要是介绍目前用的最多的,也是 Cesium 等 WebGIS 框架中提供的两种默认切片布局,分别是经纬度与 Web 墨卡托,在 Cesium 中对应布局参数为:WebMercatorTilingScheme 和 GeographicTilingScheme

CesiumJS 能用的 TMS 目前只支持两种切片方案(TilingScheme):

0 级瓦片有 2 个的投影,是直接以经纬度数值展平成平面,众所周知:

纬度跨度:经度跨度 = 180:360 = 1:2

所以 GeographicTilingScheme 的样子就是一个一比二的矩形,刚好就在 0 级瓦片时有两个,后续就按常规的四叉树切分即可

WebMercator 投影后的坐标系 xy 值域是 [-20037508.34, 20037508.34]^2,是一个正方形,所以可以按单个0级瓦片进行四叉树切分

2 GeoTrellis 提供的切片布局

GeoTrellis 也是默认提供了两种切片布局,分别是 WebMercator 和 Latlng,阅读其源码,得知,其实就是使用了 EPSG:3857EPSG:4326,下面代码是如何使用 GeoTrellis 构造布局。

import geotrellis.proj4.{CRS, LatLng, WebMercator}// WebMercator 布局val layoutScheme: ZoomedLayoutScheme = ZoomedLayoutScheme(CRS.fromEpsgCode(3857), tileSize = 256)val layoutScheme: ZoomedLayoutScheme = ZoomedLayoutScheme(WebMercator, tileSize = 256)// Latlng 布局,以下两种方式一样val layoutScheme: ZoomedLayoutScheme = ZoomedLayoutScheme(CRS.fromEpsgCode(4326), tileSize = 256)val layoutScheme: ZoomedLayoutScheme = ZoomedLayoutScheme(Latlng, tileSize = 256)

GeoTrellis 提供的 WebMercator 布局与我们熟知的 Web 墨卡托,布局一致,可以正常在 Cesium 中进行加载,但是其提供的 Latlng 布局,与我们熟知的地理坐标系投影不一样,其 0 级瓦片只有 1 个,因此不能在 Cesium 中正常加载。

3 解决方案

我认为主要有三种解决手段:

这三种方式,前两种我都已经测试过,可以解决不兼容的问题,第三种方式我推测也是可以。

3.1 方案一

val tileSize: Int = 256val initialExtent: Extent = Extent(-180, -90, 180, 90)val tileLayout = TileLayout(2, 1, tileSize, tileSize)val layoutScheme: LayoutDefinition = LayoutDefinition(initialExtent, tileLayout)val (zoom, reprojected): (Int, RDD[(SpatialKey, MultibandTile)] with Metadata[TileLayerMetadata[SpatialKey]]) = coverage.reproject(CRS.fromEpsgCode(4326), layoutScheme)
var tmsLayer = viewer.imageryLayers.addImageryProvider(    new Cesium.UrlTemplateImageryProvider({        tilingScheme: new Cesium.GeographicTilingScheme(),        url: "http://10.101.240.60/tms_test/{z}/{x}/{y}.png",    }));

但是这种方式有如个缺点,用上述代码定义的 layoutScheme 生成的 reprojected 会被默认指定为0级,即 zoom = 0,这是因为:

LayoutDefinition 是单一层级布局

未使用层级推导机制

3.2 方案二

// Latlng 布局,以下两种方式一样val layoutScheme: ZoomedLayoutScheme = ZoomedLayoutScheme(CRS.fromEpsgCode(4326), tileSize = 256)val layoutScheme: ZoomedLayoutScheme = ZoomedLayoutScheme(Latlng, tileSize = 256)
const customTilingScheme = new Cesium.GeographicTilingScheme({    rectangle: Cesium.Rectangle.fromDegrees(        -180.0,        -90.0,        180.0,        90.0    ), // 瓦片覆盖范围    numberOfLevelZeroTilesX: 1, // 0 级横向瓦片数(默认是 2)    numberOfLevelZeroTilesY: 1, // 0 级纵向瓦片数(默认是 1)});var tmsLayer = viewer.imageryLayers.addImageryProvider(    new Cesium.UrlTemplateImageryProvider({),        tilingScheme: customTilingScheme,        url: "http://10.101.240.60/tms_test/{z}/{x}/{y}.png",    }));

3.3 方案三

方案三主要是考虑到 EPSG:3857 支持的纬度范围在:85.05113°S 至 85.05113°N,而极地区域的数据如果我们不是很需要的话,实际上我们可以在读取影像数据为 RDD 时就将这部分数据过滤掉,因为比较简单,就没有给出代码,推测也是可以达到效果的。

4 结果展示