-- -- Fill given extent with a rectangular coverage -- -- @param ext Extent to fill. Only rectangles with center point falling -- inside the extent (or at the lower or leftmost edge) will -- be emitted. The returned hexagons will have the same SRID -- as this extent. -- -- @param width With of each rectangle -- -- @param height Height of each rectangle -- -- @param origin Optional origin to allow for exact tiling. -- If omitted the origin will be 0,0. -- The parameter is checked for having the same SRID -- as the extent. -- -- CREATE OR REPLACE FUNCTION CDB_RectangleGrid(ext GEOMETRY, width FLOAT8, height FLOAT8, origin GEOMETRY DEFAULT NULL) RETURNS SETOF GEOMETRY AS $$ DECLARE h GEOMETRY; -- rectangle cell hstep FLOAT8; -- horizontal step vstep FLOAT8; -- vertical step hw FLOAT8; -- half width hh FLOAT8; -- half height vstart FLOAT8; hstart FLOAT8; hend FLOAT8; vend FLOAT8; xoff FLOAT8; yoff FLOAT8; xgrd FLOAT8; ygrd FLOAT8; x FLOAT8; y FLOAT8; srid INTEGER; BEGIN srid := ST_SRID(ext); xoff := 0; yoff := 0; IF origin IS NOT NULL THEN IF ST_SRID(origin) != srid THEN RAISE EXCEPTION 'SRID mismatch between extent (%) and origin (%)', srid, ST_SRID(origin); END IF; xoff := ST_X(origin); yoff := ST_Y(origin); END IF; --RAISE DEBUG 'X offset: %', xoff; --RAISE DEBUG 'Y offset: %', yoff; hw := width/2.0; hh := height/2.0; xgrd := hw; ygrd := hh; --RAISE DEBUG 'X grid size: %', xgrd; --RAISE DEBUG 'Y grid size: %', ygrd; hstep := width; vstep := height; -- Tweak horizontal start on hstep grid from origin hstart := xoff + ceil((ST_XMin(ext)-xoff)/hstep)*hstep; --RAISE DEBUG 'hstart: %', hstart; -- Tweak vertical start on vstep grid from origin vstart := yoff + ceil((ST_Ymin(ext)-yoff)/vstep)*vstep; --RAISE DEBUG 'vstart: %', vstart; hend := ST_XMax(ext); vend := ST_YMax(ext); --RAISE DEBUG 'hend: %', hend; --RAISE DEBUG 'vend: %', vend; x := hstart; WHILE x < hend LOOP -- over X y := vstart; h := ST_MakeEnvelope(x-hw, y-hh, x+hw, y+hh, srid); WHILE y < vend LOOP -- over Y RETURN NEXT h; h := ST_Translate(h, 0, vstep); y := yoff + round(((y + vstep)-yoff)/ygrd)*ygrd; -- round to grid END LOOP; x := xoff + round(((x + hstep)-xoff)/xgrd)*xgrd; -- round to grid END LOOP; RETURN; END $$ LANGUAGE 'plpgsql' IMMUTABLE;