Search code examples
rspatialpointr-sfsmoothing

From points to buffer passing through a smoothed line using sf package


I have a lot of shapefiles of points that I have to manipulate in R. My aim is to link all the points with a line, smooth it (to recreate a kind of path through points), segmentize the smoothed line in small sections (every section must have a precise length) and then create a buffer for every segments (then transform from lines to polygon) and finally count the points inside the polygons.

enter image description here

I start importing the points:

p <- st_read("/points.shp")

then I create the line:

l <- p %>% st_coordinates()  %>% st_linestring()

From the line to the smoothed line:

ls <- smooth(l, method = "ksmooth")

Then I have created the segmentized smoothed line:

sls = st_segmentize(ls, 50)

And finally my buffer:

mybuf <- st_buffer(sls, dist= 30, endCapStyle="ROUND")

Unfortunately with this last command I can create only one buffer but I have to obtain a "segmented" buffer with a length of 50 meters and a height of 30m for each section. I'm working with WGS84/UTM zone 32 N, epsg 32632 projection and my buffers must have the same projection. Maybe there is another way to to that? Thanks...

Here the link to download a subset of the shapefile


Solution

  • From what I can tell, the main issue to surmount was that your code defines the line through your points as a single feature, so st_buffer was drawing a buffer around the whole line, rather than each segment between points. My goal was to figure out how to make sure each 50 meter segment was a unique feature.

    library(sf)
    library(smoothr)
    
    cols <- c("red", "blue", "yellow")
    source_file <- "./punti.shp"
    
    par(mfrow = c(2,4))
    
    p <- st_read(source_file)
    plot(st_geometry(p), col = cols, main = "points")
    
    l <- p %>% st_coordinates()  %>% st_linestring()
    plot(st_geometry(l), col = cols, main = "line")
    l <- st_as_sf(data.frame(id = 1, geom=st_geometry(l)))
    
    ls <- smooth(l, method = "ksmooth")
    plot(st_geometry(ls), col = cols, main = "smoothed line")
    
    # Note that segmentize doesn't slice a line
    # Instead, it seems to just increases the number of vertices
    sls <- st_segmentize(ls, 50)
    slsp <- st_cast(sls, "POINT")
    plot(st_geometry(slsp), col = cols, main = "segmented line vertices")
    
    # Draw line between pairs of consecutive points
    slsp <- st_as_sf(data.frame(id = 1, geom=st_geometry(slsp)))
    slsp2 <- cbind(slsp[-nrow(slsp),"geometry"], slsp[-1,"geometry"])
    ll <- st_sfc(mapply(function(a,b){
      st_cast(st_union(a,b),"LINESTRING")}, slsp2$geometry, slsp2$geometry.1, SIMPLIFY=FALSE))
    plot(st_geometry(ll), col = cols,  main = "manually segmented line")
    plot(st_geometry(head(ll)), col = cols,  main = "man. segmented line, 1-10")
    
    # Assign crs
    st_crs(ll)
    st_crs(ll) <- st_crs(p)
    
    # Calculate buffers
    mybuf <- st_buffer(ll, dist= 30, endCapStyle="ROUND")
    plot(st_geometry(mybuf), col = cols, main = "buffers, all")
    plot(st_geometry(head(mybuf)), col = cols, main = "buffers, 1-10")
    
    # Count points in buffers
    lengths(st_intersects(mybuf, p))
    

    segmented lines