我想从道路网络中随机选择路段。我以为这不会太难,但是我什么也没得到。 这个想法是从线状网络中采样道路的延伸。我希望这些延伸段具有一定的长度,并且希望从网络中随机选择这些延伸段。 我找到了将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))
这给了我一条带有两条简单线的图。
或
或
我可以将其细分为给定长度的片段,如上所述,它给出了类似的内容(长度= 0.3):
但是这些段仅限于一行,并且不能从随机点开始。
有什么想法吗?
答案 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
}