Reputation: 25
I have a latitude and longitude that I am treating as a center point. I want to draw a 100 nautical mile circle around that point. Since 1 degree of lat/lon is approximately 60 nautical miles, I would expect the difference between the max and min latitude (as well as the max and min longitudes) to be a little over 3 degrees.
When I create a 185,200 meter (1,852 m per nautical mile) buffer around the lat/lon (28.5, 86.5), the bounding box of the resulting polygon has a min/max lon of 84.85 and 88.16, respectively. This makes sense. However, the resulting min/max lat is 0.24 and 56.78. That makes no sense at all to me and I have no idea what's going on.
This is the code I've tried
test_point = st_as_sf(data.frame(Lat=28.5,Lon=86.5),coords=c("Lat","Lon"),remove=FALSE)
st_crs(test_point) = 4326
buff1 = st_buffer(test_point,100*1852)
buff2 = st_transform(buff1,crs=4326)
When I look at the min/max x,y coordinates for buff1, the differences in the min/max between each dimension is about 200 nautical miles; this makes sense since that's twice the radius I've specified. But things go haywire when I go back to WSG84
buff1
#Simple feature collection with 1 feature and 2 fields
#Geometry type: POLYGON
#Dimension: XY
#Bounding box: xmin: 667639.2 ymin: 9981165 xmax: 1038039 ymax: 10351570
#CRS: +proj=utm +zone=16
# Lat Lon geometry
#1 28.5 86.5 POLYGON ((1038039 10166365,...
#(Note that (10351570-9981165)/1852 is about 200 and (1038039-667639.2)/1852 is about 200 too.
buff2
#Simple feature collection with 1 feature and 2 fields
#Geometry type: POLYGON
#Dimension: XY
#Bounding box: xmin: 0.2407929 ymin: 84.84537 xmax: 56.77518 ymax: 88.15623
#Geodetic CRS: WGS 84
# Lat Lon geometry
#1 28.5 86.5 POLYGON ((20.35843 84.95627...
# Note how far apart the xmin and xmax are.
Upvotes: 0
Views: 219
Reputation: 17399
That test_point
ends up near North Pole, at 86N, and up there circle with 100 nmile radius can indeed cover 57+ degrees longitude (black points are bbox corners):
library(sf)
library(ggplot2)
library(mapview)
test_point = st_as_sf(data.frame(Lat=28.5,Lon=86.5),coords=c("Lat","Lon"),remove=FALSE)
st_crs(test_point) = 4326
buff1 = st_buffer(test_point,100*1852)
buff1
#> Simple feature collection with 1 feature and 2 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: 0 ymin: 84.81199 xmax: 57.29792 ymax: 88.18218
#> Geodetic CRS: WGS 84
#> Lat Lon geometry
#> 1 28.5 86.5 POLYGON ((2.271324 86.23322...
# let's visualize
bbox_points <-
st_bbox(buff1) %>%
st_as_sfc() %>%
st_cast("POINT") %>%
st_as_sf() %>%
mutate(coord = lapply(x, \(x) paste0(round(x[1],3),"\n", round(x[2],3))))
ggplot() +
geom_sf(data = buff1, alpha = .2) +
geom_sf(data = test_point, color = "red") +
geom_sf(data = bbox_points) +
geom_sf_text( data = bbox_points, aes(label = coord)) +
coord_sf(crs = 6115) +
theme_bw() +
theme(panel.border = element_blank())
Assuming from UTM Zone16 CRS in your code output, you might have meant 86.5 West not 86.5 East for longitude, so after fixing coordinate order (coords
parameter in st_as_sf()
uses x,y order) and changing sign for longitude, we now end up with this:
test_point_2 <- st_as_sf(
data.frame(Lat = 28.5,
Lon = -86.5),
coords = c("Lon","Lat"),
remove = FALSE,
crs = "WGS84")
buff_2 <- st_buffer(test_point_2, units::set_units(100, nmile))
buff_2
#> Simple feature collection with 1 feature and 2 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -88.4016 ymin: 26.81976 xmax: -84.5851 ymax: 30.18484
#> Geodetic CRS: WGS 84
#> Lat Lon geometry
#> 1 28.5 -86.5 POLYGON ((-84.94013 29.4612...
# visualize
buff_extend <- st_buffer(test_point_2, units::set_units(500, nmile))
viewExtent(buff_extend) +
mapview(buff_2) +
mapview(test_point_2)
x-range of the bounding box is much closer to your expected result now, though 1 degree of lat being ~60 nautical miles only works at the equator.
Created on 2023-03-11 with reprex v2.0.2
Upvotes: 1