У меня есть фрейм данных с точками долготы и широты, которые при построении выглядят так: Я хочу определить отдельный фрейм данных, который содержит весь внешний левый край. Здесь я выделил несколько моментов: .
Я пробовал использовать функцию st_convex_hull(), а также функцию getBorders(), которая является частью пакета картографии, но это дает мне весь внешний край, а не только тот левый край, который мне нужен.
В этом решении используется самая северная и самая южная точки, чтобы разделить границу с lwgeom
. Нужный «край» нужно выбрать вручную (две линии из трех). В качестве примера я использовал meuse
. Граница получается с помощью st_concave_hull(ratio=0.1)
и на ней проверяются точки. В зависимости от вогнутости может потребоваться регулировка.
library(tidyverse)
library(sf)
#> Linking to GEOS 3.11.2, GDAL 3.7.2, PROJ 9.3.0; sf_use_s2() is TRUE
library(lwgeom) # for lwgeom::st_split
#> Warning: le package 'lwgeom' a été compilé avec la version R 4.3.3
#> Linking to liblwgeom 3.0.0beta1 r16016, GEOS 3.11.2, PROJ 9.3.1
#> Warning in fun(libname, pkgname): PROJ versions differ: lwgeom has 9.3.1 sf has
#> 9.3.0
#>
#> Attachement du package : 'lwgeom'
#> L'objet suivant est masqué depuis 'package:sf':
#>
#> st_perimeter
library(sp) # for meuse
data(meuse)
df_sf = meuse %>% st_as_sf(coords= c("x","y"),remove= FALSE) %>%
mutate(ID= 1:n())
ggplot(data=df_sf)+geom_sf()
# Boundary
st_simplify(df_sf %>% summarise() %>% st_concave_hull(ratio=0.1) %>% st_cast(to = "LINESTRING")) %>%
st_as_sfc() %>% ggplot(data=.)+geom_sf()
# Getting the points
border_point = df_sf %>% summarise() %>% st_concave_hull(ratio=0.1) %>% st_cast(to = "POINT") %>%
st_join(df_sf, .predicate = st_equals)
# Choosing start/end point.
MinMax = bind_rows(border_point %>% slice_max(y),
border_point %>% slice_min(y))
# Splitting along those points
boundary_split =
lwgeom::st_split(df_sf %>% summarise() %>% st_concave_hull(ratio=0.1) %>% st_cast(to = "LINESTRING"),
MinMax ) %>%
st_collection_extract(., "LINESTRING") %>%
mutate(id_line = 1:n())
# Three lines are generated, since the start/end of the linestring acts as a splitting point as well
# Plotting to identify the releveants id_line (left shore),
boundary_split %>%
ggplot(data=.)+geom_sf( aes(col = id_line %>% as.factor()))
# manually selecting
left_boundary = boundary_split %>% filter( id_line %in% c(1,2))
left_points = st_join(df_sf,left_boundary ) %>%
# Removing unjoinned point (NA), there is certainly a better way
filter( id_line %in% c(1,2))
# Ploting elements
ggplot()+
geom_sf(data=df_sf %>% summarise() %>% st_concave_hull(ratio=0.1),fill=NA)+
geom_sf(data=df_sf,col = "grey")+
geom_sf(data =MinMax, col = "green", size =5)+
geom_sf(data = boundary_split,aes(col = id_line %>% as.factor()) )+
geom_sf(data = left_points, col = "red")
Created on 2024-04-16 with reprex v2.1.0
элегантное решение. Большое большое спасибо
Я попробовал решение, но мне нужно знать, согласны ли вы сделать выбор вручную, прежде чем опубликовать его. В противном случае вам нужно уточнить, что вы считаете «левым краем» (между самым южным и самым северным?)