一、前言

在实际 GIS 项目开发中,我们常常会遇到这样的需求:

  • 判断某个点是否在某个行政区内;

  • 计算两个多边形的交集面积;

  • 分析某个区域的占比,比如灌区面积占流域总面积的比例;

  • 做缓冲区分析(如某条河流 500 米范围内的耕地面积)。

Java 后端 中,有两种常见的实现方式:

  1. JTS (Java Topology Suite):纯 Java 的几何运算库;

  2. PostGIS:基于 PostgreSQL 的空间扩展,SQL 即可完成复杂分析。

本文将结合 Java + JTSPostGIS 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 的组合,可以让你快速解决实际问题。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐