I am trying to return the vertices of a linestring using the sf
package. So far I have:
ls <- st_sfc(st_linestring(rbind(c(0,0),c(0,1))),
st_linestring(rbind(c(0,0),c(10,0))))
get_line_endings <- function(line){
res <- lapply(line, function(x){
pnts <- st_coordinates(x)
pnts <- pnts[c(1, nrow(pnts)),]
data.frame(pnts)
})
res <- do.call("rbind", res)
res <- res[!duplicated(res),]
st_as_sf(res, coords = c("X", "Y"), crs = st_crs(line))
}
pnts <- get_line_endings(ls)
plot(ls)
plot(pnts, add = TRUE)
Is this error prone? Can I rely on st_coordinates
being "in order"? Is there a more efficient way of doing this?
Answer
st_cast
is what you are looking for.
library(sf)
library(mapview)
ls <- st_sfc(st_linestring(rbind(c(0,0),c(0,1))),
st_linestring(rbind(c(0,0),c(10,0))))
ptns = st_cast(ls, "POINT")
mapview(ls, color = "red") + ptns
You can also cast to MULTIPOINT
if you wish.
Edit:
As mentioned by @Spacedman in the comments, this returns 4 points, because 2 separate linestrings with 2 vertices each are cast. If we want only 3 points, we need to set up the line to be a single linestring with 3 vertices:
ls = st_sfc(st_linestring(matrix(c(c(0,1),c(0,0),c(10,0)),
ncol = 2, byrow = TRUE)))
Then pnts = st_cast(ls, "POINT")
will result in 3 points.
Edit 2:
If you only want the endpoints, then st_line_sample
is what you are looking for:
ptns = st_line_sample(ls, sample = 1)
where sample
is a numeric value between 0 and 1 (0 being the start point and 1 the endpoint).
No comments:
Post a Comment