PostGIS Geometry是什么
PostGIS Geometry是PostGIS提供的一种空间数据类型,用于在PostgreSQL数据库中存储和处理二维、三维以及带测量值的几何对象。
PostGIS是PostgreSQL的空间数据库扩展。
通过Geometry,可以在数据库中直接保存:
- Point
- LineString
- Polygon
- MultiPoint
- MultiLineString
- MultiPolygon
- GeometryCollection
例如:
POINT (116.397 39.908)
可以作为一个Geometry存储在PostgreSQL表中。
简单来说:
PostGIS Geometry就是PostgreSQL数据库中用于存储和计算GIS空间几何数据的数据类型。
PostGIS是什么
PostGIS是PostgreSQL的空间数据库扩展。
普通PostgreSQL主要处理:
整数
字符串
日期
JSON
数组
安装PostGIS以后,可以增加:
Geometry
Geography
Raster
空间索引
空间函数
空间分析
可以理解为:
PostgreSQL
↓
PostGIS
↓
空间数据库能力
例如:
SELECT *
FROM roads
WHERE ST_Length(geom) > 1000;
数据库就可以直接进行空间计算。
Geometry的基本结构
PostGIS中的Geometry不仅包含几何类型和坐标,还包含空间参考信息。
可以简单理解为:
Geometry
├── Geometry Type
│ ├── Point
│ ├── LineString
│ └── Polygon
│
├── Coordinates
│ ├── X
│ ├── Y
│ ├── Z
│ └── M
│
└── SRID
└── Coordinate Reference System
例如:
POINT (116.397 39.908)
对应:
Geometry Type = Point
X = 116.397
Y = 39.908
如果设置:
SRID = 4326
就可以明确这些坐标使用的是EPSG:4326坐标参考系统。
创建Geometry字段
PostGIS中最常见的Geometry字段定义方式:
CREATE TABLE cities (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
geom geometry(Point, 4326)
);
这里:
geom geometry(Point, 4326)
表示:
geom
↓
Geometry字段
Point
↓
只允许Point类型
4326
↓
SRID为EPSG:4326
因此数据库可以对空间数据进行一定程度的类型约束。
插入Point
可以使用WKT创建Geometry:
INSERT INTO cities (name, geom)
VALUES (
'北京',
ST_GeomFromText('POINT (116.397 39.908)', 4326)
);
其中:
ST_GeomFromText()
用于将WKT转换为PostGIS Geometry。
结构:
WKT
↓
ST_GeomFromText
↓
Geometry
↓
PostGIS
查询Geometry
例如:
SELECT name, geom
FROM cities;
查询结果中的:
geom
就是PostGIS Geometry对象。
如果希望转换成WKT:
SELECT ST_AsText(geom)
FROM cities;
结果:
POINT(116.397 39.908)
因此:
Geometry
↓
ST_AsText()
↓
WKT
Geometry常见类型
PostGIS支持常见的OGC空间几何类型。
主要包括:
Point
MultiPoint
LineString
MultiLineString
Polygon
MultiPolygon
GeometryCollection
可以理解为:
Geometry
├── Point
├── MultiPoint
├── LineString
├── MultiLineString
├── Polygon
├── MultiPolygon
└── GeometryCollection
Point
Point表示一个空间位置。
例如:
'POINT (116.397 39.908)'
可以表示:
- 城市
- POI
- 医院
- 学校
- 设备
- 传感器
- 摄像头
数据库定义:
CREATE TABLE devices (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
geom geometry(Point, 4326)
);
LineString
LineString表示一条有顺序的线。
例如:
LINESTRING (
116.397 39.908,
116.405 39.915,
116.412 39.920
)
常用于:
- 道路
- 河流
- 铁路
- 管线
- GPS轨迹
数据库定义:
CREATE TABLE roads (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
geom geometry(LineString, 4326)
);
Polygon
Polygon表示一个封闭区域。
例如:
POLYGON ((
116.390 39.900,
116.400 39.900,
116.400 39.910,
116.390 39.910,
116.390 39.900
))
常用于:
- 行政区
- 地块
- 建筑物
- 公园
- 土地利用区域
数据库定义:
CREATE TABLE parcels (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
geom geometry(Polygon, 4326)
);
MultiPoint
MultiPoint用于存储多个独立Point。
例如:
MULTIPOINT (
(116.397 39.908),
(116.405 39.915),
(116.412 39.920)
)
适合:
- 采样点
- 多个监测点
- 一组设施
- 空间事件
MultiLineString
MultiLineString表示多个独立LineString。
例如:
MULTILINESTRING (
(
116.397 39.908,
116.405 39.915
),
(
116.420 39.920,
116.430 39.925
)
)
可以表示:
- 多段道路
- 多段河流
- 多段管线
- 铁路网络
MultiPolygon
MultiPolygon表示多个Polygon组成的Geometry。
例如:
MULTIPOLYGON (
(
(
116.390 39.900,
116.400 39.900,
116.400 39.910,
116.390 39.910,
116.390 39.900
)
),
(
(
116.420 39.920,
116.430 39.920,
116.430 39.930,
116.420 39.930,
116.420 39.920
)
)
)
适合:
- 群岛
- 多个不连续区域
- 多块土地
- 多个行政区域
GeometryCollection
GeometryCollection可以包含不同类型的Geometry。
例如:
GEOMETRYCOLLECTION (
POINT (116.397 39.908),
LINESTRING (
116.397 39.908,
116.405 39.915
)
)
其中可以同时包含:
Point
LineString
Polygon
因此:
GeometryCollection
├── Point
├── LineString
└── Polygon
不过实际数据库设计中,通常优先使用明确的Geometry类型。
SRID是什么
SRID用于表示Geometry使用的空间参考系统。
例如:
SRID = 4326
表示:
EPSG:4326
常见:
4326
3857
例如:
geometry(Point, 4326)
表示:
Point
+
EPSG:4326
Geometry和SRID的关系
仅仅看到:
POINT (116.397 39.908)
无法完全确定坐标的空间含义。
还需要知道:
SRID
因此:
Coordinates
+
SRID
=
完整空间参考信息
例如:
POINT (116.397 39.908)
SRID 4326
可以理解为:
X = 116.397
Y = 39.908
CRS = EPSG:4326
设置SRID
可以使用:
ST_SetSRID()
例如:
SELECT ST_SetSRID(
ST_GeomFromText('POINT (116.397 39.908)'),
4326
);
这里需要特别注意:
ST_SetSRID主要是给Geometry设置或修改SRID标识,并不会把坐标值从一个坐标系转换到另一个坐标系。
如果需要真正转换坐标,应使用:
ST_Transform()
Geometry坐标转换
例如将EPSG:4326转换为EPSG:3857:
SELECT ST_Transform(
geom,
3857
)
FROM cities;
关系:
EPSG:4326
↓
ST_Transform
↓
EPSG:3857
所以:
ST_SetSRID
↓
设置坐标参考标识
ST_Transform
↓
真正进行坐标转换
这是PostGIS中非常重要的区别。
Geometry的Z坐标
PostGIS Geometry可以支持三维坐标。
例如:
POINT Z (116.397 39.908 50)
其中:
X = 116.397
Y = 39.908
Z = 50
Z可以表示:
- 高程
- 建筑高度
- 三维空间位置
- 地形高度
数据库字段可以定义为:
geometry(PointZ, 4326)
Geometry的M值
Geometry还可以支持M值。
例如:
POINT M (116.397 39.908 100)
M通常用于表示:
- 里程
- 测量值
- 时间
- 路径上的距离
也可以使用:
X Y Z M
表示四维坐标结构。
Geometry与WKT
WKT是Geometry的一种文本表示方式。
例如:
POINT (116.397 39.908)
PostGIS可以通过:
ST_GeomFromText()
将WKT转换为Geometry。
例如:
SELECT ST_GeomFromText(
'POINT (116.397 39.908)',
4326
);
反过来:
SELECT ST_AsText(geom)
FROM cities;
得到:
POINT(116.397 39.908)
因此:
WKT
↕
Geometry
Geometry与WKB
WKB是Geometry的二进制表示方式。
PostGIS可以使用:
ST_AsBinary()
将Geometry转换为WKB。
例如:
SELECT ST_AsBinary(geom)
FROM cities;
反向可以使用:
ST_GeomFromWKB()
因此:
WKT
↓
文本表示
WKB
↓
二进制表示
Geometry
↓
数据库空间对象
Geometry与GeoJSON
PostGIS可以直接将Geometry转换为GeoJSON。
使用:
ST_AsGeoJSON()
例如:
SELECT ST_AsGeoJSON(geom)
FROM cities;
结果类似:
{
"type": "Point",
"coordinates": [116.397, 39.908]
}
反过来,也可以使用:
ST_GeomFromGeoJSON()
将GeoJSON Geometry转换为PostGIS Geometry。
因此:
GeoJSON
↓
ST_GeomFromGeoJSON
↓
PostGIS Geometry
Geometry与Feature
PostGIS中的Geometry通常只负责空间部分。
例如:
Geometry
↓
POINT (116.397 39.908)
属性信息可以单独存储:
name = 北京
type = city
population = ...
数据库表:
cities
├── id
├── name
├── type
└── geom
其中:
geom
↓
Geometry
name/type
↓
Attributes
因此可以理解为:
Feature
=
Attributes
+
Geometry
Geometry计算长度
对于LineString,可以使用:
ST_Length()
例如:
SELECT ST_Length(geom)
FROM roads;
返回Geometry长度。
需要注意:
长度的单位取决于Geometry所在的坐标参考系统。
如果使用经纬度坐标:
EPSG:4326
Geometry中的数值单位是度,并不适合直接当作米使用。
因此实际距离计算时,需要合理选择投影坐标系,或者根据需求使用Geography。
Geometry计算面积
Polygon可以使用:
ST_Area()
例如:
SELECT ST_Area(geom)
FROM parcels;
返回Polygon面积。
同样需要注意:
面积单位
取决于坐标系单位。
例如投影坐标使用米:
面积 = 平方米
而经纬度坐标直接计算并不能简单理解为平方米。
Geometry计算距离
PostGIS可以使用:
ST_Distance()
计算两个Geometry之间的距离。
例如:
SELECT ST_Distance(
a.geom,
b.geom
)
FROM cities a, cities b;
如果Geometry使用适合距离计算的投影坐标系,返回值通常可以直接理解为对应的线性单位。
对于经纬度距离,需要注意坐标系和单位问题。
Geometry缓冲区
PostGIS可以使用:
ST_Buffer()
创建缓冲区。
例如:
SELECT ST_Buffer(
geom,
100
)
FROM roads;
可以理解为:
道路
↓
100单位缓冲
↓
Polygon
常用于:
- 道路影响范围
- 服务区分析
- 查询附近设施
- 环境影响范围
- 安全距离分析
Geometry相交
可以使用:
ST_Intersects()
判断两个Geometry是否相交。
例如:
SELECT ST_Intersects(
a.geom,
b.geom
)
FROM roads a, parcels b;
返回:
true
或者:
false
这类函数是空间查询的基础。
Geometry包含关系
可以使用:
ST_Contains()
判断一个Geometry是否包含另一个Geometry。
例如:
行政区
↓
包含
↓
城市
SQL:
SELECT ST_Contains(
district.geom,
city.geom
)
FROM districts district, cities city;
Geometry空间关系
PostGIS提供大量空间关系判断函数。
例如:
ST_Intersects
ST_Contains
ST_Within
ST_Covers
ST_Touches
ST_Overlaps
ST_Crosses
ST_Disjoint
可以用于判断:
相交
包含
位于内部
覆盖
接触
重叠
穿过
分离
因此:
Geometry
↓
Spatial Relationship
↓
空间分析
Geometry空间集合运算
PostGIS还可以对Geometry进行空间集合运算。
常见函数:
ST_Intersection
ST_Union
ST_Difference
ST_SymDifference
例如:
Polygon A
+
Polygon B
↓
Intersection
↓
交集区域
使用:
SELECT ST_Intersection(a.geom, b.geom)
FROM a, b;
Geometry空间索引
PostGIS最重要的能力之一就是空间索引。
常见索引:
CREATE INDEX idx_cities_geom
ON cities
USING GIST (geom);
这里使用:
GiST
索引支持空间数据的高效查询。
例如:
SELECT *
FROM cities
WHERE ST_DWithin(
geom,
ST_SetSRID(
ST_Point(116.397, 39.908),
4326
),
1000
);
在正确的索引和查询条件下,可以大幅减少需要检查的空间对象数量。
为什么需要空间索引
假设数据库中有:
100万个Point
如果查询:
找距离某位置最近的对象。
没有空间索引时可能需要:
100万
↓
逐个计算
有空间索引后:
100万
↓
空间索引筛选
↓
少量候选对象
↓
精确计算
因此:
Geometry
+
GiST空间索引
=
高效空间查询
Geometry字段约束
可以限制Geometry类型:
geometry(Point, 4326)
也可以使用更宽泛的:
geometry(Geometry, 4326)
例如:
geometry(Point, 4326)
表示:
只允许Point
SRID必须为4326
而:
geometry(Geometry, 4326)
表示:
允许不同Geometry类型
SRID为4326
在数据库设计中,应根据实际业务选择合适的约束。
Geometry有效性
PostGIS可以检查Geometry是否有效。
例如:
SELECT ST_IsValid(geom)
FROM parcels;
结果:
true
或者:
false
常见无效Geometry包括:
Polygon自相交
环结构错误
重复节点
异常坐标
对于Polygon等复杂Geometry,有效性非常重要。
修复无效Geometry
PostGIS提供:
ST_MakeValid()
可以尝试修复无效Geometry。
例如:
SELECT ST_MakeValid(geom)
FROM parcels
WHERE NOT ST_IsValid(geom);
处理空间数据导入时,经常需要:
导入
↓
检查有效性
↓
修复
↓
空间分析
Geometry与Geography
PostGIS中除了Geometry,还有:
Geography
两者都可以存储空间数据,但使用场景不同。
简单理解:
Geometry
↓
平面坐标模型
而:
Geography
↓
地球椭球体上的地理坐标模型
例如:
geometry(Point, 4326)
与:
geography(Point, 4326)
虽然都可以表示经纬度Point,但空间计算的模型不同。
Geometry与Geography区别
| 特性 | Geometry | Geography |
|---|---|---|
| 模型 | 平面 | 地球曲面/椭球体 |
| 常用坐标 | 投影坐标或经纬度 | 经纬度 |
| 空间计算 | 平面计算 | 地理测量计算 |
| 性能 | 通常较快 | 某些计算更复杂 |
| 适合 | GIS空间分析 | 地球范围距离、面积 |
因此不能简单认为:
Geometry一定比Geography好。
应该根据业务需求选择。
Geometry常见SQL
创建空间字段:
CREATE TABLE places (
id SERIAL PRIMARY KEY,
name TEXT,
geom geometry(Point, 4326)
);
创建Point:
ST_SetSRID(
ST_Point(116.397, 39.908),
4326
)
WKT转Geometry:
ST_GeomFromText(
'POINT (116.397 39.908)',
4326
)
Geometry转WKT:
ST_AsText(geom)
Geometry转GeoJSON:
ST_AsGeoJSON(geom)
坐标转换:
ST_Transform(geom, 3857)
判断相交:
ST_Intersects(a.geom, b.geom)
计算距离:
ST_Distance(a.geom, b.geom)
创建缓冲:
ST_Buffer(geom, 100)
检查有效性:
ST_IsValid(geom)
一个完整示例
创建城市表:
CREATE TABLE cities (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
geom geometry(Point, 4326)
);
插入数据:
INSERT INTO cities (name, geom)
VALUES (
'北京',
ST_SetSRID(
ST_Point(116.397, 39.908),
4326
)
);
查询:
SELECT
id,
name,
ST_AsText(geom) AS wkt
FROM cities;
结果:
id | name | wkt
---+------+----------------------
1 | 北京 | POINT(116.397 39.908)
转换坐标:
SELECT
ST_AsText(
ST_Transform(geom, 3857)
)
FROM cities;
转换为GeoJSON:
SELECT ST_AsGeoJSON(geom)
FROM cities;
这样就形成了一个完整的:
创建
↓
存储
↓
查询
↓
转换
↓
输出
Geometry数据流程
一个典型PostGIS数据处理流程:
Shapefile
GeoJSON
WKT
CSV
↓
导入PostGIS
↓
Geometry
↓
设置SRID
↓
建立空间索引
↓
空间查询
↓
空间分析
↓
GeoJSON / WKT / WKB
↓
WebGIS
例如WebGIS应用:
PostGIS
↓
空间查询
↓
GeoJSON
↓
OpenLayers / Leaflet
↓
地图
Geometry与WebGIS
PostGIS经常作为WebGIS后端数据库。
典型架构:
WebGIS
↓
OpenLayers / Leaflet
↓
API
↓
后端服务
↓
PostGIS
↓
Geometry
数据库负责:
数据存储
空间查询
空间分析
空间索引
前端负责:
地图显示
交互
样式
编辑
Geometry知识结构
可以这样理解PostGIS Geometry:
PostGIS
↓
Geometry
├── Type
│ ├── Point
│ ├── LineString
│ ├── Polygon
│ ├── MultiPoint
│ ├── MultiLineString
│ ├── MultiPolygon
│ └── GeometryCollection
│
├── Coordinates
│ ├── X
│ ├── Y
│ ├── Z
│ └── M
│
├── SRID
│ └── CRS
│
├── Input / Output
│ ├── WKT
│ ├── WKB
│ └── GeoJSON
│
├── Spatial Functions
│ ├── Distance
│ ├── Buffer
│ ├── Intersection
│ └── Spatial Relations
│
└── Spatial Index
└── GiST
Geometry、WKT、WKB、GeoJSON的关系
可以简单理解为:
Geometry
│
┌───────────┼───────────┐
↓ ↓ ↓
WKT WKB GeoJSON
文本表示 二进制表示 JSON表示
例如同一个Point:
WKT:
POINT (116.397 39.908)
GeoJSON:
{
"type": "Point",
"coordinates": [116.397, 39.908]
}
它们表达的是同一个空间对象,只是表示形式不同。
总结
PostGIS Geometry是PostgreSQL空间数据库中最核心的数据类型之一。
它用于存储:
Point
LineString
Polygon
MultiPoint
MultiLineString
MultiPolygon
GeometryCollection
Geometry不仅包含:
Coordinates
还可以关联:
SRID
Z
M
并且PostGIS可以直接对Geometry进行:
距离计算
长度计算
面积计算
缓冲区分析
相交判断
包含判断
空间集合运算
有效性检查
坐标转换
同时可以通过GiST等空间索引提高空间查询效率。
可以记住:
PostGIS Geometry = PostgreSQL中的空间几何数据 + SRID + 空间计算能力 + 空间索引。
相关工具
使用 IYATools 在线工具快速处理 GIS 数据