Java 与 GIS 空间分析实战:JTS 与 PostGIS 双方案
一、前言
在实际 GIS 项目开发中,我们常常会遇到这样的需求:
-
判断某个点是否在某个行政区内;
-
计算两个多边形的交集面积;
-
分析某个区域的占比,比如灌区面积占流域总面积的比例;
-
做缓冲区分析(如某条河流 500 米范围内的耕地面积)。
在 Java 后端 中,有两种常见的实现方式:
-
JTS (Java Topology Suite):纯 Java 的几何运算库;
-
PostGIS:基于 PostgreSQL 的空间扩展,SQL 即可完成复杂分析。
本文将结合 Java + JTS 和 PostGIS SQL 两种方式,展示交集与占比的计算。
二、方案一:Java + JTS 实现交集与占比
引入依赖:
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.19.0</version>
</dependency>
代码示例(两个多边形交集与占比):
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKTReader;
public class GisIntersectDemo {
public static void main(String[] args) throws Exception {
WKTReader reader = new WKTReader();
// 多边形1 与 多边形2
Geometry poly1 = reader.read("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))");
Geometry poly2 = reader.read("POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))");
// 求交集
Geometry intersection = poly1.intersection(poly2);
// 计算面积
double area1 = poly1.getArea();
double area2 = poly2.getArea();
double interArea = intersection.getArea();
System.out.println("交集面积:" + interArea);
System.out.println("交集占多边形1比例:" + (interArea / area1 * 100) + "%");
System.out.println("交集占多边形2比例:" + (interArea / area2 * 100) + "%");
}
}
输出结果:
交集面积:25.0
交集占多边形1比例:25.0%
交集占多边形2比例:25.0%
适用场景:小规模计算、前后端交互时直接返回结果。
三、方案二:PostGIS SQL 实现交集与占比
当数据量比较大(比如存储了成千上万个地块、多边形),在 Java 里做计算会非常慢,这时候推荐用 PostGIS 直接在数据库层面完成空间分析。
1. 表结构示例
假设我们有两张表:
-- 区域表 A
CREATE TABLE region_a (
id serial primary key,
name varchar(50),
geom geometry(Polygon, 4326)
);
-- 区域表 B
CREATE TABLE region_b (
id serial primary key,
name varchar(50),
geom geometry(Polygon, 4326)
);
2. 计算交集面积
SELECT
a.name as region_a,
b.name as region_b,
ST_Area(ST_Intersection(a.geom, b.geom)) as inter_area
FROM region_a a, region_b b
WHERE ST_Intersects(a.geom, b.geom);
3. 计算交集占比
SELECT
a.name as region_a,
b.name as region_b,
ST_Area(ST_Intersection(a.geom, b.geom)) / ST_Area(a.geom) * 100 as ratio_a,
ST_Area(ST_Intersection(a.geom, b.geom)) / ST_Area(b.geom) * 100 as ratio_b
FROM region_a a, region_b b
WHERE ST_Intersects(a.geom, b.geom);
4. 判断点是否在多边形内
SELECT
p.id as point_id,
r.name as region_name
FROM points p
JOIN region_a r
ON ST_Contains(r.geom, p.geom);
5. 缓冲区分析
比如:统计一条河流 500 米缓冲区内的耕地面积:
SELECT
r.name,
ST_Area(ST_Intersection(ST_Buffer(river.geom, 500), farmland.geom)) as farmland_area
FROM river, farmland r;
适用场景:数据量大、需要高效批量计算时。
四、Java 调用 PostGIS
Java 后端调用 PostGIS 的 SQL 结果非常简单:
String sql = "SELECT ST_Area(ST_Intersection(a.geom, b.geom)) FROM region_a a, region_b b WHERE a.id=? AND b.id=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, 1);
ps.setInt(2, 2);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
double interArea = rs.getDouble(1);
System.out.println("交集面积:" + interArea);
}
五、实际业务案例
在灌区管理系统中:
-
需求:计算某个灌区与耕地的交集面积,得出耕地占灌区的比例。
-
实现:
-
灌区边界存在
irrigation_area表; -
耕地数据存在
farmland表; -
使用 PostGIS 一条 SQL 即可:
-
SELECT
i.name as irrigation_name,
f.name as farmland_name,
ST_Area(ST_Intersection(i.geom, f.geom)) / ST_Area(i.geom) * 100 as farmland_ratio
FROM irrigation_area i, farmland f
WHERE ST_Intersects(i.geom, f.geom);
输出结果即可直接返回给前端,结合 OpenLayers/Leaflet 做可视化。
六、总结
-
小规模计算 → 推荐用 Java + JTS,灵活、简单、无需数据库依赖;
-
大规模计算 → 推荐用 PostGIS,直接在数据库层面做空间分析,效率更高;
-
前端可视化 → 通过 GeoJSON 返回计算结果,OpenLayers/Leaflet/Mapbox 都能渲染。
空间分析在水利、环保、国土、城市规划等场景都有广泛应用,掌握 Java + GIS 的组合,可以让你快速解决实际问题。
更多推荐


所有评论(0)