PostGIS可用于创建国家/地区的网格地图吗?

时间:2012-08-22 04:05:02

标签: postgresql gis latitude-longitude postgis

我正在尝试将一个区域的地图划分为1 km x 1 km方格网格,并最终计算并检索有多少点(给定它们的纬度和经度值)落入此地图的每个方格。可以在PostGIS中完成此操作,如果是,我该怎么做?

更新:Mike Toews在此处有详细解答:

https://gis.stackexchange.com/questions/16374/how-to-create-a-regular-polygon-grid-in-postgis

2 个答案:

答案 0 :(得分:1)

正如我的评论所述 make a regular grid。要为整个国家制造1公里的电网,这可能具有挑战性,因为地球不平坦,不能分成完美的1公里电网。

要制作1 km网格,您需要一个投影坐标系,长度单位为米。 WGS84 (EPSG:4326)无法做到这一点,因为它具有纬度/长度单位。要找到合适的投影系统,您需要找到“等面积”投影,例如Lambert azimuthal equal-area projection(LAEA)。例如,所有欧洲都可以使用ETRS-LAEA (EPSG:3035),尽管某些部分可能会有一些失真。或者如果在新西兰,New Zealand Transverse Mercator 2000。每个地区通常都有很好的投射使用。

要运行PostGIS查询,您需要使用ST_Transform(geom, 3035)将几何图形投影到网格上(例如,对于ETRS-LAEA)。

答案 1 :(得分:0)

我写了一个PostGIS函数来在另一层上生成十六进制网格。

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 $$;

输入参数必须设置为: _curs:几何字段名称和输入几何的表名称。 _table:输出表的名称。 _srid:输入(和输出)几何的地理投影代码。 _height:投影单元中六边形网格单元格的高度。

我在声明块中生成缩放的六边形几何体,然后遍历输入几何体。在循环中,我为x和y范围生成系列,并为每个输入几何生成一些系列。如果两个几何相交,六边形将被平移并插入临时表中。第二对系列生成替代偏移行。 最后,我按照几何图形对六边形网格单元进行分组,以删除重复数据。

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

enter image description here