This question gave me some ideas to write a post about it, trying to get the R tools to perform such a thing.
Here you can check all details. It is in spanish but you can use the translation of the browser.
This is the resume of what I tryed:
- Convert all layers into points by sampling the lines layer (streets & rivers) and by sampling the polygons (areas with speed restrictions) by a regular grid. At this points you can either change the speed of streen by the polygon one or keep both points with different speeds.
- Merge the speedpoints layers.
- Create an empty raster grid and rasterize the points using it.
- Calculate the accumulated cost with the
gdistance
library.
- (optional but as you asked for Voronoi...) Convert back the raster into points and calculate the polygons with
st_voronoi
.
- Consolidate this process into a functiton that can by used in parallel over all you points.
Here, speeds is the raster of speed values:
# Read raw data
locs <- st_read("./data/20230126/data-raw/LEIP/LEIP.shp")
roads <- st_read("./data/20230126/data-raw/Carreteras_IMD/Carreteras_IMD.shp")
terrain <- st_read("./data/20230126/data-raw/AEIP/AEIP.shp")
rios <- st_read("./data/20230126/data-raw/Rios/Rios.shp")
# Create random speeds for features
r <- r %>% mutate(SPEED = sample(50, size = nrow(r))) %>% st_cast("LINESTRING")
w <- w %>% mutate(SPEED = sample(500, size = nrow(w))/10) %>% st_cast("LINESTRING")
t <- t %>% mutate(SPEED = sample(50, size = nrow(t)))
wpoints <- w %>% st_cast("POINT")
rpoints <- r %>% st_cast("POINT")
tpoints <- st_sample(t, size = 500, type = "regular") %>% st_as_sf() %>% st_join(t, join = st_nearest_feature)
# merge all points with speeds
speedpoints <- bind_rows(wpoints, rpoints, tpoints) %>% dplyr::select(SPEED)
#función para empty raster (raster base)
library(raster)
library(fasterize)
rasterbase <- function(layer, res){
r <- raster(extent(layer), res)
res(r) <- c(res, res)
crs(r) <- crs(layer)
values(r) <- NA
return(r)
}
raster <- rasterbase(l, 50)
g = st_combine(st_geometry(speedpoints))
x <- st_voronoi(g, bOnlyEdges = FALSE)
v = st_as_sf(st_collection_extract(x)) %>%
st_join(speedpoints, join = st_nearest_feature) %>%
st_make_valid() %>%
st_cast("POLYGON") %>%
st_crop(l)
speeds <- fasterize(v, raster, field = "SPEED")
tr <- transition(speeds, transitionFunction=mean, directions=8)
trc <- geoCorrection(tr, type="c", multpl=FALSE, scl=TRUE)
Here is the function for travel time for one starting point:
traveltime <- function(p, trc){
# p <- p <- l[1,]
ac <- accCost(trc, st_coordinates(p))
ttras <- round(ac)
ttpol <- polygonizator(ttras) %>% rename(TIME = layer)
ttpol$ID <- p$ID
return(ttpol)
}
And here, lsel is the layer with Locations (points), around 1000:
lsel <- l
library(parallel)
cl <- parallel::makeCluster(detectCores(), type="FORK")
doParallel::registerDoParallel(cl)
TTIMES <- parLapply(cl, 1:nrow(lsel), function(x){traveltime(lsel[x,], trc)})
stopCluster(cl)



May not be a perfect solution, but as an aproximation can be useful. May be others can develop this further.
Hope it helps.