Преобразовать точку в UTM 32N

я пишу с помощью R и RStudio. В моей глобальной среде есть набор полигонов, один из которых называется buek250_shapefile. Я могу нанести их на листовку. Для следующего шага я написал функцию, которая получает значения широты и долготы и должна возвращать информацию о фигуре, которая имеет кратчайшее расстояние до следующей формы многоугольника. Моя проблема: я всегда получаю одну и ту же форму многоугольника для всех значений широты и долготы, которые я пытаюсь использовать. Расчетные расстояния составляют от 5000 до 7000 км. Но все мои фигуры и значения широты находятся в Германии, а Германия не такая уж большая. Мои данные: https://download.bgr.de/bgr/boden/BUEK250/shp/buek250_mg_utm_v55.zip Может ли кто-нибудь здесь помочь мне, пожалуйста? Большое спасибо

lowestdistancebuek <- function(inputlat, inputlon) {
  # Modify the clicked point. Make the input data into CRS format
  # Order is important: first lat, then lon
  point <- st_point(c(inputlat, inputlon)) %>%
    st_sfc(crs = 25832)
  
  # Is there a shape containing the clickedpoint?
  nearestshape <- st_intersects(point, buek250_shapefile_all, sparse = FALSE)
  # nearestsape is a logical matrix. For every polygon it contains if the point is in or not
  # Which polygon contains the point? Extract it
  nearestshape <- which(nearestshape, arr.ind = TRUE)
  # Extract the column
  nearestshape <- nearestshape[,2]

  # If there is a shape containing the point, nearestshape has length 1
  # In this case, nearestshape is set to the sf
  # Otherwise, the nearestshape is determinded and set to nearestshape
  if (length(nearestshape) == 1) {
    nearestshape <- buek250_shapefile_all[nearestshape, ]
  } else if (length(nearestshape) == 0){ # no polygon contains the point
    # Compute the distances between each polygon and the point. Result is saved in distances
    distances <- st_distance(point, buek250_shapefile_all,
                             by_element = FALSE, # TRUE returns a vector
                             tolerance = TRUE # speeds up computing
                             )
    # Which distance ist the smallest one?
    nearestshape <- which.min(distances)
    # The shortest number was saved in nearestshape, now there is saved the polygone information
    nearestshape <- buek250_shapefile_all[nearestshape, ]
  }
  return(nearestshape)
}

Прямо сейчас я получаю для каждого входа один и тот же результат. Я ожидаю, что код вернет шейп-файл с кратчайшим расстоянием до заданной точки.

Добро пожаловать в ТАК! Пожалуйста, сделайте этот пример воспроизводимым для других. Например, мы не знаем, как вы загружаете этот шейп-файл, как вы звоните lowestdistancebuek() или какие значения координат вы тестировали. Тем не менее, ваш st_point(c(inputlat, inputlon)) должен читаться st_point(c(inputlon, inputlat)). Или, что еще лучше, используйте что-то вроде x,y или easting, northing при ссылке на координаты зоны 32N ETRS89/UTM в вашем коде.

margusl 19.06.2024 10:54

Делаем еще одно предположение на основе заголовка («трансформировать») и комментариев к коду («щелчок») — если эти входные координаты являются значениями широты и долготы из листовки, st_sfc(crs = 25832) не преобразует, а просто переводит геометрию CRS в epsg:25832. В результате любое значение широты и долготы из Германии, независимо от порядка, оказывается где-то в Атлантике, рядом с Африкой, в том же диапазоне 5000....7000 км от Германии, свидетелем которого вы являетесь.

margusl 19.06.2024 11:41

Эй, Маргусл, сейчас я просто тестирую некоторые значения широты и долготы, например 52,52, 10,405. Я предполагаю, что моя проблема — ложное смещение на восток, но я не знаю, как ее решить. Почему st_transform делает это нет? Я загружаю форму с помощью: buek250_shapefile_all <- sf::st_read("C:/Users/Documents/Uni/SoilMapExtraData/buek250‌​_mg_utm_v55/buek250_‌​mg_utm_v55.shp") Я могу сопоставить формы с помощью листовки. Прямо сейчас я вызываю lowdistancebuek(52.52,10.405) или другие значения прямо в консоли.

odcoder 19.06.2024 11:49

Как правильно предположил @margusl, вы вводите координаты в десятичных градусах в свою функцию, а затем назначаете им проекционную систему координат (PCS) CRS, которая имеет метры для единиц измерения. Таким образом, эти десятичные градусы рассматриваются как метры. Предполагая, что вы вводите значения WGS84/EPSG:4326, вам нужно что-то вроде st_point(c(inputlon, inputlat)) %>% st_sfc(crs = 4326) %>% st_transform(25832). Что бы вы ни делали, вам необходимо знать систему координат ваших входных координат и убедиться, что это долгота (назначается первой), а какая широта (назначается второй).

L Tyrone 19.06.2024 12:17

Я уже пробовал этот способ. Но это ничего не меняет при вычислении расстояний. point_df <- data.frame(X = c(inputlat), Y = c(inputlon)) point <- st_as_sf(point_df, coords = c("X", "Y"), crs = 4326) point <- st_transform( point, crs = 25832) > point Простая коллекция объектов с 1 объектом и 0 полями Тип геометрии: POINT Размер: XY Ограничительная рамка: xmin: 5908302 ymin: 1601570 xmax: 5908302 ymax: 1601570 Проецируемая CRS: ETRS89 / зона UTM 32N геометрия 1 POINT (5908302 1601570) > расстояния[которые.мин(расстояния)] 6283818 [м]

odcoder 19.06.2024 12:30

Вы все еще инвертируете значения широты и долготы в своем df. Пожалуйста, перечитайте внимательно комментарии выше. Чтобы объяснить это по-другому, x == долгота и y == широта. Так и должно быть df <- data.frame(X = c(inputlon), Y = c(inputlat)).

L Tyrone 19.06.2024 12:35
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хотя географические координаты обычно представляются в виде пар latitude, longitude, геометрические операции обычно предполагают порядок x, y, который также применим и к sf::st_point(). Если вам нужна мнемоника для широты и долготы, вы можете попробовать «lat» -> «ladder» -> «y» .

Чтобы преобразовать одну CRS в другую, используйте st_transform(); но для того, чтобы это работало, входным данным должен быть назначен CRS, и это роль аргумента crs в st_sfc(x, crs = "WGS84"). Он определяет то, что у вас есть в данный момент, а не то, что вы хотите получить в итоге.

Здесь я использую формы из giscoR для воспроизводимого примера.

library(giscoR)
library(sf)
#> Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE

# example shapes from GISCO / giscoR
ger_25832 <- 
  giscoR::gisco_get_nuts(country = "Germany", nuts_level = "1") |>
  st_transform(25832)

plot(ger_25832[,"NUTS_NAME"], axes = TRUE)

Во-первых, давайте попробуем построить точку по этим географическим координатам, чтобы она оказалась где-то в интересующей области:

# input point coordinates, WGS84
inputlat_wgs84 <- 52.52   # mnemonic: latitude like "ladder", y-axis
inputlon_wgs84 <- 10.405

# create WGS84 point, transform, check distances:
ref_pt <- 
  # x,y!
  st_point(c(inputlon_wgs84, inputlat_wgs84)) |> 
  st_sfc(crs = "WGS84") |>
  st_transform(crs = st_crs(ger_25832))

st_distance(ger_25832, ref_pt) |> units::set_units(km)
#> Units: [km]
#>            [,1]
#>  [1,] 221.48755
#>  [2,] 184.04861
#>  [3,]  88.60661
#>  [4,] 114.36606
#>  [5,] 101.80472
#>  [6,] 115.41499
#>  [7,]  87.67142
#>  [8,]   0.00000
#>  [9,]  87.76893
#> [10,] 250.06811
#> [11,] 396.54742
#> [12,] 165.09594
#> [13,]  35.32782
#> [14,]  94.75578
#> [15,]  99.73750
#> [16,] 308.01952

Кажется, на этот раз у нас правильный порядок и преобразование широты и долготы, давайте соответствующим образом настроим эту функцию, мы можем использовать st_nearest_feature() для подмножества ближайшего объекта:

# same in the function + subset with st_nearest_feature()
lowestdistancebuek <- function(inputlat_wgs84, inputlon_wgs84, shapes = ger_25832){
  ref_pt <- 
    st_point(c(inputlon_wgs84, inputlat_wgs84)) |> 
    st_sfc(crs = "WGS84") |>
    st_transform(crs = st_crs(shapes))
  shapes[st_nearest_feature(ref_pt, shapes),]
}

nearest_shape <- lowestdistancebuek(inputlat_wgs84, inputlon_wgs84)
nearest_shape
#> Simple feature collection with 1 feature and 10 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 343686.6 ymin: 5682911 xmax: 674176.7 ymax: 5971541
#> Projected CRS: ETRS89 / UTM zone 32N
#>    NUTS_ID LEVL_CODE URBN_TYPE CNTR_CODE     NAME_LATN     NUTS_NAME MOUNT_TYPE
#> 58     DE9         1         0        DE NIEDERSACHSEN NIEDERSACHSEN          0
#>    COAST_TYPE FID geo                       geometry
#> 58          0 DE9 DE9 MULTIPOLYGON (((486772.8 59...

Постройте нашу тестовую точку и полученную форму:

# plot 
plot(st_union(ger_25832))
plot(nearest_shape, add = TRUE)
#> Warning in plot.sf(nearest_shape, add = TRUE): ignoring all but the first
#> attribute
plot(ref_pt, col = "red", pch = 16, add = TRUE)

Created on 2024-06-19 with reprex v2.1.0

Другие вопросы по теме