R: el paquete sf apunta a varias líneas con st_cast

8

Quiero crear varias líneas a partir de puntos dados como sf objects.

Si tengo varios puntos como

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

y estoy usando st_castpara crear líneas de ellos

lines <- st_cast(pts, "MULTILINESTRING")

Siempre obtendré uno sf objectcon múltiples segmentos, pero lo que quiero obtener son varias líneas (dos en este ejemplo).

danceb
fuente
¿Qué resultado te gustaría obtener? Con tres puntos A, B y C puede hacer 3 líneas diferentes: AB, AC, BC. ¿Qué pasa si su matriz tiene cien líneas?
user30184
Parece que desea el equivalente de SF de este procedimiento postgis : gis.stackexchange.com/questions/174472/… , que AFAIK no es posible ... todavía. ¿Quizás plantear un problema en la página de github de sf?
obrl_soil

Respuestas:

7

Creo que el sfpaquete necesita saber primero cómo desea crear las líneas a partir de sus puntos. Me refiero a qué par de POINThacer cada LINESTRING. En mi ejemplo, eso se definió dentro de la lapplyfunción. Siga el código reproducible y comentado a continuación, espero que ayude:

# 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)

Figura 1

Guzmán
fuente
Gracias Guzmán por tu respuesta! Esta solución funciona si el orden de los puntos dados es el mismo que el orden de las líneas que se crearán. Pero si hay otro orden en el sf object(like matrix(c(10, 10, 30, 30, 15, 20), nrow = 3, byrow = TRUE)), crea una línea que une la esquina inferior izquierda con la superior derecha en este caso. user30184 mencionó esto en su comentario anterior. ¿Existe la posibilidad de ordenar los puntos por distancia mínima o algo así? ¡Gracias!
danceb
4

¡He encontrado una solución! Para todos los demás, que también buscan una respuesta, la forma en que la resolví:

# 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)

ingrese la descripción de la imagen aquí

Sin embargo, ¡gracias de nuevo por tu ayuda!

danceb
fuente