SpringBoot整合GeoTools
1、GeoTools相关的依赖
<dependencies>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>28-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-swing</artifactId>
<version>28-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-epsg-hsql</artifactId>
<version>28-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.geotools.jdbc</groupId>
<artifactId>gt-jdbc-mysql</artifactId>
<version>28-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>28-SNAPSHOT</version>
</dependency>
<!-- 解析几何geometry对象用的-->
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.19.0</version>
</dependency>
</dependencies>
在pom文件中添加以下文字,防止geotools依赖导入失败
<repositories>
<repository>
<id>osgeo</id>
<name>OSGeo Release Repository</name>
<url>https://repo.osgeo.org/repository/release/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>osgeo-snapshot</id>
<name>OSGeo Snapshot Repository</name>
<url>https://repo.osgeo.org/repository/snapshot/</url>
<snapshots><enabled>true</enabled></snapshots>
<releases><enabled>false</enabled></releases>
</repository>
</repositories>
2、本文所用到的公共类及实体类
R
@Data
@NoArgsConstructor
public class R<T> {
private int code;
private String msg;
private T data;
public static R ok(){
R r = new R();
r.setCode(200);
r.setMsg("成功");
return r;
}
public static R error(){
R r = new R();
r.setCode(444);
r.setMsg("失败");
return r;
}
public R data(T data){
this.setData(data);
return this;
}
}
China
@Data
public class China {
private int fid;
private String theGeom;
private String sheng;
}
3、本文所用到的数据库表
china
4、WKT格式怎么转化为GeoJson格式
工具类
/**
* WKT 格式转化为 GeoJson
* @Param: 传入WKT形式的字符串
*/
public static String WktToGeojson(String wktPoint){
WKTReader reader = new WKTReader();
Geometry geometry = null;
try {
geometry = reader.read(wktPoint);
} catch (ParseException e) {
e.printStackTrace();
}
StringWriter writer = new StringWriter();
GeometryJSON g = new GeometryJSON();
try {
g.write(geometry, writer);
} catch (IOException e) {
e.printStackTrace();
}
String result = writer.toString();
return result;
}
测试:
// wkt转geoJson
@GetMapping("/WktToGeojson")
public R WktToGeojson(){
try {
String wktPoint = "POINT(11.11111 12.22222)";
String result = GeoToolsUtils.WktToGeojson(wktPoint);
return R.ok().data(result);
} catch (Exception e) {
System.out.println("转换异常!" + e.toString());
}
return R.error();
}
结果:
5、GeoJson格式怎么转化为WKT格式
工具类
/**
* GeoJson 格式转化为 WKT
* @Param: 传入GeoJson形式的字符串
*/
public static String GeojsonToWkt(String geoJson) {
GeometryJSON gjson = new GeometryJSON();
Reader reader = new StringReader(geoJson);
Geometry geometry = null;
try {
geometry = gjson.read(reader);
} catch (IOException e) {
e.printStackTrace();
}
String wkt = geometry.toText();
return wkt;
}
测试:
// geoJson转wkt
@GetMapping("/GeojsonToWkt")
public R GeojsonToWkt(){
String geoJson="{\n" +
" \"type\": \"MultiPolygon\",\n" +
" \"coordinates\":\n" +
" [ \n" +
" [\n" +
" [\n" +
" [109.2041015625,30.088107753367257],\n" +
" [115.02685546875,30.088107753367257],\n" +
" [115.02685546875,32.7872745269555],\n" +
" [109.2041015625,32.7872745269555],\n" +
" [109.2041015625,30.088107753367257]\n" +
" \n" +
" \n" +
" ]\n" +
" ],\n" +
" [\n" +
" [\n" +
" [112.9833984375,26.82407078047018],\n" +
" [116.69677734375,26.82407078047018],\n" +
" [116.69677734375,29.036960648558267],\n" +
" [112.9833984375,29.036960648558267],\n" +
" [112.9833984375,26.82407078047018]\n" +
" ]\n" +
" ]\n" +
" ]\n" +
"}";
String wkt = GeoToolsUtils.GeojsonToWkt(geoJson);
return R.ok().data(wkt);
}
结果:
6、怎么把一张表的数据写入shp文件中
工具类
/**
* 写shp文件
* @Param: 文件存放的路径和名字 格式:D:\\test\\locations.shp
* @Param: 需要构建的shp文件的属性表字段名,其中第一个参数为空间数据名,比如 list["the_geom","fid","name","number"]
* @Param: 需要存入属性表中的值,其中空间属性值为WKT格式,属性顺序与名称必须与第二个参数传入的顺序一致
* @Param: 传入的空间属性类型,比如:Point、LineString、Polygon等
*/
public static void WriteSHP(String path,List<String> list,List<?> dataList,Class<?> geometry) throws IOException, IllegalAccessException, ParseException {
//1.创建shape文件对象
File file =new File(path);
Map<String, Serializable> params = new HashMap<>();
//用于捕获参数需求的数据类
//URLP:url to the .shp file.
params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
//2.创建一个新的数据存储——对于一个还不存在的文件。
ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
//3.定义图形信息和属性信息
//SimpleFeatureTypeBuilder 构造简单特性类型的构造器
SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder();
//设置
//WGS84:一个二维地理坐标参考系统,使用WGS84数据
tBuilder.setCRS(DefaultGeographicCRS.WGS84);
tBuilder.setName("shapefile");
//构造属性表字段名
tBuilder.add(list.get(0), geometry);
for(int i=1;i<list.size();i++){
tBuilder.add(list.get(i),String.class);
}
//设置此数据存储的特征类型
ds.createSchema(tBuilder.buildFeatureType());
//设置编码
ds.setCharset(Charset.forName("GBK"));
//设置writer
//为给定的类型名称创建一个特性写入器
//1.typeName:特征类型
//2.transaction :事物,写入失败,回滚
//3.ShapefileDataStore::getTypeNames:
/*public String[] getTypeNames()
获取这个数据存储保存的类型名称数组。
ShapefileDataStore总是返回一个名称
*/
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(
ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
//从数据库中读取数据
SimpleFeature feature = null;
GeometryFactory geometryFactory = new GeometryFactory();
for(Object o:dataList){
feature= writer.next();
// 通过反射机制获取对象的属性值
Class<?> aClass = o.getClass();
Field[] fields = aClass.getDeclaredFields();
for(Field f:fields){
f.setAccessible(true);
// 获得属性值
String s=f.get(o).toString();
if(s.indexOf("POINT")==0||s.indexOf("MULTIPOINT")==0||s.indexOf("LINESTRING")==0
||s.indexOf("MULTILINESTRING")==0||s.indexOf("POLYGON")==0||s.indexOf("MULTIPOLYGON")==0){
WKTReader reader = new WKTReader(geometryFactory);
feature.setAttribute(list.get(0),reader.read(s));
}else{
// 设置属性名和属性值
feature.setAttribute(f.getName(), s);
}
}
}
//写入
writer.write();
//关闭
writer.close();
//释放资源
ds.dispose();
}
测试:
Controller
// 写shp文件
@PostMapping("/WriteSHP")
public R WriteSHP() throws IOException, ParseException, IllegalAccessException {
String path="D:\\test\\china\\china.shp";
ArrayList<String> arr = new ArrayList<>();
arr.add("the_geom");
arr.add("fid");
arr.add("sheng");
GeoToolsUtils.WriteSHP(path,arr, chinaService.getAll(), MultiPolygon.class);
return R.ok();
}
service:
List<China> getAll();
serviceImpl:
@Autowired
private ChinaMapper chinaMapper;
@Override
public List<China> getAll() {
return chinaMapper.getAll();
}
mapper:
int insert(China china);
mapper.xml:
<resultMap id="BaseChina" type="China">
<id column="fid" jdbcType="INTEGER" property="fid"/>
<result column="the_geom" jdbcType="OTHER" property="theGeom" />
<result column="sheng" jdbcType="OTHER" property="sheng" />
</resultMap>
<select id="getAll" resultMap="BaseChina">
select fid,ST_ASWKT(the_geom) AS the_geom,sheng from china
</select>
结果:
查看 D:\test\china 路径:
使用ArcMap查看china.shp:
查看china.shp的属性表:
7、怎么读取shp文件并把数据存入数据库表中
工具类
/**
* 读shp文件并把数据存入数据库
* @Param: 需要读取的shp文件的路径及名字
* @return
*/
public static FeatureCollection<SimpleFeatureType, SimpleFeature> ReadSHP(String path) throws Exception{
//构建shapefile数据存储的实例
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
//基于路径构建文件对象
File file = new File(path);
//构建一个已存在的shapfile数据源
//ShapefileDataStore:数据存储实现,允许从Shapefiles读取和写入
ShapefileDataStore ds = (ShapefileDataStore) dataStoreFactory.createDataStore(file.toURI().toURL());
//设置编码,防止中文读取乱码
ds.setCharset(Charset.forName("GBK"));
//getFeatureSource():ContentFeatureSource
//这个特性是由 FeatureCollection提供的操作完成的。单独的特征记忆实现由子类提供:
//SimpleFeatureSource特征资源明确地使用FeatureCollection【集合】,可迭代
SimpleFeatureSource featureSource = ds.getFeatureSource();
//getFeatures():以FeatureCollection的形式检索所有特性。
//一个用于处理FeatureCollection的实用工具类。提供一个获取FeatureCollection实例的机制
FeatureCollection<SimpleFeatureType, SimpleFeature> result=featureSource.getFeatures();
System.out.println("几何对象总共有:"+result.size());
return result;
}
测试: 这里的shp文件基于上面第6点所构造的shp文件,while循环中设置China属性值的顺序是按照shp文件属性表中的顺序来的
controller
// 读取shp文件并把数据存入mysql
@PostMapping("/ReadSHP")
public R ReadSHP() throws Exception {
//基于shapfile文件,进行读取
String path = "D:\\test\\china\\china.shp";
FeatureCollection<SimpleFeatureType, SimpleFeature> result = GeoToolsUtils.ReadSHP(path);
System.out.println("几何对象总共有:"+result.size());
//features():返回一个FeatureIterator迭代器
SimpleFeatureIterator it =(SimpleFeatureIterator) result.features();
while(it.hasNext()){
SimpleFeature feature = it.next();
//迭代属性【属性我们可以理解为一个几何对象的属性节点,也就是对一个几何图形的描述字段】
Iterator<Property> ip = feature.getProperties().iterator();
System.out.println("========================");
China china = new China();
Property property = ip.next();
china.setTheGeom(String.valueOf(property.getValue()));
property=ip.next();
china.setFid(Integer.parseInt((String) property.getValue()));
property=ip.next();
china.setSheng(String.valueOf(property.getValue()));
chinaService.insertWKT(china);
}
it.close();
return R.ok();
}
service:
int insertWKT(China china);
serviceImpl:
@Override
public int insertWKT(China china) {
return chinaMapper.insertWKT(china);
}
mapper:
int insertWKT(China china);
mapper.xml: 我这里数据库中空间字段the_geom的类型设置为longtext,是以WKT格式直接存入数据库
<insert id="insertWKT" parameterType="China">
insert into newchina (the_geom,sheng) values (#{theGeom},#{sheng})
</insert>
结果:
数据库中也有值:
8、一些常用的空间函数(mysql版)
ST_AsText(), ST_AsWKT() 从Geometry格式转换为WKT
ST_AsGeoJSON() 从Geometry格式转换为GeoJson
ST_GeomFromText(), ST_GeometryFromText() 从WKT格式返回Geometry
等等