postgis生成网格

用的比较多的网格有六边形网格、正方形网格、长方形网格。网格的生成方法有很多种,在这里做一个分类,按照实现方式分为:

  • 前端实现
  • 后端实现(java、python、C#)
  • 数据库层实现
前端实现的方式可以使用turf进行网格生成rurf链接
image.png
后端实现方式目前只尝试过一种:使用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);
image.png
最后一种就是借助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);
image.png
生成正方形网格 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
        
        
image.png
生成矩形
-- 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
image.png
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
image.png

你可能感兴趣的:(postgis生成网格)