8

I want to create multiple lines out of given points as sf objects.

If I have a number of points as

library(sf)
pts <- st_multipoint(matrix(c(10, 10, 15, 20, 30, 30), nrow = 3, byrow = TRUE), dim = "XY")

and I am using st_cast to create lines of them

lines <- st_cast(pts, "MULTILINESTRING")

I will always get one sf object with multiple segments, but what I want to get is multiple lines (two in this example).

  • What result would you like to get? With three points A, B, and C you can make 3 different lines: AB, AC, BC. What if your matrix has a hundred lines? – user30184 Feb 8 '18 at 8:28
  • It sounds like you want the sf equivalent of this postgis procedure - gis.stackexchange.com/questions/174472/…, which AFAIK is not possible...yet. Maybe raise an issue on sf's github page? – obrl_soil Feb 8 '18 at 12:25
7

I think that the sf package need to know first how you want to create the lines from your points. I mean which pair of POINT make every LINESTRING. In my example that was defined inside the lapply function. Follow the reproducible and commented code below, hope that helps:

# Load library
library(sf)

# Create points data
multipoints <- st_multipoint(matrix(c(10, 10, 15, 20, 30, 30), nrow = 3, byrow = TRUE), dim = "XY")
points <- st_cast(st_geometry(multipoints), "POINT") 

# Number of total linestrings to be created
n <- length(points) - 1

# Build linestrings
linestrings <- lapply(X = 1:n, FUN = function(x) {

  pair <- st_combine(c(points[x], points[x + 1]))
  line <- st_cast(pair, "LINESTRING")
  return(line)

})

# One MULTILINESTRING object with all the LINESTRINGS
multilinetring <- st_multilinestring(do.call("rbind", linestrings))

# Plot
plot(multipoints, pch = 19, cex = 2)
plot(multilinetring[[1]], col = "orange", lwd = 2, add = TRUE)
plot(multilinetring[[2]], col = "green", lwd = 2, add = TRUE)

fig1

  • Thank you Guzmán for your answer! This solution works if the order of the given points is the same as the order of the lines to be created. But if there is another ordering in the sf object (like matrix(c(10, 10, 30, 30, 15, 20), nrow = 3, byrow = TRUE)) it creates a line which link the lower left with the upper right point in this case. user30184 mentioned this in his comment above. Is there a possibility to sort the points per minimal distance or something like that? Thanks! – danceb Feb 9 '18 at 11:02
4

I have found a solution! For all of the others, which are looking for an answer as well, the way I have solved it:

# Load library
library(sf)

# create points data
m <- matrix(c(10, 10, 30, 30, 15, 20), nrow = 3, byrow = TRUE)
multipoints <- st_multipoint(m, dim = "XY")

# save ranges of coordinates
x.range <- max(m[,1]) - min(m[,1])
y.range <- max(m[,2]) - min(m[,2])

# order by greatest range
if (x.range > y.range) {
  sort.id <- order(m[,1])
} else if (y.range > x.range) {
  sort.id <- order(m[,2])
} else if (y.range == x.range) {
  sort.id <- order(m[,2])
}

# creat lines by previous sorting and save them in the list
lines <- lapply(1:(length(sort.id)-1), function(i) {
  st_linestring(rbind(multipoints[sort.id[i],], multipoints[sort.id[i+1],]))
})

# plot results
plot(multipoints)
plot(lines[[1]], col = "orange", lwd = 2, add = TRUE)
plot(lines[[2]], col = "green", lwd = 2, add = TRUE)

enter image description here

Nevertheless, thanks again for your help!

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.