Can PostGIS be used to create a grid map of a country?

一世执手 提交于 2019-12-03 16:28:00
Mike T

As mentioned in my comment make a regular grid. To make a 1 km grid for a whole country, this could be challenging, since the earth is not flat and cannot be divided into perfect 1 km grids.

To make a 1 km grid, you need a projected coordinate system, with length units of metres. WGS84 (EPSG:4326) cannot do this, since it has units of degrees lat/long. To find a suitable projection system, you need to find an "equal area" projection, such as Lambert azimuthal equal-area projection (LAEA). For example all of Europe could use ETRS-LAEA (EPSG:3035), although there might be some distortion in some parts. Or if in New Zealand, New Zealand Transverse Mercator 2000. Each region generally has a good projection to use.

To run your PostGIS query, you would need to project geometries onto the grid using ST_Transform(geom, 3035) (e.g., for ETRS-LAEA).

I wrote a PostGIS function to generate hex grids on top of another layer.

DO $$
DECLARE
  _curs   CURSOR FOR SELECT geom3857 FROM nrw;
  _table  TEXT    := 'nrw_hx_10k';
  _srid   INTEGER := 3857;
  _height NUMERIC := 10000;
  _width  NUMERIC := _height * 0.866;
  _geom   GEOMETRY;
  _hx     TEXT    := 'POLYGON((' || 0 || ' ' || 0 || ',' || (_width * 0.5) || ' ' || (_height * 0.25) || ',' ||
                 (_width * 0.5) || ' '
                 || (_height * 0.75) || ',' || 0 || ' ' || _height || ',' || (-1 * (_width * 0.5)) || ' ' ||
                 (_height * 0.75) || ',' ||
                 (-1 * (_width * 0.5)) || ' ' || (_height * 0.25) || ',' || 0 || ' ' || 0 || '))';
  _hx_g   GEOMETRY := ST_SetSRID(_hx::GEOMETRY, _srid);

BEGIN
  CREATE TEMP TABLE hx_tmp (geom GEOMETRY(POLYGON));

  OPEN _curs;
  LOOP
    FETCH
    _curs INTO _geom;
    EXIT WHEN NOT FOUND;

    INSERT INTO hx_tmp
      SELECT
        ST_Translate(_hx_g, x_series, y_series)::GEOMETRY(POLYGON) geom
      FROM
        generate_series(
          (st_xmin(_geom) / _width)::INTEGER * _width - _width,
          (st_xmax(_geom) / _width)::INTEGER * _width + _width,
          _width) x_series,
        generate_series(
          (st_ymin(_geom) / (_height * 1.5))::INTEGER * (_height * 1.5) - _height,
          (st_ymax(_geom) / (_height * 1.5))::INTEGER * (_height * 1.5) + _height,
          _height * 1.5) y_series
      WHERE
        ST_Intersects(ST_Translate(_hx_g, x_series, y_series)::GEOMETRY(POLYGON), _geom);

    INSERT INTO hx_tmp
      SELECT ST_Translate(_hx_g, x_series, y_series)::GEOMETRY(POLYGON) geom
      FROM
        generate_series(
          (st_xmin(_geom) / _width)::INTEGER * _width - (_width * 1.5),
          (st_xmax(_geom) / _width)::INTEGER * _width + _width,
          _width) x_series,
        generate_series(
          (st_ymin(_geom) / (_height * 1.5))::INTEGER * (_height * 1.5) - (_height * 1.75),
          (st_ymax(_geom) / (_height * 1.5))::INTEGER * (_height * 1.5) + _height,
          _height * 1.5) y_series
      WHERE
        ST_Intersects(ST_Translate(_hx_g, x_series, y_series)::GEOMETRY(POLYGON), _geom);

  END LOOP;
  CLOSE _curs;

  CREATE INDEX sidx_hx_tmp_geom ON hx_tmp USING GIST (geom);
  EXECUTE 'DROP TABLE IF EXISTS '|| _table;
  EXECUTE 'CREATE TABLE '|| _table ||' (geom GEOMETRY(POLYGON, '|| _srid ||'))';
  EXECUTE 'INSERT INTO '|| _table ||' SELECT * FROM hx_tmp GROUP BY geom';
  EXECUTE 'CREATE INDEX sidx_'|| _table ||'_geom ON '|| _table ||' USING GIST (geom)';
  DROP TABLE IF EXISTS hx_tmp;
END $$;

Input parameters must be set for: _curs: The geometry field name and the table name of input geometries. _table: The name of the output table. _srid: The geographic projection code of the input (and output) geometries. _height: The height of a hexgon grid cell in projection units.

I generate a scaled hexagon geometry in the declare block and then loop through the input geometries. In the loop, I generate series for the x and y extent plus some for each input geometry. The hexagon is translated and inserted into a temporary table if the two geometries intersect. A second pair of series is generated alternative offset rows. Finally I group the hexagon grid cells by their geometries to remove duplicates.

There is a more detailed description and some background on medium.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!