I'm trying to work out how to create boundary boxes from sf point geometry data on every row in an sf object. I'm trying to use the 'bb' function from the tmaptools package, along with dplyr and rowwise(). However, the output I get is just the same bounday box values copied onto every row, rather than a specific boundary box calculated from the point data on each row.
Here is a snip of the data frame sf object:
df1<-structure(list(Altitude = c(65.658, 65.606, 65.562, 65.51, 65.479,
65.408, 65.342, 65.31, 65.242, 65.17, 65.122), Bearing = c(201.3042,
201.3042, 201.3042, 201.3042, 201.3042, 201.3042, 201.3042, 201.3042,
201.3042, 201.3042, 201.3042), TAI = c(0.7535967, 0.7225685,
0.7142722, 0.7686105, 0.760403, 0.7515627, 0.7905218, 0.6231222,
0.7246232, 0.6290409, 0.635797), lat_corrd = c(51.28648265, 51.28647067,
51.28646118, 51.28645183, 51.28644244, 51.28643067, 51.28642109,
51.28641164, 51.28639984, 51.2863905, 51.28638087), lon_corrd = c(0.866623929,
0.866616631, 0.866610968, 0.86660517, 0.866598889, 0.866591258,
0.866585183, 0.866579259, 0.866571906, 0.86656599, 0.866560288
), geometry = structure(list(structure(c(0.866623929, 51.28648265
), class = c("XY", "POINT", "sfg")), structure(c(0.866616631,
51.28647067), class = c("XY", "POINT", "sfg")), structure(c(0.866610968,
51.28646118), class = c("XY", "POINT", "sfg")), structure(c(0.86660517,
51.28645183), class = c("XY", "POINT", "sfg")), structure(c(0.866598889,
51.28644244), class = c("XY", "POINT", "sfg")), structure(c(0.866591258,
51.28643067), class = c("XY", "POINT", "sfg")), structure(c(0.866585183,
51.28642109), class = c("XY", "POINT", "sfg")), structure(c(0.866579259,
51.28641164), class = c("XY", "POINT", "sfg")), structure(c(0.866571906,
51.28639984), class = c("XY", "POINT", "sfg")), structure(c(0.86656599,
51.2863905), class = c("XY", "POINT", "sfg")), structure(c(0.866560288,
51.28638087), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT",
"sfc"), precision = 0, bbox = structure(c(xmin = 0.866560288,
ymin = 51.28638087, xmax = 0.866623929, ymax = 51.28648265), class = "bbox"), crs = structure(list(
input = "EPSG:4326", wkt = "GEOGCRS[\"WGS 84\",\n DATUM[\"World Geodetic System 1984\",\n ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n LENGTHUNIT[\"metre\",1]]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n CS[ellipsoidal,2],\n AXIS[\"geodetic latitude (Lat)\",north,\n ORDER[1],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n AXIS[\"geodetic longitude (Lon)\",east,\n ORDER[2],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n USAGE[\n SCOPE[\"Horizontal component of 3D system.\"],\n AREA[\"World.\"],\n BBOX[-90,-180,90,180]],\n ID[\"EPSG\",4326]]"), class = "crs"), n_empty = 0L)), row.names = 5000:5010, class = c("sf",
"data.frame"), sf_column = "geometry", agr = structure(c(Altitude = NA_integer_,
Bearing = NA_integer_, TAI = NA_integer_, lat_corrd = NA_integer_,
lon_corrd = NA_integer_), .Label = c("constant", "aggregate",
"identity"), class = "factor"))
str(df1)
#Classes ‘sf’ and 'data.frame': 11 obs. of 6 variables:
What I want to do is create a new boundary box from the sfc_point values in the 'geometry' column, for example:
require(tmaptools)
bb(df1, cx = st_coordinates(df1)[,1], cy = st_coordinates(df1)[,2], width = 0.000012, height = 0.000012, relative = FALSE)
# xmin ymin xmax ymax
# 0.8666179 51.2864767 0.8666299 51.2864887
Or more specifically, something that is like this:
bb(df1[i,], cx = st_coordinates(df1)[i,1], cy = st_coordinates(df1)[i,2], width = 0.000012, height = 0.000012, relative = FALSE)
I want the resulting xmin,ymin, xmax, ymax values calculated for each row as a new geometry called something like boundary_boxes added to the existing data frame.
I tried to do it using 'apply' but it didn't work at all, and seemed like the way that 'apply' passes the 'geometry' sf list-type values along wasn't correct for 'bb'. I then tried to use 'dplyr' and this worked better, but still not quite right:
df1 %>% rowwise() %>% mutate(boundary_boxes = list(bb(cx = st_coordinates(.)[,1], cy = st_coordinates(.)[,2], width = 0.000012, height = 0.000012, relative = FALSE)))
This almost works but just repeats the same values for each row in the new 'boundary_box' column rather than give a specific boundary box.
How do i get this to work, or is there a better way to do it? Many thanks
Once I have a bbox for each row of data, I then need to convert the bounding box to a spatial object. I've used 'bb_poly' to do this:
bb_poly('some boundary box data', steps = 1)