2

I've been moving most of my workflow to using the sf package in R, and I'm trying to find the equivalent to the maptools package SpatialLinesMidPoints function - I've used this function frequently over the years and had modified to get line endpoints as well (here).

Is there an equivalent function using sf package? I've looked at st_cast and st_line_sample, but want to explicitly get midpoints of lines. I'm guessing perhaps I can make use of either st_cast or st_line_sample with slight modification to get just midpoints but struggling a bit with approach.

Just to be explicit, I'm looking for equivalent of doing:

library(spData)
library(maptools)
library(sf)

seine <- as(seine, 'Spatial')
seine_midpoints <- SpatialLinesMidPoints(seine)
# To verify:
plot(seine, axes=T)
plot(seine_midpoints, add=T, col='red')
5

Looks like maptools:::getMidpoint, which underpins maptools::SpatialLinesMidPoints, can be applied to a LINESTRING geometry set without too much modification, e.g.

st_line_midpoints <- function(sf_lines = NULL) {

  g <- st_geometry(sf_lines)

  g_mids <- lapply(g, function(x) {

    coords <- as.matrix(x)

    # this is just a copypaste of View(maptools:::getMidpoints):
    get_mids <- function (coords) {
      dist <- sqrt((diff(coords[, 1])^2 + (diff(coords[, 2]))^2))
      dist_mid <- sum(dist)/2
      dist_cum <- c(0, cumsum(dist))
      end_index <- which(dist_cum > dist_mid)[1]
      start_index <- end_index - 1
      start <- coords[start_index, ]
      end <- coords[end_index, ]
      dist_remaining <- dist_mid - dist_cum[start_index]
      mid <- start + (end - start) * (dist_remaining/dist[start_index])
      return(mid)
    }

    mids <- st_point(get_mids(coords))
    })

  out <- st_sfc(g_mids, crs = st_crs(sf_lines))
  out <- st_sf(out)
}

So,

seine_sf <- st_as_sf(seine)
seine_sf_mids <- st_line_midpoints(seine_sf)

plot(seine_sf)
plot(seine_sf_mids, add = TRUE)

Looks ok for sfc_LINESTRING, but the function would need some tweaks to handle sfc_MULTILINESTRING.

  • @mweber, if this worked please accept the answer so it will be closed. There are too many open answers on this site that have valid solutions presented. – Jeffrey Evans Mar 27 '18 at 16:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.