[GIS] Breaking long line segments into shorter ones in R using sf

linestringrsf

I have a shapefile of river segments that I've imported into R. The segments range in length from 5-115km. I want to split the segments that are over 10km into 10km chunks. So I use st_segmentize. But this doesn't actually split a long line into multiple new shorter lines, which is what I want… Is there a way to do this? I think st_segmentize just adds vertices every 10km. So I just need to split the lines at the vertices.

Code so far:

library("sf")

rivers = st_read("./YukonMain4_copy.shp", layer = 'YukonMain4_copy')

seg = st_segmentize(rivers, units::set_units(10,km))

Re. my above comment

The issue is, my resulting lines have lengths mostly from 200-500m, and then there are random onesthat are 700000m long. Plus, this data set is of multiple rivers, so now I have lines connecting places that should not be connected. Any ideas?

Here is my code:

  1. Import file, segmentize the data, and cast it into the point cloud
  2. Create an index to combine segments by (hopefully so that they are approx 10km in length
  3. Combine things back into lines.

    rivers=st_read("./YukonMain4_copy.shp", layer='YukonMain4_copy')
    seg = st_segmentize(rivers, units::set_units(10000,m))
    seg2= st_cast(seg, 'POINT')
    
    
    length = length(seg2$OBJECTID)/2
    index = rep(1:length, each=2)
    rivers.index=cbind(seg2, index)
    
    to_line <- function(points) st_cast(st_combine(points), "LINESTRING") %>% .[[1]] 
    rivers.nest = rivers.index %>% group_by(index) %>% nest
    segments = rivers.nest %>% pull(data) %>% map(to_line)%>%st_sfc(crs = 4326)
    lines = rivers.nest %>% select(data)%>% st_sf(geometry=segments)
    

Best Answer

I was looking for exactly this function to use with NHDPlus data. I spent some time with JMT2080AD's functions but needed a bit more scalable solution.

The function in this gist does the trick pretty nicely. There is a reproducible example at the bottom of the gist too.

--- Edit:

There is also now a function to do this in the lwgeom package. https://github.com/r-spatial/lwgeom/issues/16

Related Question