Search code examples
rterra

SpatVector lines: cannot create independent segments


Given the example of the help page:

x1 <- rbind(c(-180,-20), c(-140,55), c(10, 0), c(-140,-60))
x2 <- rbind(c(-10,0), c(140,60), c(160,0), c(140,-55))
x3 <- rbind(c(-125,0), c(0,60), c(40,5), c(15,-45))
hole <- rbind(c(80,0), c(105,13), c(120,2), c(105,-13))
z <- rbind(cbind(object=1, part=1, x1, hole=0), cbind(object=2, part=1, x3, hole=0),
           cbind(object=3, part=1, x2, hole=0), cbind(object=3, part=1, hole, hole=1))
colnames(z)[3:4] <- c('x', 'y')
z[z[, "hole"]==1, "object"] <- 4
lns <- vect(z[,1:4], "lines")
z[1:3,]
#     object part    x   y hole
#[1,]      1    1 -180 -20    0
#[2,]      2    1 -140  55    0
#[3,]      3    1   10   0    0

I modify z to define the vertices of a polyline (independent segments between consecutive points)

z[,1] <- 1:nrow(z)
duptimes <- rep(2,nrow(z))
idx <- rep(1:nrow(z), duptimes)
dupz <- z[idx,]
dupz <- dupz[-c(1,nrow(dupz)]
dupz[,1] <- rep(1:(nrow(z)-1), rep(2, nrow(z)-1))

head(dupz)
#     object part    x   y hole
#[1,]      1    1 -180 -20    0
#[2,]      1    1 -140  55    0
#[3,]      2    1 -140  55    0
#[4,]      2    1   10   0    0
#[5,]      3    1   10   0    0
#[6,]      3    1 -140 -60    0

But get an empty object

 river <- vect(dupz, "lines")   
 plot(river)
 river
 #class       : SpatVector 
 #geometry    : lines 
 #dimensions  : 16, 0  (geometries, attributes)
 #extent      : -180, 160, -60, 60  (xmin, xmax, ymin, ymax)
 #coord. ref. :  

enter image description here


Solution

  • The simple way to do this is to use disagg(, segments=TRUE).

    lns <- vect(z[,1:4], "lines")
    d <- disagg(lns, segments=TRUE)
    set.seed(1)
    plot(d, col=sample(rainbow(30)), lwd=3)
    

    enter image description here

    Your code doesn't run, but it should work if you fix it as suggested by L_O. Here is another way to express the same

    n <- nrow(z)
    i <- rep(2:(n-1), each=2)
    dupz <- z[c(1, i, n),]
    dupz[,1] <- c(1, 1, i)
    
    v <- vect(dupz[,-5], "lines")
    set.seed(1)
    plot(v, col=sample(rainbow(30)), lwd=3)
    

    enter image description here

    This approach connects each polyline. I would not think that you would want that. But if you do want that, a much simpler approach would be

    v <- as.lines(as.points(lns)) |> disagg(TRUE)