用的比较多的网格有六边形网格、正方形网格、长方形网格。网格的生成方法有很多种,在这里做一个分类,按照实现方式分为:
- 前端实现
- 后端实现(java、python、C#)
- 数据库层实现
前端实现的方式可以使用turf进行网格生成rurf链接
后端实现方式目前只尝试过一种:使用geotools vector grid包 link
ReferencedEnvelope gridBounds =
new ReferencedEnvelope(110.0, 150.0, -45.0, -5.0, DefaultGeographicCRS.WGS84);
SimpleFeatureSource grid = Grids.createSquareGrid(gridBounds, 10.0);
最后一种就是借助postgis,通过数据库生成
首先是生成六边形网格 link
----------------------------------------------------------------------------------
-- INPUT
--
-- areakm2 : area of each hexagon in square km.
-- - note: hexagon size can be off slightly due to coordinate rounding in the calcs.
--
-- xmin, ymin : min coords of the grid extents.
--
-- xmax, ymax : max coords of the grid extents.
--
-- inputsrid : the coordinate system (SRID) of the input min/max coords.
--
-- workingsrid : the SRID used to process the polygons.
-- - SRID must be a projected coord sys (i.e. in metres) as the calcs require ints. Degrees are out.
-- - should be an equal area SRID such as Albers or Lambert Azimuthal (e.g. Australia = 3577, US = 2163).
-- - using Mercator will NOT return hexagons of equal area due to its distortions (don't try it in Greenland).
--
-- ouputsrid : the SRID of the output polygons.
--
-- NOTES
--
-- Hexagon height & width are rounded up & down to the nearest metre, hence the area may be off slightly.
-- This is due to the Postgres generate_series function which doesn't support floats.
--
-- Why are my areas wrong in QGIS, MapInfo, etc...?
-- Let's assume you created WGS84 lat/long hexagons, you may have noticed the areas differ by almost half in a desktop GIS
-- like QGIS or MapInfo Pro. This is due to the way those tools display geographic coordinate systems like WGS84 lat/long.
-- Running the following query in PostGIS will confirm the min & max sizes of your hexagons (in km2):
--
-- SELECT (SELECT (MIN(ST_Area(geom::geography, FALSE)) / 1000000.0)::numeric(10,3) From my_hex_grid) AS minarea,
-- (SELECT (MAX(ST_Area(geom::geography, FALSE)) / 1000000.0)::numeric(10,3) From my_hex_grid) AS maxarea;
--
--------------------------------------------------------------------------------------------------------------------------------
--DROP FUNCTION IF EXISTS hex_grid(areakm2 FLOAT, xmin FLOAT, ymin FLOAT, xmax FLOAT, ymax FLOAT, inputsrid INTEGER,
-- workingsrid INTEGER, ouputsrid INTEGER);
CREATE OR REPLACE FUNCTION hex_grid(areakm2 FLOAT, xmin FLOAT, ymin FLOAT, xmax FLOAT, ymax FLOAT, inputsrid INTEGER,
workingsrid INTEGER, ouputsrid INTEGER)
RETURNS SETOF geometry AS
$BODY$
DECLARE
minpnt GEOMETRY;
maxpnt GEOMETRY;
x1 INTEGER;
y1 INTEGER;
x2 INTEGER;
y2 INTEGER;
aream2 FLOAT;
qtrwidthfloat FLOAT;
qtrwidth INTEGER;
halfheight INTEGER;
BEGIN
-- Convert input coords to points in the working SRID
minpnt = ST_Transform(ST_SetSRID(ST_MakePoint(xmin, ymin), inputsrid), workingsrid);
maxpnt = ST_Transform(ST_SetSRID(ST_MakePoint(xmax, ymax), inputsrid), workingsrid);
-- Get grid extents in working SRID coords
x1 = ST_X(minpnt)::INTEGER;
y1 = ST_Y(minpnt)::INTEGER;
x2 = ST_X(maxpnt)::INTEGER;
y2 = ST_Y(maxpnt)::INTEGER;
-- Get height and width of hexagon - FLOOR and CEILING are used to get the hexagon size closer to the requested input area
aream2 := areakm2 * 1000000.0;
qtrwidthfloat := sqrt(aream2/(sqrt(3.0) * (3.0/2.0))) / 2.0;
qtrwidth := FLOOR(qtrwidthfloat);
halfheight := CEILING(qtrwidthfloat * sqrt(3.0));
-- Return the hexagons - done in pairs, with one offset from the other
RETURN QUERY (
SELECT ST_Transform(ST_SetSRID(ST_Translate(geom, x_series::FLOAT, y_series::FLOAT), workingsrid), ouputsrid) AS geom
FROM generate_series(x1, x2, (qtrwidth * 6)) AS x_series,
generate_series(y1, y2, (halfheight * 2)) AS y_series,
(
SELECT ST_GeomFromText(
format('POLYGON((0 0, %s %s, %s %s, %s %s, %s %s, %s %s, 0 0))',
qtrwidth, halfheight,
qtrwidth * 3, halfheight,
qtrwidth * 4, 0,
qtrwidth * 3, halfheight * -1,
qtrwidth, halfheight * -1
)
) AS geom
UNION
SELECT ST_Translate(
ST_GeomFromText(
format('POLYGON((0 0, %s %s, %s %s, %s %s, %s %s, %s %s, 0 0))',
qtrwidth, halfheight,
qtrwidth * 3, halfheight,
qtrwidth * 4, 0,
qtrwidth * 3, halfheight * -1,
qtrwidth, halfheight * -1
)
)
, qtrwidth * 3, halfheight) as geom
) AS two_hex);
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
CREATE TABLE us_hex_grid (
gid SERIAL NOT NULL PRIMARY KEY,
geom GEOMETRY('POLYGON', 4326, 2) NOT NULL
)
WITH (OIDS=FALSE);
INSERT INTO us_hex_grid (geom)
SELECT hex_grid(5, 119.95, 30.03, 120.43, 30.43, 4326, 3857, 4326);
生成正方形网格 link
raster ST_MakeEmptyRaster(raster rast);
raster ST_MakeEmptyRaster(integer width, integer height, float8 upperleftx, float8 upperlefty, float8 scalex, float8 scaley, float8 skewx, float8 skewy, integer srid=unknown);
raster ST_MakeEmptyRaster(integer width, integer height, float8 upperleftx, float8 upperlefty, float8 pixelsize);
--width 宽上多少个格子
-- height 高上多少格子
-- upperlefty 左上角坐标y
-- upperleftx 坐上角坐标x
-- pixelsize 距离
-- scalex x方向距离
-- scaley y方向距离
-- skewx x方向上旋转
-- skewy y方向上旋转
SELECT
(
ST_PixelAsPolygons (
ST_AddBand (
ST_SetSRID(ST_MakeEmptyRaster( 50, 30, 119.96, 30.40, 0.01),4326),
'8BSI' :: TEXT,
1,
0
),
1,
FALSE
)).geom
生成矩形
-- scalex x方向距离
-- scaley y方向距离
-- scalex scaley带正负号,和象限一致
SELECT
(
ST_PixelAsPolygons (
ST_AddBand (
ST_MakeEmptyRaster( 50, 50, 119.96, 30.40, 0.01, 0.01, 0, 0, 4326),
'8BSI' :: TEXT,
1,
0
),
1,
FALSE
)).geom
SELECT
(
ST_PixelAsPolygons (
ST_AddBand (
ST_MakeEmptyRaster( 50, 50, 119.96, 30.40, 0.01, -0.02, 0, 0, 4326),
'8BSI' :: TEXT,
1,
0
),
1,
FALSE
)).geom