Преобразовать результат `st_bbox()` в другие CRS

#r #transform #geospatial #sf

#r #преобразовать #геопространственный #sf

Вопрос:

Есть ли простой способ преобразовать ограничение простого объекта ( sf object) в другой CRS?

Результат функции st_bbox() относится к классу bbox . Невозможно использовать st_transform() для преобразования его в другой CRS.

Я использую вычисляемую ограничивающую рамку на основе EPSG: 28992 :

 sf::st_bbox(xmin = 187470, xmax =194587, 
            ymin = 409753, ymax = 412715,  
            crs = st_crs(28992))
  

Теперь я хочу преобразовать это поле в EPSG:4326

Комментарии:

1. Обратите внимание, что прямоугольник в одной системе координат может не быть прямоугольником в другой. Если вы действительно хотите спроецировать полную форму прямоугольника, а не только четыре угла, тогда вам нужно создать прямоугольный многоугольник с большим количеством вершин по сторонам и спроецировать это .

Ответ №1:

Существует st_as_sfc метод для bbox объектов, поэтому мы можем преобразовать bbox вот так:

 library(sf)

bb = sf::st_bbox(c(xmin = 187470, xmax =194587, 
                   ymin = 409753, ymax = 412715),  
                 crs = st_crs(28992))

bb_ll = st_bbox(
  st_transform(
    st_as_sfc(bb), 
    4326
  )
)

# or pipey
library(magrittr)

bb_ll = bb %>%
  st_as_sfc() %>%
  st_transform(crs = 4326) %>%
  st_bbox()

bb_ll

    xmin      ymin      xmax      ymax 
5.856639 51.675176  5.959866 51.702257
  

Ответ №2:

Один из способов сделать это — создать промежуточное значение sfc_MULTIPOINT , преобразовать его в 4326, затем извлечь ограничивающую рамку из этого объекта:

 pts <- st_multipoint(rbind(c(187470, 409753), c(194587, 412715))) %>% st_sfc(crs = st_crs(28992))
pts <- pts %>% st_transform(crs = 4326)

st_bbox(pts)

     xmin      ymin      xmax      ymax 
 5.856639 51.675634  5.959866 51.701799 
  

Ответ №3:

Как отметил @spacedman, прямоугольник в одной системе координат может не быть прямоугольником в другой. Некоторые системы координат намного более изогнуты, чем другие!

Чтобы более безопасно преобразовать ограничивающую рамку, вы могли бы добавить вершины, используя st_make_grid (n = что угодно).

 # pipey code to show the steps clearly
library(sf)
library(dplyr)
bb_better_reproj = bb_orig %>% 
                      st_make_grid(n=10) %>%  #this also makes it into a polygon
                      st_transform(crs = 4326) %>% 
                      st_bbox()
  

Это не на 100% безопасно, но лучше, чем просто преобразовать прямоугольный многоугольник (который преобразует только угловые вершины, ничего между ними). Слишком много вершин сетки работает очень медленно. Я нахожу, что ~ 10-20 хорошо работают в большинстве случаев.

Пример (с использованием систем отсчета координат, отличных от OP, для иллюстрации):

 library(sf)
library(dplyr)

bb_orig = st_bbox(c(xmin = 40, xmax =-40, 
                    ymin = 45, ymax = 55), 
                    crs = st_crs(4326)) #lag/long

new_crs = 3995 # arctic polar stereographic

bb_simple_reproj = bb_orig %>% 
                   st_as_sfc() %>% 
                   st_transform(crs=new_crs) %>% 
                   st_bbox

bb_better_reproj = bb_orig %>% 
                   st_make_grid(n=10) %>%  
                   st_transform(crs = new_crs) %>% 
                   st_bbox()

# 100 random points inside the original bounding box (grey)
  sample_from_bb_orig = st_sample(st_as_sfc(bb_orig), 1000) %>%
  st_transform(new_crs)

  plot(st_geometry(sample_from_bb_orig), col="grey")

# if the bbox was only transformed as simple rectangle we would get (red):
  # red points indicate those missed by the simple bbox reprojection -- note that many are missed!
  plot(st_geometry(st_as_sfc(bb_simple_reproj)), border="red", add=TRUE)
  plot(st_difference(sample_from_bb_orig, st_as_sfc(bb_simple_reproj)) , col="red", add=TRUE)

# using 'better' repojection, with more vertices added (blue)
  # blue points indicate those missed by the simple bbox reprojection
  plot(st_geometry(st_as_sfc(bb_better_reproj)), border="blue", add=TRUE)
  plot(st_difference(sample_from_bb_orig, st_as_sfc(bb_better_reproj)) , col="blue", pch="x", add=TRUE)