blob: e985f1db02087ac84838808ba21a70df7194ff07 [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
本页介绍如何使用 SedonaViz 可视化空间数据。==示例代码使用 Scala 编写,但同样适用于 Java==。
SedonaViz 通过对 Sedona 处理大规模空间数据的能力进行扩展,原生支持通用的地图制图设计。它可以可视化空间 RDD 与空间查询,并以并行方式渲染超高分辨率图像。
SedonaViz 提供了 Map Visualization SQL,使用户能更灵活地设计美观的地图可视化效果,包括散点图与热力图。同时也提供 SedonaViz RDD API。
!!!note
SedonaViz 的 SQL/DataFrame API 全部说明请参阅 [SedonaViz API](../api/viz/sql.md)。
## 为什么需要可扩展的地图可视化
数据可视化让用户能够对数据进行总结、分析与推理。要在多个缩放级别上保证细致而准确的地理空间地图可视化,需要极高分辨率的地图。Google Maps、MapBox、ArcGIS 等传统方案受计算资源限制,对大规模地理空间数据生成地图需要花费大量时间。在大空间数据场景下,这类工具往往直接崩溃或长时间无法完成。
SedonaViz 把地图可视化流程的主要步骤(如像素化、聚合、渲染)封装为一组可大规模并行的 GeoViz 算子,用户可以自由组合任意自定义样式。
## 可视化 SpatialRDD
本教程主要介绍 SQL/DataFrame API。
## 配置依赖
1. 阅读 [Sedona Maven Central 坐标](../setup/maven-coordinates.md)
2. 添加 [Apache Spark core](https://mvnrepository.com/artifact/org.apache.spark/spark-core_2.11)、[Apache SparkSQL](https://mvnrepository.com/artifact/org.apache.spark/spark-sql)、Sedona-core、Sedona-SQL、Sedona-Viz 依赖
## 创建 Sedona 配置
在程序开头使用以下代码创建 Sedona 配置。如果您已经有了由 Wherobots / AWS EMR / Databricks 创建的 SparkSession(通常名为 `spark`),可跳过此步骤直接使用 `spark`。
==Sedona >= 1.4.1===
```scala
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 起已弃用,请改用上面的方式。
```scala
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===
```scala
val sedona = SedonaContext.create(config)
SedonaVizRegistrator.registerAll(sedona)
```
==Sedona <1.4.1==
下面这种方式自 Sedona 1.4.1 起已弃用,请改用上面的方式创建 SedonaContext。
```scala
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|
```
首先需要构造一列几何类型的列:
```sql
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 应用](sql.md)。
## 生成单张图像
大多数情况下,您只想从空间数据中得到一张图像。
### 像素化空间对象
要在地图图像上显示空间对象,先要把它们转换为像素。
首先计算该列的空间边界:
```sql
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** 函数。
```sql
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** 展开:
```sql
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),否则地图可能出现变形。
### 聚合像素
许多对象可能被像素化到同一个像素位置。需要按空间聚合或按温度、湿度等空间观测值进行聚合:
```sql
CREATE OR REPLACE TEMP VIEW pixelaggregates AS
SELECT pixel, count(*) as weight
FROM pixels
GROUP BY pixel
```
`weight` 表示空间聚合或空间观测的程度,后续会决定该像素的颜色。
### 给像素上色
运行以下命令为像素根据 weight 上色:
```sql
CREATE OR REPLACE TEMP VIEW pixelaggregates AS
SELECT pixel, ST_Colorize(weight, (SELECT max(weight) FROM pixelaggregates)) as color
FROM pixelaggregates
```
详细 API 说明请参阅 [ST_Colorize](../api/viz/sql.md#st_colorize)。
### 渲染图像
使用 `ST_Render` 把所有像素绘制到一张图像上:
```sql
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` 把图像保存到磁盘:
```scala
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:
```sql
CREATE OR REPLACE TEMP VIEW pixelaggregates AS
SELECT pixel, weight, ST_TileName(pixel, 3) AS pid
FROM pixelaggregates
```
其中 `3` 表示这些地图瓦片的缩放级别。
### 像素上色
使用与单张图像生成相同的命令进行上色。
### 渲染地图瓦片
把像素按 tile 分组,然后并行渲染各个瓦片图像:
```sql
CREATE OR REPLACE TEMP VIEW images AS
SELECT ST_Render(pixel, color, 3) AS image
FROM pixelaggregates
GROUP BY pid
```
`3` 是这些地图瓦片的缩放级别。
### 将地图瓦片保存到磁盘
可以沿用单张图像生成中的命令,将所有地图瓦片逐一取出并保存。