随机选择路网中给定长度的线

时间:2018-10-03 13:42:25

标签: r gis spatial sampling

我想从道路网络中随机选择路段。我以为这不会太难,但是我什么也没得到。 这个想法是从线状网络中采样道路的延伸。我希望这些延伸段具有一定的长度,并且希望从网络中随机选择这些延伸段。 我找到了将SpatialLines分段为给定长度HERE的分段的方法,但这不允许随机进行,也不允许组合不同线段。 我可以使用sp包中的spsample到沿直线等距的空间点。然后,我将能够随机选择一个点作为起点。从理论上讲,我认为应该可以向一条线中添加相邻点,但是我不确定该怎么做,并且不知道当道路分开时(两条线相交)我将如何随机选择一个方向。

这里有一些数据。

    data <- data.frame(
  x = c(1,2,3,3,3,3,1,2,3),
  y = c(1,2,2,3,4,5,4,4,4),
  id = c(rep("A",6), rep("B",3))
) 


#with Kyle Walker's functions I convert the points to lines
#https://rpubs.com/walkerke/points_to_line 

library(sp)
library(maptools)

points_to_line <- function(data, long, lat, id_field = NULL, sort_field = NULL) {

  # Convert to SpatialPointsDataFrame
  coordinates(data) <- c(long, lat)

  # If there is a sort field...
  if (!is.null(sort_field)) {
    if (!is.null(id_field)) {
      data <- data[order(data[[id_field]], data[[sort_field]]), ]
    } else {
      data <- data[order(data[[sort_field]]), ]
    }
  }

  # If there is only one path...
  if (is.null(id_field)) {

    lines <- SpatialLines(list(Lines(list(Line(data)), "id")))

    return(lines)

    # Now, if we have multiple lines...
  } else if (!is.null(id_field)) {  

    # Split into a list by ID field
    paths <- sp::split(data, data[[id_field]])

    sp_lines <- SpatialLines(list(Lines(list(Line(paths[[1]])), "line1")))

    # I like for loops, what can I say...
    for (p in 2:length(paths)) {
      id <- paste0("line", as.character(p))
      l <- SpatialLines(list(Lines(list(Line(paths[[p]])), id)))
      sp_lines <- spRbind(sp_lines, l)
    }

    return(sp_lines)
  }
}

lines <- points_to_line(data = data, 
                        long = "x", 
                        lat = "y", 
                        id_field = "id")

#plot it
ori.plot <- plot(lines, col = rep(c(1, 2), length.out = length(lines)), axes = T, main="original",
     ylim=c(0,5), xlim=c(0,5))

这给了我一条带有两条简单线的图。

original lines

我想要的是一种类似于以下结果的方式: enter image description here

enter image description here

enter image description here

我可以将其细分为给定长度的片段,如上所述,它给出了类似的内容(长度= 0.3):

enter image description here

但是这些段仅限于一行,并且不能从随机点开始。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我最终做了以下事情: 将线分成一定间距的点 如我所知,横断面的长度,我知道横断面应包含多少个点。我也知道我需要多少样样。 因此,我将缓冲一个点并随机选择缓冲区中的下一个点,直到样条中有足够的点,然后再移动到下一个样条。 如果缓冲区中没有尚未分配给样点的点,则需要重置正在构建的样点中包含的点,然后通过随机选择新的起点来重新开始。

代码仍然有点混乱,但是可以在我这边工作:

#Convert the SpatialLines into SpatialPoints with regularly spaced points
points_spdf <- spsample(lines, n = 30, type = "regular")

#In my case I would need to calculate the total distance of the road network, then divide that so that I get
#a point for every XX meter

#Convert the spatialpointsdataframe to dataframe

points.df <- as.data.frame(points_spdf)
#add an ID column
points.df$ID <- seq(from=1, to=nrow(points.df), by=1)

library(sf)
#convert to an sf data.frame
points_sf <- st_as_sf(x = points.df, 
                      coords = c("x", "y"),
                      crs = "+proj=utm +zone=32 +datum=WGS84")

#add transect colum
points_sf$transect <- 0 #adds transect column and fills those with zeroes
th <- 4 #sets nr of points which are needed to form total distance of each transect

library(dplyr) #for function sample_n

plot(points_sf)

i <-1 #counter for transects, these are used as transectIDs


#####################################
#function
#This function resets transectIDs to 0 if there are no un-assigned points in the buffer and the number of 
#points with the buffer aren't enough. It also then draws a new random point.
#####################################

reset_and_sample <- function() {
  points_sf$transect <- tryCatch(points_in_poly[sample_n(subset(points_in_poly, transect.x == 0 & transect.y == i),1),1], 
                                 error=function(e) ifelse(points_sf$transect==i, 
                                                          points_sf$transect[points_sf$transect == i] <-0, 
                                                          points_sf$transect <- points_sf$transect)) 
  points_sf <<- points_sf #to retun points_sf to global ennvironment
  pt <- points_sf[ sample_n(subset(points_sf, transect == 0),1 ) ,1 ] 
  pt <<- pt
}
#####################################
pt <- NULL


while(i < 5){ #to create 4 transects
pt <- if(sum(points_sf$transect == i) < th) {
           tryCatch(points_in_poly[sample_n(subset(points_in_poly, transect.x == 0 & transect.y == i),1),1], 
            error=function(e) (reset_and_sample()))
  }else{
  pt <- (points_sf[ sample_n(subset(points_sf, transect == 0),1 ) ,1 ])
}


#put the transectID in the dataframe
ifelse((sum(points_sf$transect == i) < th),
       points_sf$transect[points_sf$ID==pt[[1]]]<-i,
       points_sf$transect[points_sf$ID==pt[[1]]]<-i+1) #puts 1 in row where ID is from pt

#this is the place where the counter for the transects is set
ifelse((sum(points_sf$transect == i) < th),
       i <- i,
       i <- i+1)

#buffers point with the ID of the selected point
buf_poly <- st_buffer((points_sf[points_sf$ID[pt[[1]]],]), dist = 0.31) 

plot(points_sf, add=TRUE)
plot(buf_poly, add=TRUE)

points_in_poly <- st_join(points_sf, buf_poly, join = st_intersects) #only points in polygons have polygon info in columns

}