Scala/Java
本页介绍如何使用 SedonaViz 可视化空间数据。示例代码使用 Scala 编写,但同样适用于 Java。
SedonaViz 通过对 Sedona 处理大规模空间数据的能力进行扩展,原生支持通用的地图制图设计。它可以可视化空间 RDD 与空间查询,并以并行方式渲染超高分辨率图像。
SedonaViz 提供了 Map Visualization SQL,使用户能更灵活地设计美观的地图可视化效果,包括散点图与热力图。同时也提供 SedonaViz RDD API。
Note
SedonaViz 的 SQL/DataFrame API 全部说明请参阅 SedonaViz API。
为什么需要可扩展的地图可视化¶
数据可视化让用户能够对数据进行总结、分析与推理。要在多个缩放级别上保证细致而准确的地理空间地图可视化,需要极高分辨率的地图。Google Maps、MapBox、ArcGIS 等传统方案受计算资源限制,对大规模地理空间数据生成地图需要花费大量时间。在大空间数据场景下,这类工具往往直接崩溃或长时间无法完成。
SedonaViz 把地图可视化流程的主要步骤(如像素化、聚合、渲染)封装为一组可大规模并行的 GeoViz 算子,用户可以自由组合任意自定义样式。
可视化 SpatialRDD¶
本教程主要介绍 SQL/DataFrame API。
配置依赖¶
- 阅读 Sedona Maven Central 坐标
- 添加 Apache Spark core、Apache SparkSQL、Sedona-core、Sedona-SQL、Sedona-Viz 依赖
创建 Sedona 配置¶
在程序开头使用以下代码创建 Sedona 配置。如果您已经有了由 Wherobots / AWS EMR / Databricks 创建的 SparkSession(通常名为 spark),可跳过此步骤直接使用 spark。
Sedona >= 1.4.1=
val config = SedonaContext.builder()
.config("spark.kryo.registrator", classOf[SedonaVizKryoRegistrator].getName) // org.apache.sedona.viz.core.Serde.SedonaVizKryoRegistrator
.master("local[*]") // 集群模式下请删除此行
.appName("Sedona Viz") // 改成合适的名字
.getOrCreate()
Sedona <1.4.1
下面这种方式自 Sedona 1.4.1 起已弃用,请改用上面的方式。
var sparkSession = SparkSession.builder()
.master("local[*]") // 集群模式下请删除此行
.appName("Sedona Viz") // 改成合适的名字
// 启用 Sedona 自定义 Kryo 序列化器
.config("spark.serializer", classOf[KryoSerializer].getName) // org.apache.spark.serializer.KryoSerializer
.config("spark.kryo.registrator", classOf[SedonaVizKryoRegistrator].getName) // org.apache.sedona.viz.core.Serde.SedonaVizKryoRegistrator
.getOrCreate()
初始化 SedonaContext¶
在创建 Sedona 配置之后加上以下代码。如果您已经有了由 Wherobots / AWS EMR / Databricks 创建的 SparkSession(通常名为 spark),请改为调用 SedonaContext.create(spark)。
Sedona >= 1.4.1=
val sedona = SedonaContext.create(config)
SedonaVizRegistrator.registerAll(sedona)
Sedona <1.4.1
下面这种方式自 Sedona 1.4.1 起已弃用,请改用上面的方式创建 SedonaContext。
SedonaSQLRegistrator.registerAll(sparkSession)
SedonaVizRegistrator.registerAll(sparkSession)
也可以通过在 spark-submit 或 spark-shell 中传入 --conf spark.sql.extensions=org.apache.sedona.viz.sql.SedonaVizExtensions,org.apache.sedona.sql.SedonaSqlExtensions 来一并注册。
创建空间 DataFrame¶
假设有如下 DataFrame:
+----------+---------+
| _c0| _c1|
+----------+---------+
|-88.331492|32.324142|
|-88.175933|32.360763|
|-88.388954|32.357073|
|-88.221102| 32.35078|
首先需要构造一列几何类型的列:
CREATE OR REPLACE TEMP VIEW pointtable AS
SELECT ST_Point(cast(pointtable._c0 as Decimal(24,20)),cast(pointtable._c1 as Decimal(24,20))) as shape
FROM pointtable
Sedona 提供了多种方式加载各种空间数据格式,详见 编写空间 DataFrame 应用。
生成单张图像¶
大多数情况下,您只想从空间数据中得到一张图像。
像素化空间对象¶
要在地图图像上显示空间对象,先要把它们转换为像素。
首先计算该列的空间边界:
CREATE OR REPLACE TEMP VIEW boundtable AS
SELECT ST_Envelope_Aggr(shape) as bound FROM pointtable
然后用 ST_Pixelize 将其转换为像素。
下面这段代码适用于 Sedona v1.0.1 之前。ST_Pixelize 继承自 Generator,因此可以直接展开数组而无需 explode 函数。
CREATE OR REPLACE TEMP VIEW pixels AS
SELECT pixel, shape FROM pointtable
LATERAL VIEW ST_Pixelize(ST_Transform(shape, 'epsg:4326','epsg:3857'), 256, 256, (SELECT ST_Transform(bound, 'epsg:4326','epsg:3857') FROM boundtable)) AS pixel
下面这段代码适用于 Sedona v1.0.1 及之后。ST_Pixelize 返回像素数组,需要使用 explode 展开:
CREATE OR REPLACE TEMP VIEW pixels AS
SELECT pixel, shape FROM pointtable
LATERAL VIEW explode(ST_Pixelize(ST_Transform(shape, 'epsg:4326','epsg:3857'), 256, 256, (SELECT ST_Transform(bound, 'epsg:4326','epsg:3857') FROM boundtable))) AS pixel
执行完本教程末尾的 ST_Render 后,将得到 256*256 分辨率的图像。
Warning
强烈建议先用 ST_Transform 将坐标转换到适合可视化的坐标系(如 epsg:3857),否则地图可能出现变形。
聚合像素¶
许多对象可能被像素化到同一个像素位置。需要按空间聚合或按温度、湿度等空间观测值进行聚合:
CREATE OR REPLACE TEMP VIEW pixelaggregates AS
SELECT pixel, count(*) as weight
FROM pixels
GROUP BY pixel
weight 表示空间聚合或空间观测的程度,后续会决定该像素的颜色。
给像素上色¶
运行以下命令为像素根据 weight 上色:
CREATE OR REPLACE TEMP VIEW pixelaggregates AS
SELECT pixel, ST_Colorize(weight, (SELECT max(weight) FROM pixelaggregates)) as color
FROM pixelaggregates
详细 API 说明请参阅 ST_Colorize。
渲染图像¶
使用 ST_Render 把所有像素绘制到一张图像上:
CREATE OR REPLACE TEMP VIEW images AS
SELECT ST_Render(pixel, color) AS image, (SELECT ST_AsText(bound) FROM boundtable) AS boundary
FROM pixelaggregates
该 DataFrame 中将包含一列 Image 类型的列,且只有一张图像。
将图像保存到磁盘¶
从上面的 DataFrame 中取出图像:
var image = sedona.table("images").take(1)(0)(0).asInstanceOf[ImageSerializableWrapper].getImage
使用 Sedona Viz 的 ImageGenerator 把图像保存到磁盘:
var imageGenerator = new ImageGenerator
imageGenerator.SaveRasterImageAsLocalFile(image, System.getProperty("user.dir")+"/target/points", ImageType.PNG)
生成地图瓦片¶
如果您是地图相关从业者,可能需要为不同缩放级别生成地图瓦片,最终构建出地图瓦片图层。
像素化与像素聚合¶
请先用与单张图像生成相同的命令完成像素化与像素聚合。在 ST_Pixelize 中需要指定较高的分辨率,例如 1000*1000。注意:每个维度都应能被 2^zoom-level 整除。
计算 tile name¶
使用以下命令为每个像素计算 tile name:
CREATE OR REPLACE TEMP VIEW pixelaggregates AS
SELECT pixel, weight, ST_TileName(pixel, 3) AS pid
FROM pixelaggregates
其中 3 表示这些地图瓦片的缩放级别。
像素上色¶
使用与单张图像生成相同的命令进行上色。
渲染地图瓦片¶
把像素按 tile 分组,然后并行渲染各个瓦片图像:
CREATE OR REPLACE TEMP VIEW images AS
SELECT ST_Render(pixel, color, 3) AS image
FROM pixelaggregates
GROUP BY pid
3 是这些地图瓦片的缩放级别。
将地图瓦片保存到磁盘¶
可以沿用单张图像生成中的命令,将所有地图瓦片逐一取出并保存。