i am coding with R and RStudio. I have a set of polygons in one in my global environment called buek250_shapefile. I am able to plot them with leaflet. For the next step I wrote a function which gets lat and lon values, and should give back information about the shape which haqs the shortest distance to the next polygon shape. My problem: I always get back the same polygon shape for all lat lon values I am trying. And the computed distances are between 5000 and 7000km. But all my shapes and lat lon values are in Germany, and Germany is not so big. My data: https://download.bgr.de/bgr/boden/BUEK250/shp/buek250_mg_utm_v55.zip Can anyone here help me please? Thank you very much
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)
}
Right now I receive for every input the same output. I expect the code to return the shapefile with the shortest distance to the given point.
While geographic coordinates are usually represented as latitude, longitude
pairs, geometric operations generally expect x, y
order, that also applies for sf::st_point()
. If you need a mnemonic for lat/lon, you could try "lat" -> "ladder" -> "y" .
To transform from one CRS to another, use st_transform()
; but for this to work, input must have CRS assigned and this is the role of crs
argument in st_sfc(x, crs = "WGS84")
.It defines what you currently have, not what you want to end up with.
I'm using shapes from giscoR
for a reproducible example here.
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)
First, let's try to build a point from those geographic coordinates so it ends up somewhere in the area of interest:
# 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
Seems that we got lat/lon order and transformation right this time, let's adjust that function accordingly, we can use st_nearest_feature()
to subset 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 our test point & resulting shape:
# 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