GeoSparkViz 可视化
上一节我们使用GeoSpark SQL简单进行了空间的一些操作,本节我们继续利用GeoSpark SQL以及GeoSparkViz将我们的结果进行渲染展示。下面是我们今天要用到的新的6个SQL函数:
-
CAST ( expression AS type ):这是PostGresql原生提供的函数,用于字段类型转换 -
ST_Point (X:decimal, Y:decimal, UUID1, UUID2, ...):从给定的X和Y生成一个点要素。 -
ST_Pixelize (A:geometry, ResolutionX:int, ResolutionY:int, Boundary:geometry):将给定的geometry转为图片中的像素。 -
ST_Colorize (weight:Double, maxWeight:Double, mandatory color: string (Optional)):给定一个像素的权重,返回相应的颜色。权重可以是任意含义的数值,比如温度和湿度等观测值。 -
ST_Render (A:pixel, B:color):给定像素和颜色,生成Java中的BufferedImage对象,代表了一副图片。 -
ST_Envelope_Aggr (A:geometryColumn):返回A的最小外接矩形
加载数据
SparkSession spark = SparkSession.builder().
config("spark.serializer","org.apache.spark.serializer.KryoSerializer").
config("spark.kryo.registrator", "org.datasyslab.geospark.serde.GeoSparkKryoRegistrator").
master("local[*]").appName("Learn05").getOrCreate();
GeoSparkSQLRegistrator.registerAll(spark);
GeoSparkVizRegistrator.registerAll(spark);
// 加载CSV文件,CSV中的第一列为WKT格式
String inputCSVPath = Learn04.class.getResource("/checkin.csv").toString();
Dataset rawDF = spark.read().format("csv").
option("delimiter", ",").
option("header", "false").
load(inputCSVPath);
rawDF.createOrReplaceTempView("pointtable");
构建几何图形(Geometry)
// 创建Geometry列
String sqlText = "select ST_Point(cast(_c0 as Decimal(24,20)), cast(_c1 as Decimal(24,20))) AS shape, _c2 from pointtable";
Dataset spatialDf = spark.sql(sqlText);
spatialDf.createOrReplaceTempView("pointtable");
spatialDf.show();
+--------------------+----------+
| shape| _c2|
+--------------------+----------+
|POINT (-88.331492...| hotel|
|POINT (-88.175933...| gas|
|POINT (-88.388954...| bar|
|POINT (-88.221102...|restaurant|
+--------------------+----------+
渲染
接下来就要对上面四个点进行展示,首先我们要将地理位置转为屏幕上的像素坐标,首先使用ST_Pixelize,但是ST_Pixelize要求首先提供一个边界范围,所以我们先用ST_Envelope_Aggr来生成bound。
sqlText = "SELECT ST_Envelope_Aggr(shape) as bound FROM pointtable";
spatialDf = spark.sql(sqlText);
spatialDf.createOrReplaceTempView("boundtable");
spatialDf.show();
+--------------------+
| bound|
+--------------------+
|POLYGON ((-88.388...|
+--------------------+
生成像素
sqlText = "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";
spatialDf = spark.sql(sqlText);
spatialDf.createOrReplaceTempView("pixels");
spatialDf.show();
+--------------------+--------------------+
| pixel| shape|
+--------------------+--------------------+
|Pixel(x=69.0, y=0...|POINT (-88.331492...|
|Pixel(x=255.0, y=...|POINT (-88.175933...|
|Pixel(x=0.0, y=23...|POINT (-88.388954...|
|Pixel(x=201.0, y=...|POINT (-88.221102...|
+--------------------+--------------------+
生成颜色
本次仅仅是展示点,因此可以给每个点固定的颜色,所以这里权重就填1。
sqlText = "SELECT ST_Colorize(1, 1, 'red') as color, pixel FROM pixels";
spatialDf = spark.sql(sqlText);
spatialDf.createOrReplaceTempView("pixelaggregates");
spatialDf.show(false);
+------+----------------------------------------------------------------------------+
|color |pixel |
+------+----------------------------------------------------------------------------+
|-65536|Pixel(x=69.0, y=0.0, width=256, height=256, isDuplicate=false, tileId=-1) |
|-65536|Pixel(x=255.0, y=255.0, width=256, height=256, isDuplicate=false, tileId=-1)|
|-65536|Pixel(x=0.0, y=230.0, width=256, height=256, isDuplicate=false, tileId=-1) |
|-65536|Pixel(x=201.0, y=186.0, width=256, height=256, isDuplicate=false, tileId=-1)|
+------+----------------------------------------------------------------------------+
渲染
在得到像素点和颜色后,就可以调用ST_Render生成图片了
sqlText = "SELECT ST_Render(pixel, color) AS image, (SELECT ST_AsText(bound) FROM boundtable) AS boundary FROM pixelaggregates" ;
spatialDf = spark.sql(sqlText);
spatialDf.createOrReplaceTempView("images");
spatialDf.show();
+--------------------------+--------------------+
| image| boundary|
+--------------------------+--------------------+
|Image(width=256height=256)|POLYGON ((-88.388...|
+--------------------------+--------------------+
保存图片
Dataset<org.apache.spark.sql.Row> images = spark.table("images");
Row[] take = (Row[])images.take(1);
ImageSerializableWrapper image = (ImageSerializableWrapper)take[0].get(0);
new ImageGenerator().SaveRasterImageAsLocalFile(image.getImage(),System.getProperty("user.home") + "/point", ImageType.PNG);

1559199793770.png