Java Hive UDTF 将WKT格式的Geomotry转换成GeoJSON
背景知识
WKT(Well-known text)是一种文本标记语言,用于表示矢量几何对象、空间参照系统及空间参照系统之间的转换。它的二进制表示方式,亦即WKB(well-known-binary)则胜于在传输和在数据库中存储相同的信息。
GeoJSON是一种对各种地理数据结构进行编 码的格式,可以表示几何、特征或者特征集合。
WTK
点 POINT(6 10)
线 LINESTRING(44 4,11 44,33 25)
面 POLYGON((1 1,2 2,3 3,4 4,5 5,1 1),(11 11,2 13,34 43,34 42,52 52,11 11))
多点 MULTIPOINT(44 4,11 44,33 25)
多线 MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))
多面 MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),((6 3,9 2,9 4,6 3)))
几何集合 GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))
对应geojson
点 {“type”:“Point”,“coordinates”:[6,10]}
线 {“type”:“LineString”,“coordinates”:[[44, 4],[11, 44],[33, 25]]}
面 {“type”:“Polygon”,“coordinates”:[[[1, 1],[2, 2],[3, 3],[4, 4],[5, 5],[1, 1]],[[11, 11],[2, 13],[34, 43],[34, 42],[52, 52],[11, 11]]]}
多点 {“type”:“MultiPoint”,“coordinates”:[[44, 4],[11, 44],[33, 25]]}
多线 {“type”:“MultiLineString”,“coordinates”:[[[3, 4],[10, 50],[20, 25]],[[-5, -8],[-10, -8],[-15, -4]]}
多面 {“type”:“MultiPolygon”,“coordinates”:[[[3, 4],[10, 50],[20, 25]],[[-5, -8],[-10, -8],[-15, -4]]]}
几何集合 {“type”:“FeatureCollection”,“features”:[{“type”:“Feature”,“geometry”:{“type”:“Point”,“coordinates”:[4,6]},},{“type”:“Feature”,“geometry”:{“type”:“LineString”,“coordinates”:[[[4,6],[7,10]]}]}
具体需求
目前MULTIPOLYGON不能直接转成geojson,主要是业务方不能处理多面,需要对多面进行拆分成多个Polygon ,具体到hive数据就是实现udtf对这种多面类型的数据进行解析处理,拆分成多行一行代表一个Polygon。
解决方案
方法一:调研库函数直接封装进行处理:比如 vividsolutions jts包 进行处理
vividsolutions比较强大,其实现原理如下:
Geometry类作为基础数据类型,单点、单线、单面都继承Geometry去实现,同时定义了一个GeometryCollection来实现Geometry 底层用Geometry类型的数组数据结果进行存储,多点、多线、多面都继承自GeometryCollection ,基本上解析后只需要对类型进行判断,然后根据类型进行层层处理 比如:多面类型里面有多个面,对多面进行循环解析就可以了。
如下代码片段
// 如下传如一个 Geometry 基础类,这里会利用java多态进行判断
public static JSONObject parsePolygon2Geojson(Geometry geom) throws ParseException {
JSONObject jsonObject = new JSONObject();
String type = geom.getGeometryType();
jsonObject.put("type", geom.getGeometryType());
if ("MultiPolygon".equalsIgnoreCase(type)) {
JSONArray coordJson = new JSONArray();
//geom 实际上底层数据结构是数组,可以从中获取单个Polygon
for (int i = 0; i < geom.getNumGeometries(); i++) {
// polygon
coordJson.add(parsePolygon