Le package R: sf pointe vers plusieurs lignes avec st_cast

8

Je veux créer plusieurs lignes à partir de points donnés en tant que sf objects.

Si j'ai un certain nombre de points

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

et j'utilise st_castpour en créer des lignes

lines <- st_cast(pts, "MULTILINESTRING")

J'en obtiendrai toujours un sf objectavec plusieurs segments, mais ce que je veux obtenir, c'est plusieurs lignes (deux dans cet exemple).

danceb
la source
Quel résultat aimeriez-vous obtenir? Avec trois points A, B et C, vous pouvez faire 3 lignes différentes: AB, AC, BC. Et si votre matrice a cent lignes?
user30184
Il semble que vous souhaitiez l'équivalent sf de cette procédure postgis - gis.stackexchange.com/questions/174472/… , ce que l'AFAIK n'est pas possible ... pour le moment. Peut-être soulever un problème sur la page github de sf?
obrl_soil

Réponses:

7

Je pense que le sfpackage doit d'abord savoir comment vous voulez créer les lignes à partir de vos points. Je veux dire quelle paire de POINTfaire chaque LINESTRING. Dans mon exemple, cela a été défini à l'intérieur de la lapplyfonction. Suivez le code reproductible et commenté ci-dessous, j'espère que cela vous aidera:

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

Fig. 1

Guzmán
la source
Merci Guzmán pour ta réponse! Cette solution fonctionne si l'ordre des points donnés est le même que l'ordre des lignes à créer. Mais s'il y a un autre ordre dans le sf object(comme matrix(c(10, 10, 30, 30, 15, 20), nrow = 3, byrow = TRUE)), il crée une ligne qui relie le coin inférieur gauche au point supérieur droit dans ce cas. user30184 l'a mentionné dans son commentaire ci-dessus. Y a-t-il une possibilité de trier les points par distance minimale ou quelque chose comme ça? Merci!
danceb
4

J'ai trouvé une solution! Pour tous les autres, qui cherchent également une réponse, la façon dont je l'ai résolu:

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

entrez la description de l'image ici

Néanmoins, merci encore pour votre aide!

danceb
la source