# gis-postgis-jts
**Repository Path**: optcode/gis-postgis-jts
## Basic Information
- **Project Name**: gis-postgis-jts
- **Description**: PostGIS + Postgresql + JTS + GeoJSON +Jackson 序列化反序列化
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 10
- **Created**: 2023-05-27
- **Last Updated**: 2023-05-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# gis-postgis-jts
# GEOJSON官网:[GEOJSON](https://geojson.org/)
#### 介绍
PostGIS + Postgresql + JTS + GeoJSON +Jackson 序列化反序列化
java中使用postgis操作地理位置数据简单说明了基本的postgis建模,还有其如何与java程序进行数据交互。 但postgis-jdbc中提供的java模型生态与通用行不好,在java生态中,还有一个专门进行几何运算的库[JTS](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flocationtech%2Fjts)。
JTS Topology Suite([JTS](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flocationtech%2Fjts))拓扑套件是开源Java软件库,它提供平面几何的对象模型以及一组基本几何功能。并且 [JTS](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flocationtech%2Fjts)符合Open GIS联盟发布的SQL简单功能规范(Simple Features Specification for SQL)。所以[JTS](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flocationtech%2Fjts) 不仅可以和postgis的数据进行交互,并且还可以在java层提供空间数据关系的运算。
下面会介绍下怎样在一个java项目中引入[JTS](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flocationtech%2Fjts)并与postgis中的数据进行交互
引入[JTS](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Flocationtech%2Fjts)
使用maven,直接引入`jts-core`即可
> ```
>
> org.locationtech.jts
> jts-core
> 1.18.2
>
> ```
其中核心是`org.locationtech.jts.geom.Geometry`类,可以看到其结构与postgis的数据类型是基本一致的

# JTS与GeoJSON 格式序列化反序列化
引入maven jar
```
com.gis.postgis
postgis-geojson-jts
1.0-SNAPSHOT
```
```java
package com.gis.postgis.jts;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gis.postgis.geojson.collection.FeatureCollection;
import com.gis.postgis.geojson.crs.Crs;
import com.gis.postgis.geojson.crs.CrsType;
import com.gis.postgis.jackson.JtsModule;
import com.gis.postgis.jts.bean.Feature;
import com.gis.postgis.jts.bean.Features;
import com.gis.postgis.jts.bean.GeomCollection;
import com.google.common.collect.Maps;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.PrecisionModel;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
/**
* 〈功能简述〉
* 〈〉
*
* @author Mr.QL
* @ClassName geojsonTest
* @Date 2022-03-05 13:22
* @Version 1.0
*/
public class geojsonTest {
private static ObjectMapper objectMapper = new ObjectMapper();
private static GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
private static WKTReader wktReader = new WKTReader(geometryFactory);
static {
objectMapper.registerModule(jtsModule());
}
public static JtsModule jtsModule() {
return new JtsModule(geometryFactory());
}
public static GeometryFactory geometryFactory() {
return new GeometryFactory(precisionModel(), 4326);
}
public static PrecisionModel precisionModel() {
return new PrecisionModel();
}
public static void main(String[] args) throws IOException, ParseException {
TestFeatureVO();
TestFeature();
TestFeatures();
TestGeomCollection();
}
private static void TestFeatureVO() throws JsonProcessingException, ParseException {
Geometry location = wktReader.read("POINT(2.2944313287734985 48.85826523681466)");
System.out.println("--------------泛型---------------------");
com.gis.postgis.geojson.collection.Feature geometryFeature = new com.gis.postgis.geojson.collection.Feature(location);
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(geometryFeature);
System.out.println(json);
com.gis.postgis.geojson.collection.Feature geometryFeature1 = objectMapper.readValue(json, new TypeReference>() {
});
System.out.println(geometryFeature1.toString());
}
public static void TestFeature() throws IOException, ParseException {
Geometry location = wktReader.read("POINT(2.2944313287734985 48.85826523681466)");
Feature fe = new Feature(1L, "Eiffel Tower", "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France", location);
String jsonx = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(fe);
System.out.println(jsonx);
Feature featurex = objectMapper.readValue(jsonx, Feature.class);
System.out.println(featurex.toString());
String jsonxx = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featurex);
System.out.println(jsonxx);
Crs crs = new Crs();
crs.setType(CrsType.link);
Map properties = Maps.newHashMap();
properties.put("href","http://example.com/crs/42");
properties.put("type", "proj4");
crs.setProperties(properties);
fe.setCrs(crs);
double[] bbox = new double[]{-180.0, -90.0, 180.0, 90.0};
fe.setBbox(bbox);
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(fe);
System.out.println(json);
Feature feature = objectMapper.readValue(json, Feature.class);
System.out.println(feature.toString());
String jsonvo = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(feature);
System.out.println(jsonvo);
Feature fe2 = new Feature(2L, "CHONGQING Tower", "CHONGQING CHINA", location);
Crs crs2 = new Crs();
Map properties2 = Maps.newHashMap();
properties2.put("name","urn:ogc:def:crs:OGC:1.3:CRS84");
crs2.setProperties(properties2);
fe2.setCrs(crs2);
fe2.setBbox(bbox);
String json2 = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(fe2);
System.out.println(json2);
Feature feature2 = objectMapper.readValue(json2, Feature.class);
System.out.println(feature2.toString());
String jsonvo2 = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(feature2);
System.out.println(jsonvo2);
}
public static void TestFeatures() throws IOException, ParseException {
Geometry location = wktReader.read("POINT(2.2944313287734985 48.85826523681466)");
Feature fe = new Feature(1L, "Eiffel Tower", "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France", location);
Crs crs = new Crs();
crs.setType(CrsType.link);
Map properties = Maps.newHashMap();
properties.put("href","http://example.com/crs/42");
properties.put("type", "proj4");
crs.setProperties(properties);
fe.setCrs(crs);
double[] bbox = new double[]{-180.0, -90.0, 180.0, 90.0};
fe.setBbox(bbox);
Feature fe2 = new Feature(2L, "CHONGQING Tower", "CHONGQING CHINA", location);
Crs crs2 = new Crs();
Map properties2 = Maps.newHashMap();
properties2.put("name","urn:ogc:def:crs:OGC:1.3:CRS84");
crs2.setProperties(properties2);
fe2.setCrs(crs2);
fe2.setBbox(bbox);
ArrayList features = new ArrayList<>();
features.add(fe);
features.add(fe2);
System.out.println("-------------继承------------------");
FeatureCollection featureCollection = new Features().build(features);
featureCollection.setBbox(bbox);
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCollection);
System.out.println(json);
FeatureCollection featureCol = objectMapper.readValue(json, Features.class);
String s = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCol);
System.out.println(s);
System.out.println("-------------泛型------------------");
FeatureCollection featureCollection2 = new FeatureCollection().build(features);
featureCollection2.setBbox(bbox);
String jsons = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCollection2);
System.out.println(jsons);
FeatureCollection featureCol2 = objectMapper.readValue(jsons, new TypeReference>() {
});
String jsonss = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCol2);
System.out.println(jsonss);
FeatureCollection featureCollection3 = new FeatureCollection();
String jsons3 = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCollection3);
System.out.println(jsons3);
FeatureCollection featureCol3 = objectMapper.readValue(jsons3, new TypeReference>() {
});
String jsons3s = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCol3);
System.out.println(jsons3s);
}
public static void TestGeomCollection() throws IOException, ParseException {
Geometry location = wktReader.read("POINT(2.2944313287734985 48.85826523681466)");
Geometry Line = wktReader.read("LineString (0 0, 1 1, 2 2,3 3)");
org.locationtech.jts.geom.LinearRing lr = new GeometryFactory().createLinearRing(new Coordinate[]{new Coordinate(0, 0), new Coordinate(0, 10), new Coordinate(10, 10), new Coordinate(10, 0), new Coordinate(0, 0)});
ArrayList geometries = new ArrayList<>();
geometries.add(location);
geometries.add(Line);
geometries.add(lr);
System.out.println("----------------继承-------------------");
com.gis.postgis.geojson.collection.GeometryCollection featureCollection = new GeomCollection().build(geometries);
String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCollection);
System.out.println(json);
GeomCollection featureCol = objectMapper.readValue(json, GeomCollection.class);
String s = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCol);
System.out.println(s);
System.out.println("-----------------集合------------------");
Geometry[] garray = new Geometry[]{location, Line};
GeometryCollection gc = geometryFactory.createGeometryCollection(garray);
String jsongc = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(gc);
System.out.println(jsongc);
GeometryCollection geometryCollection = objectMapper.readValue(jsongc, GeometryCollection.class);
String jsongcc = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(geometryCollection);
System.out.println(jsongcc);
System.out.println("----------------泛型-------------------");
com.gis.postgis.geojson.collection.GeometryCollection collection = new com.gis.postgis.geojson.collection.GeometryCollection().build(geometries);
String jsons = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(collection);
System.out.println(jsons);
com.gis.postgis.geojson.collection.GeometryCollection geometryGeometryCollection = objectMapper.readValue(json, new TypeReference>() {
});
String ss = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(geometryGeometryCollection);
System.out.println(ss);
}
}
运行结果:
--------------泛型---------------------
{
"type" : "Feature",
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
}
}
Feature{geom=POINT (2.2944313287734985 48.85826523681466)}
{
"type" : "Feature",
"id" : 1,
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "Eiffel Tower",
"description" : "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France"
}
}
Feature{id=1, name='Eiffel Tower', description='Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France', location=POINT (2.2944313287734985 48.85826523681466)}GeoJsonObject{crs=null, bbox=null}
{
"type" : "Feature",
"id" : 1,
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "Eiffel Tower",
"description" : "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France"
}
}
{
"type" : "Feature",
"id" : 1,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "Eiffel Tower",
"description" : "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France"
},
"crs" : {
"type" : "link",
"properties" : {
"href" : "http://example.com/crs/42",
"type" : "proj4"
}
}
}
Feature{id=1, name='Eiffel Tower', description='Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France', location=POINT (2.2944313287734985 48.85826523681466)}GeoJsonObject{crs=Crs{type='link', properties={href=http://example.com/crs/42, type=proj4}}, bbox=[-180.0, -90.0, 180.0, 90.0]}
{
"type" : "Feature",
"id" : 1,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "Eiffel Tower",
"description" : "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France"
},
"crs" : {
"type" : "link",
"properties" : {
"href" : "http://example.com/crs/42",
"type" : "proj4"
}
}
}
{
"type" : "Feature",
"id" : 2,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "CHONGQING Tower",
"description" : "CHONGQING CHINA"
},
"crs" : {
"type" : "name",
"properties" : {
"name" : "urn:ogc:def:crs:OGC:1.3:CRS84"
}
}
}
Feature{id=2, name='CHONGQING Tower', description='CHONGQING CHINA', location=POINT (2.2944313287734985 48.85826523681466)}GeoJsonObject{crs=Crs{type='name', properties={name=urn:ogc:def:crs:OGC:1.3:CRS84}}, bbox=[-180.0, -90.0, 180.0, 90.0]}
{
"type" : "Feature",
"id" : 2,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "CHONGQING Tower",
"description" : "CHONGQING CHINA"
},
"crs" : {
"type" : "name",
"properties" : {
"name" : "urn:ogc:def:crs:OGC:1.3:CRS84"
}
}
}
-------------继承------------------
{
"type" : "FeatureCollection",
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"features" : [ {
"type" : "Feature",
"id" : 1,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "Eiffel Tower",
"description" : "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France"
},
"crs" : {
"type" : "link",
"properties" : {
"href" : "http://example.com/crs/42",
"type" : "proj4"
}
}
}, {
"type" : "Feature",
"id" : 2,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "CHONGQING Tower",
"description" : "CHONGQING CHINA"
},
"crs" : {
"type" : "name",
"properties" : {
"name" : "urn:ogc:def:crs:OGC:1.3:CRS84"
}
}
} ]
}
{
"type" : "FeatureCollection",
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"features" : [ {
"type" : "Feature",
"id" : 1,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "Eiffel Tower",
"description" : "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France"
},
"crs" : {
"type" : "link",
"properties" : {
"href" : "http://example.com/crs/42",
"type" : "proj4"
}
}
}, {
"type" : "Feature",
"id" : 2,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "CHONGQING Tower",
"description" : "CHONGQING CHINA"
},
"crs" : {
"type" : "name",
"properties" : {
"name" : "urn:ogc:def:crs:OGC:1.3:CRS84"
}
}
} ]
}
-------------泛型------------------
{
"type" : "FeatureCollection",
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"features" : [ {
"type" : "Feature",
"id" : 1,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "Eiffel Tower",
"description" : "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France"
},
"crs" : {
"type" : "link",
"properties" : {
"href" : "http://example.com/crs/42",
"type" : "proj4"
}
}
}, {
"type" : "Feature",
"id" : 2,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "CHONGQING Tower",
"description" : "CHONGQING CHINA"
},
"crs" : {
"type" : "name",
"properties" : {
"name" : "urn:ogc:def:crs:OGC:1.3:CRS84"
}
}
} ]
}
{
"type" : "FeatureCollection",
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"features" : [ {
"type" : "Feature",
"id" : 1,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "Eiffel Tower",
"description" : "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France"
},
"crs" : {
"type" : "link",
"properties" : {
"href" : "http://example.com/crs/42",
"type" : "proj4"
}
}
}, {
"type" : "Feature",
"id" : 2,
"bbox" : [ -180.0, -90.0, 180.0, 90.0 ],
"geometry" : {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
},
"properties" : {
"name" : "CHONGQING Tower",
"description" : "CHONGQING CHINA"
},
"crs" : {
"type" : "name",
"properties" : {
"name" : "urn:ogc:def:crs:OGC:1.3:CRS84"
}
}
} ]
}
{
"type" : "FeatureCollection",
"features" : [ ]
}
{
"type" : "FeatureCollection",
"features" : [ ]
}
----------------继承-------------------
{
"type" : "GeometryCollection",
"geometries" : [ {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
}, {
"type" : "LineString",
"coordinates" : [ [ 0.0, 0.0 ], [ 1.0, 1.0 ], [ 2.0, 2.0 ], [ 3.0, 3.0 ] ]
}, {
"type" : "LinearRing",
"coordinates" : [ [ 0.0, 0.0 ], [ 0.0, 10.0 ], [ 10.0, 10.0 ], [ 10.0, 0.0 ], [ 0.0, 0.0 ] ]
} ]
}
{
"type" : "GeometryCollection",
"geometries" : [ {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
}, {
"type" : "LineString",
"coordinates" : [ [ 0.0, 0.0 ], [ 1.0, 1.0 ], [ 2.0, 2.0 ], [ 3.0, 3.0 ] ]
}, {
"type" : "LinearRing",
"coordinates" : [ [ 0.0, 0.0 ], [ 0.0, 10.0 ], [ 10.0, 10.0 ], [ 10.0, 0.0 ], [ 0.0, 0.0 ] ]
} ]
}
-----------------集合------------------
{
"type" : "GeometryCollection",
"geometries" : [ {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
}, {
"type" : "LineString",
"coordinates" : [ [ 0.0, 0.0 ], [ 1.0, 1.0 ], [ 2.0, 2.0 ], [ 3.0, 3.0 ] ]
} ]
}
{
"type" : "GeometryCollection",
"geometries" : [ {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
}, {
"type" : "LineString",
"coordinates" : [ [ 0.0, 0.0 ], [ 1.0, 1.0 ], [ 2.0, 2.0 ], [ 3.0, 3.0 ] ]
} ]
}
----------------泛型-------------------
{
"type" : "GeometryCollection",
"geometries" : [ {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
}, {
"type" : "LineString",
"coordinates" : [ [ 0.0, 0.0 ], [ 1.0, 1.0 ], [ 2.0, 2.0 ], [ 3.0, 3.0 ] ]
}, {
"type" : "LinearRing",
"coordinates" : [ [ 0.0, 0.0 ], [ 0.0, 10.0 ], [ 10.0, 10.0 ], [ 10.0, 0.0 ], [ 0.0, 0.0 ] ]
} ]
}
{
"type" : "GeometryCollection",
"geometries" : [ {
"type" : "Point",
"coordinates" : [ 2.2944313287734985, 48.85826523681466 ]
}, {
"type" : "LineString",
"coordinates" : [ [ 0.0, 0.0 ], [ 1.0, 1.0 ], [ 2.0, 2.0 ], [ 3.0, 3.0 ] ]
}, {
"type" : "LinearRing",
"coordinates" : [ [ 0.0, 0.0 ], [ 0.0, 10.0 ], [ 10.0, 10.0 ], [ 10.0, 0.0 ], [ 0.0, 0.0 ] ]
} ]
}
```
## 备注:GIS开发文档友情链接
[GIS麻辣香锅](https://gitee.com/good_money/gis-spicy-hot-pot)
[Jackson-datatype-jts](https://github.com/bedatadriven/jackson-datatype-jts)
[geojson-serializer](https://github.com/ancore/geojson-serializer)