I am trying to make an equal dimension square grid over a given area using R. I want my grid to be 1km x 1km square. I see examples like this which illustrate equal lat/long grids:
Creating a regular polygon grid over a spatial extent, rotated by a given angle
but that's not even size. It seems like I should be able to take the st_make_grid
function and create this, but I can't grok how to make the grid 1km x 1km.
https://r-spatial.github.io/sf/reference/st_make_grid.html
I'd like, for example, to start at (37,-89.2) and end at (36.2,-86.8) and create an evenly spaced grid that's 1km x 1km. How would I do that with R?
Note: the tricky part it seems, is keeping the grid really 1km x 1km over a very large area. I can keep the grid equal dimensions in decimal degrees, but that's not equal distance on the ground.
I've been able to do this with PostGIS, thanks to a crafty answer here. In PostGIS I've created a function:
CREATE OR REPLACE FUNCTION public.makegrid_2d (
bound_polygon public.geometry,
width_step integer,
height_step integer
)
RETURNS public.geometry AS
$body$
DECLARE
Xmin DOUBLE PRECISION;
Xmax DOUBLE PRECISION;
Ymax DOUBLE PRECISION;
X DOUBLE PRECISION;
Y DOUBLE PRECISION;
NextX DOUBLE PRECISION;
NextY DOUBLE PRECISION;
CPoint public.geometry;
sectors public.geometry[];
i INTEGER;
SRID INTEGER;
BEGIN
Xmin := ST_XMin(bound_polygon);
Xmax := ST_XMax(bound_polygon);
Ymax := ST_YMax(bound_polygon);
SRID := ST_SRID(bound_polygon);
Y := ST_YMin(bound_polygon); --current sector's corner coordinate
i := -1;
<<yloop>>
LOOP
IF (Y > Ymax) THEN
EXIT;
END IF;
X := Xmin;
<<xloop>>
LOOP
IF (X > Xmax) THEN
EXIT;
END IF;
CPoint := ST_SetSRID(ST_MakePoint(X, Y), SRID);
NextX := ST_X(ST_Project(CPoint, $2, radians(90))::geometry);
NextY := ST_Y(ST_Project(CPoint, $3, radians(0))::geometry);
i := i + 1;
sectors[i] := ST_MakeEnvelope(X, Y, NextX, NextY, SRID);
X := NextX;
END LOOP xloop;
CPoint := ST_SetSRID(ST_MakePoint(X, Y), SRID);
NextY := ST_Y(ST_Project(CPoint, $3, radians(0))::geometry);
Y := NextY;
END LOOP yloop;
RETURN ST_Collect(sectors);
END;
$body$
LANGUAGE 'plpgsql';
Then I can call it and pass it a polygon:
SELECT (
ST_Dump(
makegrid_2d(
ST_GeomFromText(
'Polygon((-75 42, -75 40, -73 40, -73 42, -75 42))',
4326
) ,
1000, -- width step in meters
1000 -- height step in meters
)
)
) .geom AS cell into test_grid_cell;
But as you can see, even with PostGIS this is hardly a canned routine. With a bit of effort I think I could port this to sf
, but I'm not overly excited about it...