Java和GDAL实现的GeoJSON数据读取与入库实践

Java和GDAL实现的GeoJSON数据读取与入库实践目录前言一 基础数据介绍数据格式数据参数二 空间数据库设计主体表模型 DDL 语句与空间索引三 GDAL 解析及入库 GDAL 中 GeoJSON 驱动解析 GeoJSONJava 模型数据入库四 总结前言在面向空间的矢量数据处理过程当中 虽然 shapefi

欢迎大家来到IT世界,在知识的湖畔探索吧!

目录

前言

一、基础数据介绍

  1. 数据格式
  2. 数据参数

二、空间数据库设计

  1. 主体表模型
  2. DDL语句与空间索引

三、GDAL解析及入库

  1. GDAL中GeoJSON驱动
  2. 解析GeoJSON
  3. Java模型
  4. 数据入库

四、总结

前言

在面向空间的矢量数据处理过程当中,虽然shapefile等文件是常用矢量文件的载体。也是大多数应用用来支持矢量文件存储的对象。其实除了shagefile这种格式,还有很多种格式。今天介绍一种在webgis比较常见的数据格式,它就是GeoJSON。

GeoJSON是一种对各种地理数据结构进行编码的格式,基于Javascript对象表示法(JavaScript Object Notation, 简称JSON)的地理空间信息数据交换格式。GeoJSON对象可以表示几何、特征或者特征集合。GeoJSON支持下面这几种几何类型:点、线、面、多点、多线、多面和几何集合。GeoJSON里的特征包含一个几何对象和其他属性,特征集合表示一系列特征。

一个完整的GeoJSON数据结构总是一个(JSON术语里的)对象。在GeoJSON里,对象由名/值对–也称作成员的集合组成。对每个成员来说,名字总是字符串。成员的值要么是字符串、数字、对象、数组,要么是下面文本常量中的一个:”true”,”false”和”null”。数组的值是上面所说的元素组成。

GeoJSON的格式

  • GeoJSON总是由一个单独的对象组成。这个对象(指的是下面的GeoJSON对象)表示几何、特征或者特征集合。
  • GeoJSON对象可能有任何数目成员(名/值对)。
  • GeoJSON对象必须有一个名字为”type”的成员。这个成员的值是由GeoJSON对象的类型所确定的字符串。
  • type成员的值必须是下面之一:”Point”, “MultiPoint”, “LineString”, “MultiLineString”, “Polygon”, “MultiPolygon”, “GeometryCollection”, “Feature”, 或者 “FeatureCollection”。这些值分别对应:点、多点、线、多线、面、多面、几何集合、特征、特征集合。
  • GeoJSON对象可能有一个可选的”crs”成员,它的值必须是一个坐标参考系统的对象。
  • GeoJSON对象可能有一个”bbox”成员,它的值必须是边界框数组。
{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }, { "type": "Feature", "geometry": { "type": "LineString", "coordinates": [[102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]] }, "properties": { "prop0": "value0", "prop1": 0.0 } }, { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]] }, "properties": { "prop0": "value0", "prop1": { "this": "that" } } } ] }

欢迎大家来到IT世界,在知识的湖畔探索吧!

本文将重点讲解在Java中如何调用GDAL进行GeoJSON矢量数据处理,首先使用QGIS工具展示待处理的地名GeoJSON数据,然后介绍在PostGIS空间数据库中创建空间表,最后介绍基于Java语言调用GDAL将GeoJSON进行空间数据入库。如果当前您也有GeoJSON数据的处理,不妨来博客指导一二。

一、基础数据介绍

今天要处理的示例数据是地名数据,原始数据由GISer last 分享,大家有兴趣的可以在他的个人公众号下回复消息,及时获取信息。时间大概是2015年左右的全国分级数据,有省会城市地名、地级市地名、县级市地名、区县地名等,都是以GeoJSON形式的保存的。

本小节以Qgis为例,对下载下来的GeoJSON数据进行处理。包括空间可视化、属性数据展示、地图标注等。GeoJSON其实也是一种json,只是在普通的json上面增加了空间数据的属性和规范。所以我们可以直接使用文本的形式来进行数据的编辑与展示。

1、 数据格式

地名数据主要是一些点位数据,除了在乡镇一级数据条数多一点之外,其它都还可以都没有超过MB。下面使用Qgis对这些数据打开来看一下。

Java和GDAL实现的GeoJSON数据读取与入库实践



欢迎大家来到IT世界,在知识的湖畔探索吧!

将GeoJSON数据加载到Qgis当中去之后,查看这些空间数据的属性。比如投影信息、属性信息等等。为了方便数据的展示,辅助添加了省级行政区划矢量数据。打开相关标注后,可以看到x效果如下:

Java和GDAL实现的GeoJSON数据读取与入库实践

省会地名数据示意图

Java和GDAL实现的GeoJSON数据读取与入库实践

地级市地名示意图

Java和GDAL实现的GeoJSON数据读取与入库实践

县级市地名示意图

2、数据参数

在qgis中查看数据的属性信息,可以看到如下信息。

序号

参数

说明

1

存储类型

GeoJSON

2

编码

UTF-8

3

几何图形

Point (Point)

4

坐标参考系

EPSG:4326 – WGS 84 – 地理的

5

范围

87.00550,20.00261 :

126.00131,45.00604

6

单位

数据属性信息如下:

序号

属性名

数据类型

说明

1

NAME

String

地名

2

PIINYIN

String

地名拼

3

CLASS

String

类型

4

BZ

String

备注

5

SLX

String

应该是标记,暂无特殊含义

Java和GDAL实现的GeoJSON数据读取与入库实践

序号

数据名称

数据条数

1

省会城市地名

29

2

地级市地名

283

3

县级市地名

339

4

区县地名

2567

有了上面的数据参数基础和属性数据基础之后。下面我们介绍如何进行空间数据库表的设计。

二、空间数据库设计

为了将GeoJSON数据保存到空间数据,我们需要设计对应的数据库表。这里我们采用PostGIS数据库,数据表采用PostGIS中的空间表。本小节将重点讲解讲解空间表的设计。

1、主体表模型

为了实现数据对象到数据库物理模型的对应。针对上述业务,我们建立1对1的映射。保留原有空间属性的独立性,同时增加表主键以及关键的空间信息字段geom。为了后续我们方便的对空间数据进行空间索引查询,在geom列上,我们构建了关键的GIST空间索引。

Java和GDAL实现的GeoJSON数据读取与入库实践

2、DDL语句与空间索引

请注意,空间索引必须要创建,否则在进行空间查询时性能很慢。提前新建好索引,对后续的性能提升有很大的帮助。

欢迎大家来到IT世界,在知识的湖畔探索吧!CREATE TABLE "public"."biz_geographic_name" ( "pk_id" int8 NOT NULL, "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, "pinyin" varchar(255) COLLATE "pg_catalog"."default", "classz" varchar(4) COLLATE "pg_catalog"."default", "bz" varchar(100) COLLATE "pg_catalog"."default", "slx" varchar(20) COLLATE "pg_catalog"."default", "geom" "public"."geometry" NOT NULL, CONSTRAINT "pk_biz_geographic_name" PRIMARY KEY ("pk_id") ) ; ALTER TABLE "public"."biz_geographic_name" OWNER TO "ghy01"; CREATE INDEX "idex_biz_geographic_name_classz" ON "public"."biz_geographic_name" USING btree ( "classz" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST ); CREATE INDEX "idx_biz_geographic_name_geom" ON "public"."biz_geographic_name" USING gist ( "geom" "public"."gist_geometry_ops_2d" ); COMMENT ON COLUMN "public"."biz_geographic_name"."pk_id" IS '主键id'; COMMENT ON COLUMN "public"."biz_geographic_name"."name" IS '地名'; COMMENT ON COLUMN "public"."biz_geographic_name"."pinyin" IS '汉语拼音'; COMMENT ON COLUMN "public"."biz_geographic_name"."classz" IS 'classz'; COMMENT ON COLUMN "public"."biz_geographic_name"."bz" IS '备注'; COMMENT ON COLUMN "public"."biz_geographic_name"."slx" IS 'slx'; COMMENT ON COLUMN "public"."biz_geographic_name"."geom" IS '空间对象'; COMMENT ON TABLE "public"."biz_geographic_name" IS '地名基础信息表,用于存储中国范围内的地名信息';

至此,我们完成了地名表的空间数据库表的设计,同时根据业务需要,创建了数据索引。

三、GDAL解析及入库

本节主要讲解如何利用GDAL来进行数据的解析,使用详细的代码讲解如何解析GeoJSON数据,最后调用MP框架实现将GeoJSON数据保存到空间数据库。

1、GDAL中GeoJSON驱动

在Gdal中,针对不同的数据格式,使用不同的驱动包来解析支持。与解析shapefile的方式一致。解析GeoJSON使用GeoJSON驱动。此驱动程序实现对访问编码在中的功能的读/写支持 GeoJSON 格式。GeoJSON是一种基于 JavaScript Object Notation

  • (JSON) . JSON是一种用于数据交换的轻量级纯文本格式,GeoJSON只不过是它对地理内容的专门化。
  • FLATTEN_NESTED_ATTRIBUTES =是/否:是否递归地探索嵌套对象并生成扁平OGR属性。默认为否。
  • NESTED_ATTRIBUTE_SEPARATOR =字符:嵌套属性组件之间的分隔符。默认为“
  • FEATURE_SERVER_PAGING =是/否:是否使用ArcGIS功能服务终结点自动滚动结果。
  • NATIVE_DATA =是/否:(GDAL>=2.1)是否在FeatureCollection和Feature级别存储本机JSon表示。默认为否。此选项可用于通过保留一些额外的JSon对象来改进从GeoJSON到GeoJSON的往返,否则OGR抽象将忽略这些额外的JSon对象。请注意,ogr2ogr在默认情况下启用此选项,除非指定其-noNativeData开关。
  • ARRAY_AS_STRING =YES/NO:(GDAL>=2.1)是否将字符串、整数或实数的JSon数组作为OGR字符串公开。默认为“否”。也可以使用 OGR_GEOJSON_ARRAY_AS_STRING 配置选项。
  • DATE_AS_STRING =YES/NO:(GDAL>=3.0.3)是使用专用的OGR日期/时间/日期时间类型还是作为OGR字符串公开日期/时间/日期时间内容。默认值为NO(即检测到日期/时间/日期-时间)。也可以用 OGR_GEOJSON_DATE_AS_STRING 配置选项。

2、解析GeoJSON

在Java中解析GeoJSON的关键代码如下:

@Test public void readDjsGeoJSON() { // 指定文件的名字和路径 String strVectorFile = "path/2015省市区县乡镇地名数据/地名点_地级市.geojson"; // 注册所有的驱动 ogr.RegisterAll(); gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8"); String strDriverName = "GeoJSON"; org.gdal.ogr.Driver oDriver = ogr.GetDriverByName(strDriverName); if (oDriver == null) { System.out.println(strDriverName + " 驱动不可用!\n"); return; } DataSource dataSource = oDriver.Open(strVectorFile); Layer layer = dataSource.GetLayer(0); SpatialReference spatialReference = layer.GetSpatialRef(); String srid = spatialReference.GetAttrValue("AUTHORITY", 1); long featureCount = layer.GetFeatureCount(); List<GeographicName> list = new ArrayList<GeographicName>(); for (int i = 0; i < featureCount; i++) { Feature feature = layer.GetFeature(i); String name = feature.GetFieldAsString("NAME"); String pinyin = feature.GetFieldAsString("PINYIN"); String classz = feature.GetFieldAsString("CLASS"); String bz = feature.GetFieldAsString("BZ"); String slx = feature.GetFieldAsString("SLX"); Geometry geom = feature.GetGeometryRef(); //step 1、生成原始wkt String wkt = geom.ExportToWkt(); wkt = "SRID=" + srid +";" + wkt;//拼接srid,实现动态写入 list.add(new GeographicName(name, pinyin, classz, bz, slx, wkt)); System.out.println("name=" + name + "\tclassz=" + classz+ "\twkt="+ wkt); } geographicNameService.saveBatch(list,300); dataSource.delete(); gdal.GDALDestroyDriverManager(); }

3、Java模型

下面提供基础的Java实体模型,其它比如Mapper和Service对象,不进行代码说明。

欢迎大家来到IT世界,在知识的湖畔探索吧!package com.yelang.project.extend.earthquake.domain; import java.io.Serializable; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.yelang.framework.handler.PgGeometryTypeHandler; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; @Data @ToString @AllArgsConstructor @NoArgsConstructor @TableName(value ="biz_geographic_name",autoResultMap = true) public class GeographicName implements Serializable{ private static final long serialVersionUID = -L; @TableId(value = "pk_id") private Long pkId; private String name; private String pinyin; private String classz; private String bz; private String slx; public GeographicName(String name, String pinyin, String classz, String bz, String slx, String geom) { super(); this.name = name; this.pinyin = pinyin; this.classz = classz; this.bz = bz; this.slx = slx; this.geom = geom; } @TableField(typeHandler = PgGeometryTypeHandler.class) private String geom; @TableField(exist=false) private String geomJson; }

4、数据入库

使用junit进行代码测试,将数据批量插入到数据库中。

Java和GDAL实现的GeoJSON数据读取与入库实践

在程序的控制台中可以看到以下的输出,表名在执行数据库的插入操作:

Java和GDAL实现的GeoJSON数据读取与入库实践

最后来数据库中是否有批量插入的地名信息,使用以下查询语句:

select * from biz_geographic_name;
Java和GDAL实现的GeoJSON数据读取与入库实践

使用navicat可以连接数据库,看到在数据库中已经成功的将地级市的地名数据插入到空间数据中。

四、总结

以上就是本文的主要内容,本文将重点讲解在Java中如何调用GDAL进行GeoJSON矢量数据处理,首先使用QGIS工具展示待处理的地名GeoJSON数据,然后介绍在PostGIS空间数据库中创建空间表,最后介绍基于Java语言调用GDAL将GeoJSON进行空间数据入库。文章行文仓促,定有不足支持,关于文章的任何不足之处,都欢迎各位朋友在评论区留言批评指正交流,不慎感谢。

#IT##程序员##经验分享##干货分享##计算机##互联网##涨知识#

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/110312.html

(0)
上一篇 1天前
下一篇 1天前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信