Purpose: Why use it
PostgreSQL
?
- Because sometimes we need to store
空间数据
, such as: store a多边形
to data.- In PostGis
geometry
,geography
: Basic spatial data type, used to express spatial elements such as points, lines, and planes. The specific types cover the simple object model of OGC
Description: PostGIS is a spatial database extension of the PostgreSQL object-relational database. It adds support for geographic objects, allowing location queries to be run in SQL.
Features:
- PostGIS is an open source spatial database that adds the ability to store and manage spatial data to the object-relational database PostgreSQL. The spatial database stores and operates spatial objects just like any other object in the database.
- It is an extension plug-in for PostgreSQL that implements the functions of the GIS layer on top of PostgreSQL's core (storage, retrieval, transaction, etc.) layer. It cannot run independently of PostgreSQL.
Common nouns:
WKT
(Well-known text) is a text markup language developed by the Open Geospatial Consortium OGC (Open GIS Consortium). It is used to represent vector geometric objects, spatial reference systems, and conversions between spatial reference systems.
POINT(1 2)
- Common descriptions:
Point
points,LineString
lines,Polygon
polygons... > -WKB
(well-known binary) is the binary representation of WKT, which solves the problem of redundancy in WKT expression and facilitates the transmission and storage of the same information in the database > - > - pg"01020000800200000097E5880801845C404D064F3AF4AE36400000000000000000290A915F01845C40DC90B1A051AE36400000000000000000"
library Mediumgeometry
type field, the default storage iswkb
GeoJson
:{[“type": “Point", “coordinates”: [30, 10]}
Common installations:
Official website download address:
https://www.enterprisedb.com/downloads/postgres-postgresql-downloads
Extension plug-in, spatial data processing postgis installation
https://www.postgresql.org/ftp/postgis/
http://download.osgeo.org/postgis/windows/pg10/
docker installation
version: "3.1"
services:
postgresql:
image: postgres:12-alpine
container_name: postgresql
environment:
POSTGRES_DB: postgres
POSTGRES_USER: "root"
POSTGRES_PASSWORD: "root"
ports:
- 5432:5432
volumes:
- ./data:/var/lib/postgresql/data
Common functions
-- 创建扩展函数
CREATE EXTENSION postgis;
-- 读取wkt字符串为geometry
ST_GeomFromText(ST_GeometryFromText)
-- 转换为wkt
ST_AsText
-- 转换为geojson
ST_AsGeoJSON
conversion function
-- 坐标系转换
-- WGS84坐标系:地球坐标系,国际通用坐标系
-- GCJ02坐标系:火星坐标系,WGS84坐标系加密后的坐标系;Google国内地图、高德、QQ地图 使用
-- BD09坐标系: 百度坐标系,GCJ02坐标系加密后的坐标系
-- CGCS坐标系:国家2000大地坐标系
-- WGS84转GCJ02
select ST_AsText(geoc_wgs84togcj02(geom)) from md_geom_space
-- GCJ02转WGS84
select geoc_gcj02towgs84(geom) from md_geom_space
-- WGS84转BD09
select geoc_wgs84tobd09(geom) from md_geom_space
-- BD09转WGS84
select geoc_bd09towgs84(geom) from md_geom_space
-- CGCS2000转GCJ02
select geoc_cgcs2000togcj02(geom) from md_geom_space
-- GCJ02转CGCS2000
select geoc_gcj02tocgcs2000(geom) from md_geom_space
-- CGCS2000转BD09
select geoc_cgcs2000tobd09(geom) from md_geom_space
-- BD09转CGCS2000
select geoc_bd09tocgcs2000(geom) from md_geom_space
-- GCJ02转BD09
select geoc_gcj02tobd09(geom) from md_geom_space
-- BD09转GCJ02
select geoc_bd09togcj02(geom) from md_geom_space
code integration
pom
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.8</version>
</dependency>
<!-- GeoTools -->
<dependency>
<groupId>org.geolatte</groupId>
<artifactId>geolatte-geom</artifactId>
<version>1.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.geolatte/geolatte-geojson -->
<dependency>
<groupId>org.geolatte</groupId>
<artifactId>geolatte-geojson</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>net.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>28-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>28-SNAPSHOT</version>
</dependency>
<!-- 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>
mybatisplus custom type processing
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.postgis.Geometry;
import org.postgis.PGgeometry;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@MappedTypes({
String.class})
public class MyGeometryTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
PGgeometry pGgeometry = new PGgeometry(parameter);
Geometry geometry = pGgeometry.getGeometry();
//坐标系
geometry.setSrid(4326);
ps.setObject(i, pGgeometry);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
PGgeometry pGgeometry = new PGgeometry(rs.getString(columnName));
return pGgeometry.getValue().replace("SRID=4326;","");
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
PGgeometry pGgeometry = new PGgeometry(rs.getString(columnIndex));
return pGgeometry.toString();
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
PGgeometry pGgeometry = new PGgeometry(cs.getString(columnIndex));
return pGgeometry.toString();
}
}
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.typeHandler.MyGeometryTypeHandler;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* xxx
*
* @author heyonghao
* @date 2023/7/17
*/
@TableName(autoResultMap = true)
@ApiModel(value = "电子围栏")
@Accessors(chain = true)
@Data
public class GeomSpace implements Serializable {
@ApiModelProperty(value = "主键")
private Long id;
//对应数据库 geometry 类型
@ApiModelProperty(value = "围栏geo参数- 返回wkt")
@TableField(typeHandler = MyGeometryTypeHandler.class)
private String geom;
@ApiModelProperty(value = "电子围栏名称")
private String title;
@ApiModelProperty(value = "其它组成参数 eg: 圆 半径 {\\\"radius\\\":0.00030345730927194836,\\\"radiusTrue\\\":29.068128024579657}")
private String other;
}
Add new spatial type data
@ApiModel(value = "围栏点位参数")
@Accessors(chain = true)
@Data
public class GeoJsonVo implements Serializable {
@ApiModelProperty(value = "类型: POINT、MULTIPOINT、LINESTRING、MULTILINESTRING、POLYGON、MULTIPOLYGON")
private String type;
@ApiModelProperty(value = "点位 eg: [ [\"106.29384466232433\",\"31.2648657606391\"] ]")
private List<List<String>> coordinates;
public String getGeomStr(){
String coordinate="SRID=4326;%s(%s)";
String collect = this.coordinates.stream().map(s -> s.stream().map(String::valueOf).collect(Collectors.joining(" ")))
.collect(Collectors.joining(","));
coordinate=String.format(coordinate,this.getType(),collect);
return coordinate;
}
}
@ApiModel(value = "围栏新增VO")
@Data
public class MdGeomSpaceSaveVo implements Serializable {
@ApiModelProperty(value = "围栏信息")
private GeomSpace mdGeomSpace;
@ApiModelProperty(value = "围栏点位信息")
private GeoJsonVo geoJsonVo;
}
@ApiOperation(value = "添加围栏")
@PostMapping("/save")
public R<Boolean> save(@RequestBody MdGeomSpaceSaveVo geomSpaceSaveVo){
GeoJsonVo geoJsonVo = geomSpaceSaveVo.getGeoJsonVo();
String geomStr = geoJsonVo.getGeomStr();
GeomSpace mdGeomSpace = geomSpaceSaveVo.getMdGeomSpace();
mdGeomSpace.setGeom(geomStr);
mdGeomSpace.setId(IdUtil.getSnowflakeNextId());
boolean save = mdGeomSpaceService.save(mdGeomSpace);
return R.ok(save);
}
electric fence:
- Use a virtual fence to enclose a virtual geographic boundary;
- Circle a circular range or polygonal range on the map; bind characteristic rules, such as
超速
,滞留
,偏离
,聚集
etc., to generate corresponding alarms- Pass in spatial data and store it in the PG library
surface:
-- ----------------------------
DROP TABLE IF EXISTS "public"."geom_space";
CREATE TABLE "public"."geom_space" (
"id" int8 NOT NULL DEFAULT nextval('testgeomobj_id_seq'::regclass),
"geom" geometry(GEOMETRY) NOT NULL,
"title" varchar(255) COLLATE "pg_catalog"."default",
"other" varchar(255) COLLATE "pg_catalog"."default"
)
;
COMMENT ON COLUMN "public"."geom_space"."id" IS '主键';
COMMENT ON COLUMN "public"."geom_space"."geom" IS '围栏geo参数';
COMMENT ON COLUMN "public"."geom_space"."title" IS '电子围栏名称';
COMMENT ON COLUMN "public"."geom_space"."other" IS '其它组成参数 eg: 圆 半径';
-- ----------------------------
-- Primary Key structure for table geom_space
-- ----------------------------
ALTER TABLE "public"."geom_space" ADD CONSTRAINT "md_geom_space_pkey" PRIMARY KEY ("id");
-- ----------------------------
DROP TABLE IF EXISTS "public"."geom_space_rule";
CREATE TABLE "public"."geom_space_rule" (
"id" int8 NOT NULL,
"name" varchar(255) COLLATE "pg_catalog"."default",
"type" int2,
"rule" varchar(255) COLLATE "pg_catalog"."default"
)
;
COMMENT ON COLUMN "public"."geom_space_rule"."id" IS '主键';
COMMENT ON COLUMN "public"."geom_space_rule"."name" IS '规则名称';
COMMENT ON COLUMN "public"."geom_space_rule"."type" IS '规则类型 1-超速 2-聚焦 3-规矩偏离 4-滞留';
COMMENT ON COLUMN "public"."geom_space_rule"."rule" IS '规则JSON';
-- ----------------------------
-- Records of geom_space_rule
-- ----------------------------
INSERT INTO "public"."geom_space_rule" VALUES (1685206843057606656, '超速', 1, '{"speed":60,"duration":10}');
-- ----------------------------
-- Primary Key structure for table geom_space_rule
-- ----------------------------
ALTER TABLE "public"."geom_space_rule" ADD CONSTRAINT "geom_space_rule_pkey" PRIMARY KEY ("id");
-- ----------------------------
DROP TABLE IF EXISTS "public"."geom_space_bind";
CREATE TABLE "public"."geom_space_bind" (
"id" int8 NOT NULL,
"space_id" int8,
"rule_id" int8
)
;
COMMENT ON COLUMN "public"."geom_space_bind"."id" IS '主键';
COMMENT ON COLUMN "public"."geom_space_bind"."space_id" IS '围栏id';
COMMENT ON COLUMN "public"."geom_space_bind"."rule_id" IS '规则id';
-- ----------------------------
-- Records of geom_space_bind
-- ----------------------------
INSERT INTO "public"."geom_space_bind" VALUES (1685206981247340544, 1685205995128717312, 1685206843057606656);
-- ----------------------------
-- Primary Key structure for table geom_space_bind
-- ----------------------------
ALTER TABLE "public"."geom_space_bind" ADD CONSTRAINT "geom_space_bind_pkey" PRIMARY KEY ("id");