Skip to content
Snippets Groups Projects
pg_procedures_minet.sql 2.16 KiB
Newer Older
CREATE OR REPLACE FUNCTION lon2tile(lon DOUBLE PRECISION, zoom INTEGER)
  RETURNS INTEGER AS
$BODY$
    SELECT FLOOR( (lon + 180) / 360 * (1 << zoom) )::INTEGER;
$BODY$
  LANGUAGE SQL IMMUTABLE;

CREATE OR REPLACE FUNCTION lat2tile(lat double precision, zoom integer)
  RETURNS integer AS
$BODY$
    SELECT floor( (1.0 - ln(tan(radians(lat)) + 1.0 / cos(radians(lat))) / pi()) / 2.0 * (1 << zoom) )::integer;
$BODY$
  LANGUAGE sql IMMUTABLE;

CREATE OR REPLACE FUNCTION tile2lat(y integer, zoom integer)
  RETURNS double precision AS
$BODY$
DECLARE
 n float;
 sinh float;
 E float = 2.7182818284;
BEGIN
    n = pi() - (2.0 * pi() * y) / power(2.0, zoom);
    sinh = (1 - power(E, -2*n)) / (2 * power(E, -n));
    return degrees(atan(sinh));
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE;


CREATE OR REPLACE FUNCTION tile2lon(x integer, zoom integer)
  RETURNS double precision AS
$BODY$
 SELECT CAST(x * 1.0 / (1 << zoom) * 360.0 - 180.0 AS double precision);
$BODY$
  LANGUAGE sql IMMUTABLE;

CREATE OR REPLACE FUNCTION getTileEnvelope(geom geometry, zoom integer)
  RETURNS geometry AS
$BODY$
DECLARE
  _result geometry;
BEGIN
    IF ST_SRID(geom) != 4326 THEN
      geom = ST_Transform(geom, 4326);
    END IF;

    SELECT ST_MakeEnvelope(bbox.xmin, bbox.ymin, bbox.xmax, bbox.ymax, 4326) INTO _result FROM (
      SELECT tile2lon(tile.x, zoom) AS xmin, tile2lat(y, zoom) AS ymin, tile2lon(tile.x + 1, zoom) AS xmax, tile2lat(y + 1, zoom) AS ymax FROM (
        SELECT lon2tile(ST_X(geom), zoom) AS x, lat2tile(ST_Y(geom), zoom) AS y
      ) AS tile
    ) AS bbox;

    RETURN _result;
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE;

CREATE OR REPLACE FUNCTION getTileEnvelope(geog geography, zoom integer)
  RETURNS geography AS
$BODY$
DECLARE
  _result geography;
BEGIN
    SELECT ST_MakeEnvelope(bbox.xmin, bbox.ymin, bbox.xmax, bbox.ymax, 4326)::geography INTO _result FROM (
      SELECT tile2lon(tile.x, zoom) AS xmin, tile2lat(y, zoom) AS ymin, tile2lon(tile.x + 1, zoom) AS xmax, tile2lat(y + 1, zoom) AS ymax FROM (
        SELECT lon2tile(ST_X(geog::geometry), zoom) AS x, lat2tile(ST_Y(geog::geometry), zoom) AS y
      ) AS tile
    ) AS bbox;

    RETURN _result;
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE;