What data does one need to download from OSM in order to have data sufficient to define the street net? One way to answer this question is to inspect the R package ‘dodgr’ and see what data is downloaded in this package in order to construct a street net model using a weighted graph. The answer turns out to be that it is simply the ‘osm_lines’, hence the line strings of an OSM call where the ‘feature(key = “highway”)’ is retrieved. According to wiki key=‘highway’ is used for identifying any kind of road, street or path (https://wiki.openstreetmap.org/wiki/Key:highway).
The R package 'dodgr' performs efficient calculation of many-to-many
pairwise distances on dual-weighted directed graphs.
One application supported by the package is the download of subsets the
OSM street network. The subset of the network is represented as a dual-
weighted directed graph and transpotation time between nodes representing
locations are calculated.
The download of a section of the OSM network is performed using the calls
bb <- osmdata::getbb("Copenhagen")
net <- dodgr_streetnet(bb)
where the first command simply finds a bounding box that includes Copenhagen
the capital of Denmark. The second command downloads the street network of the
city Copenhagen from OSM. But what exactly is the street network?
This question is obviously twofold:
What data from OSM represents the road network of an area?
How is that data used and transformed into a network?
The command 'dodgr_streetnet(bb)' has the following sourcecode:
function (bbox, pts = NULL, expand = 0.05, quiet = TRUE)
{
bb <- process_bbox(bbox, pts, expand)
net <- osmdata::opq(bb$bbox) %>% osmdata::add_osm_feature(key = "highway") %>%
osmdata::osmdata_sf(quiet = quiet) %>% osmdata::osm_poly2line()
if (nrow(net$osm_lines) == 0)
stop("Street network unable to be downloaded")
if (!is.null(bb$bbox_poly))
net <- osmdata::trim_osmdata(net, bb$bbox_poly)
return(net$osm_lines)
}
which apparently calls the function 'process_bbox()'. The sourcecode of that function can
be gotten by calling
dodgr:::process_bbox
resulting in the print out:
function (bbox, pts = NULL, expand = 0.05)
{
bbox_poly <- NULL
if (!missing(bbox)) {
if (is.character(bbox))
bbox <- osmdata::getbb(bbox)
else if (is.list(bbox)) {
if (!all(vapply(bbox, is.numeric, logical(1))))
stop("bbox is a list, so items must be numeric ",
"(as in osmdata::getbb (..., format_out = 'polygon'))")
if (length(bbox) > 1)
message("selecting the first polygon from bbox")
bbox_poly <- bbox[[1]]
bbox <- apply(bbox[[1]], 2, range)
}
else if (is.numeric(bbox)) {
if (!inherits(bbox, "matrix")) {
if (length(bbox) != 4)
stop("bbox must have four numeric values")
bbox <- rbind(sort(bbox[c(1, 3)]), sort(bbox[c(2,
4)]))
}
else if (nrow(bbox) > 2) {
bbox_poly <- bbox
bbox <- apply(bbox, 2, range)
}
}
if (identical(rownames(bbox), c("x", "y")) |
identical(colnames(bbox), c("min", "max")))
bbox <- t(bbox)
bbox[, 1] <- bbox[, 1] + c(-expand, expand) * diff(bbox[,
1])
bbox[, 2] <- bbox[, 2] + c(-expand, expand) * diff(bbox[,
2])
}
else if (!is.null(pts)) {
nms <- names(pts)
if (is.null(nms))
nms <- colnames(pts)
colx <- which(grepl("x", nms, ignore.case = TRUE) |
grepl("lon", nms, ignore.case = TRUE))
coly <- which(grepl("y", nms, ignore.case = TRUE) |
grepl("lat", nms, ignore.case = TRUE))
if (!(length(colx) == 1 | length(coly) == 1))
stop("Can not unambiguously determine coordinates in graph")
x <- range(pts[, colx])
x <- x + c(-expand, expand) * diff(x)
y <- range(pts[, coly])
y <- y + c(-expand, expand) * diff(y)
bbox <- c(x[1], y[1], x[2], y[2])
}
else stop("Either bbox or pts must be specified.")
list(bbox = bbox, bbox_poly = bbox_poly)
}
Instead of reading the function let us try to give the function the input bb, where
bb <- osmdata::getbb('Copenhagen') and then simply inspect the output:
dodgr:::process_bbox(bb)
This will result in the output:
$bbox
x y
min 12.39407 55.51072
max 12.74607 55.86272
$bbox_poly
NULL
which is a list where $bbox_poly has been added but set to NULL.
So this answers the question: what does the call 'dodgr_streetnet(bb)' get from OSM
in order to get the street net, hence what OSM data is sufficient to define the street net.
The only thing to notice is the 'expand' argument which expands the bounding box. Other than
that it is simply the 'net$osm_lines', hence the linestrings of an OSM call where the
'feature(key = "highway")' is retrieved.