r-spatial / lwgeom

bindings to the liblwgeom library
https://r-spatial.github.io/lwgeom/
60 stars 24 forks source link

lwgeom::st_split re-orders segments #82

Closed scoddou closed 2 years ago

scoddou commented 2 years ago

Describe the bug I noticed while using lwgeom::st_split to split a LINESTRING on its own POINT's that the resulting sfc is reordered. Is this repeatable on your end (realizing lwgeom is just a binding to liblwgeom), and if so, is there a better way for me to "segment" linestrings by their vertices while retaining order?

To Reproduce

library(sf)
library(lwgeom)

line = st_sfc(st_linestring(matrix(c(0,0,0,10,0,20,0,30,0,40),ncol=2, byrow=TRUE)))
points = st_cast(line,"POINT")
st_collection_extract(st_split(line,points),"LINESTRING")

giving

Geometry set for 4 features 
Geometry type: LINESTRING
Dimension:     XY
Bounding box:  xmin: 0 ymin: 0 xmax: 0 ymax: 40
CRS:           NA
LINESTRING (0 30, 0 40)
LINESTRING (0 0, 0 10)
LINESTRING (0 10, 0 20)
LINESTRING (0 20, 0 30)
sessionInfo() R version 4.1.1 (2021-08-10) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 19042) Matrix products: default locale: [1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 [3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C [5] LC_TIME=English_United States.1252 attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] lwgeom_0.2-8 sf_1.0-7 loaded via a namespace (and not attached): [1] Rcpp_1.0.8.3 magrittr_2.0.2 units_0.8-0 tidyselect_1.1.2 [5] R6_2.5.1 rlang_1.0.2 fansi_1.0.2 dplyr_1.0.8 [9] tools_4.1.1 grid_4.1.1 KernSmooth_2.23-20 utf8_1.2.2 [13] cli_3.2.0 e1071_1.7-9 DBI_1.1.2 ellipsis_0.3.2 [17] class_7.3-19 assertthat_0.2.1 tibble_3.1.6 lifecycle_1.0.1 [21] crayon_1.5.0 purrr_0.3.4 vctrs_0.3.8 glue_1.6.2 [25] proxy_0.4-26 compiler_4.1.1 pillar_1.7.0 generics_0.1.2 [29] classInt_0.4-3 pkgconfig_2.0.3 sf::sf_extSoftVersion() GEOS GDAL proj.4 GDAL_with_GEOS USE_PROJ_H PROJ "3.9.1" "3.2.1" "7.2.1" "true" "true" "7.2.1"
scoddou commented 2 years ago

Closing here.

Ended up using a complete sf implementation that is good enough for me to proceed. In case anyone stumbles upon this thread in the future:

library(sf)

line = st_sfc(st_linestring(matrix(c(0,0,0,10,0,20,0,30,0,40),ncol=2, byrow=TRUE)))
points = st_cast(line,"POINT")
st_cast(st_difference(line,st_union(st_buffer(points,dist=0.00001))),"LINESTRING")
Geometry set for 4 features 
Geometry type: LINESTRING
Dimension:     XY
Bounding box:  xmin: 0 ymin: 1e-05 xmax: 0 ymax: 39.99999
CRS:           NA
LINESTRING (0 1e-05, 0 9.99999)
LINESTRING (0 10.00001, 0 19.99999)
LINESTRING (0 20.00001, 0 29.99999)
LINESTRING (0 30.00001, 0 39.99999)