Snap a point to the closest point on a line segment using sf

前端 未结 1 641
天命终不由人
天命终不由人 2021-02-08 10:31

I would like to snap a point to the closest point on a road segment using sf::st_snap. However, the function seems to return the wrong result, it\'s snapping my poi

1条回答
  •  感情败类
    2021-02-08 10:49

    I don't know why st_snap returns the start/end point of the linestring. Maybe that is something for an issue at https://github.com/r-spatial/sf.

    Here's a workaround that seems to identify the correct point. Note that st_nearest_points was only introduced recently, so you may need to install sf from github.

    nrst = st_nearest_points(point1, roads)
    new_point2 = st_cast(nrst, "POINT")[2]
    
    mapView(point1, color="red") + st_buffer(point1, dist = cut_dist) + new_point2 + roads
    

    Wrapping this is a function to return a new geometry set with snapped points below a certain max_dist:

    library(sf)
    library(mapview)
    
    st_snap_points = function(x, y, max_dist = 1000) {
    
      if (inherits(x, "sf")) n = nrow(x)
      if (inherits(x, "sfc")) n = length(x)
    
      out = do.call(c,
                    lapply(seq(n), function(i) {
                      nrst = st_nearest_points(st_geometry(x)[i], y)
                      nrst_len = st_length(nrst)
                      nrst_mn = which.min(nrst_len)
                      if (as.vector(nrst_len[nrst_mn]) > max_dist) return(st_geometry(x)[i])
                      return(st_cast(nrst[nrst_mn], "POINT")[2])
                    })
      )
      return(out)
    }
    
    brew = st_transform(breweries, st_crs(trails))
    
    tst = st_snap_points(brew, trails, 500)
    
    mapview(breweries) + mapview(tst, col.regions = "red") + trails
    

    0 讨论(0)
提交回复
热议问题