PostGIS 3.1+
PostGIS 3.1 引入了非常易于使用的网格生成器,即ST_SquareGrid 和ST_HexagonGrid。将这些函数与表中的数据一起使用的一种简单方法是使用LATERAL 来执行它,例如大小为 0.1° 的单元格::
样本数据
考虑以下polygon:
在给定几何体上创建一个单元格大小为 0.1° 的方格
SELECT grid.* FROM isle_of_man imn,
LATERAL ST_SquareGrid(0.1,imn.geom) grid;
如果您只想要与几何体相交的单元格,只需在 WHERE 子句中调用函数 ST_Intersects:
SELECT grid.* FROM isle_of_man imn,
LATERAL ST_SquareGrid(0.1,imn.geom) grid
WHERE ST_Intersects(imn.geom,grid.geom);
同样的原则也适用于ST_HexagonGrid:
SELECT grid.* FROM isle_of_man imn,
LATERAL ST_HexagonGrid(0.1,imn.geom) grid;
SELECT grid.* FROM isle_of_man imn,
LATERAL ST_HexagonGrid(0.1,imn.geom) grid
WHERE ST_Intersects(imn.geom,grid.geom);
旧的 PostGIS 版本
受post 的启发,我开始编写一个函数来做到这一点——它仍然需要一些调整,但它肯定会给你一个方向。以下函数创建一个网格,其中包含给定大小的单元格,覆盖给定几何图形的区域:
CREATE OR REPLACE FUNCTION public.generate_grid(_size numeric,_geom geometry)
RETURNS TABLE(gid bigint, cell geometry) LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
_bbox box2d := ST_Extent(_geom);
_ncol int := ceil(abs(ST_Xmax(_bbox)-ST_Xmin(_bbox))/_size);
_nrow int := ceil(abs(ST_Ymax(_bbox)-ST_Ymin(_bbox))/_size);
_srid int DEFAULT 4326;
BEGIN
IF ST_SRID(_geom) <> 0 THEN
IF EXISTS (SELECT 1 FROM spatial_ref_sys crs
WHERE crs.srid = ST_SRID(_geom) AND NOT crs.proj4text LIKE '+proj=longlat%') THEN
RAISE EXCEPTION 'Only lon/lat spatial reference systems are supported in this function.';
ELSE
_srid := ST_SRID($2);
END IF;
END IF;
RETURN QUERY
SELECT ROW_NUMBER() OVER (), geom FROM (
SELECT
ST_SetSRID(
(ST_PixelAsPolygons(
ST_AddBand(
ST_MakeEmptyRaster(_ncol, _nrow, ST_XMin(_bbox), ST_YMax(_bbox),_size),
'1BB'::text, 1, 0),
1, false)).geom,_srid)) j(geom);
END;
$BODY$;
注意:此功能依赖于扩展PostGIS Raster。
SELECT cell FROM isle_of_man,
LATERAL generate_grid(0.1,geom);
...如果您只对与多边形重叠的单元格感兴趣,请在查询中添加ST_Intersects:
SELECT cell FROM isle_of_man,
LATERAL generate_grid(0.1,geom)
WHERE ST_Intersects(geom,cell)
其他选择
Mike 的fishnet function 基本相同,但需要手动提供行数和列数,以及左下角的坐标对:
SELECT ST_SetSRID(cells.geom,4326)
FROM ST_CreateFishnet(4, 6, 0.1, 0.1,-4.8411, 54.0364) AS cells;
您可以使用此makegrid_2d function 在使用多边形的区域上创建网格,例如一个包含 5000 米大小的单元格的网格:
CREATE TABLE grid_isle_of_man AS
SELECT 'S'||ROW_NUMBER() OVER () AS grid_id, (g).geom
FROM (
SELECT ST_Dump(makegrid_2d(geom,5000))
FROM isle_of_man) j(g)
JOIN isle_of_man ON ST_Intersects((g).geom,geom);
同样的逻辑适用于这个hexagrid function。它在给定的 BBOX 上创建具有固定大小单元的六边形网格。您可以手动提供 BBOX(函数的第二个参数)或从给定的多边形中提取它。例如,要创建一个与多边形范围相匹配的六边形网格,并将其存储在带有所需标签的新表中 - 单元格大小为 0.1°:
CREATE TABLE hexgrid_isle_of_man AS
WITH j (hex_rec) AS (
SELECT generate_hexagons(0.1,ST_Extent(geom))
FROM isle_of_man
)
SELECT 'S'||ROW_NUMBER() OVER () AS grid_id,(hex_rec).hexagon FROM j
JOIN isle_of_man t ON ST_Intersects(t.geom,(hex_rec).hexagon);
进一步阅读: