Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r5r 0.5-0 new feature: find snap points #168

Closed
mvpsaraiva opened this issue May 11, 2021 · 12 comments · Fixed by #175
Closed

r5r 0.5-0 new feature: find snap points #168

mvpsaraiva opened this issue May 11, 2021 · 12 comments · Fixed by #175
Labels

Comments

@mvpsaraiva
Copy link
Collaborator

mvpsaraiva commented May 11, 2021

Two new functions are available in the dev version of r5r jar: getGrid() and findSnapPoints().

getGrid() uses R5 functionality to generate a grid of regularly spaced cells in the Web Mercator projection, at a given zoom level.

findSnapPoints() is useful to analyse the actual origins and destinations of trips on the road network. Since R5's link radius is set to 1.6km, the actual linkage point can be located quite far away from the original location.

To install the development version of r5r, use:

utils::remove.packages('r5r')
devtools::install_github("ipeaGIT/r5r", subdir = "r-package", ref = "dev")

Reproducible example of getGrid() and findSnapPoints():

library(r5r)

# initialize r5r
data_path <- system.file("extdata/poa", package = "r5r")
r5r_core <- setup_r5(data_path, verbose = FALSE)

# get regular grid at resolution 8
grid_df <- r5r_core$getGrid(8L)
grid_df <- jdx::convertToR(grid_df)

# snap grid to street network
snap_df <- r5r_core$findSnapPoints(grid_df$id, grid_df$lat, grid_df$lon, "CAR")
snap_df <- jdx::convertToR(snap_df)

mv1 <- mapview::mapview(snap_df, xcol="lon", ycol="lat", crs=4326)
mv2 <- mapview::mapview(snap_df, xcol="snap_lon", ycol="snap_lat", zcol="found", crs=4326)

leafsync::sync(mv1, mv2)

The result will be the following:

Screenshot 2021-05-11 at 15 56 21

@rafapereirabr
Copy link
Member

Thank you, @mvpsaraiva . A few quick questions:

  • what does resolution 8 means in terms of Km?
    • Are these resolution levels defined internally in R5?
    • How resolutions are there?
  • Could the user pass a group of points (say, centroids of census tracts) to the findSnapPoints() function?

@mvpsaraiva
Copy link
Collaborator Author

mvpsaraiva commented May 12, 2021

Good questions, @rafapereirabr

Resolution 8 means approximately 600 m, on the equator. This entire grid-building functionality is provided natively by R5, so there's no need to add any dependency to r5r. This resolution (or zoom level) scheme is used by many web mapping tools that provide maps as tiles, such as OSM, Google Maps, Mapbox...

The full list of resolutions, is below:

Level # Tiles Tile width (° of longitudes) m / pixel (on Equator) ~ Scale (on screen) Examples of areas to represent
0 1 360 156 412 1:500 million whole world
1 4 180 78 206 1:250 million
2 16 90 39 103 1:150 million subcontinental area
3 64 45 19 551 1:70 million largest country
4 256 22.5 9 776 1:35 million
5 1 024 11.25 4 888 1:15 million large African country
6 4 096 5.625 2 444 1:10 million large European country
7 16 384 2.813 1 222 1:4 million small country, US state
8 65 536 1.406 610.984 1:2 million
9 262 144 0.703 305.492 1:1 million wide area, large metropolitan area
10 1 048 576 0.352 152.746 1:500 thousand metropolitan area
11 4 194 304 0.176 76.373 1:250 thousand city
12 16 777 216 0.088 38.187 1:150 thousand town, or city district
13 67 108 864 0.044 19.093 1:70 thousand village, or suburb
14 268 435 456 0.022 9.547 1:35 thousand
15 1 073 741 824 0.011 4.773 1:15 thousand small road
16 4 294 967 296 0.005 2.387 1:8 thousand street
17 17 179 869 184 0.003 1.193 1:4 thousand block, park, addresses
18 68 719 476 736 0.001 0.596 1:2 thousand some buildings, trees
19 274 877 906 944 0.0005 0.298 1:1 thousand local highway and crossing details
20 1 099 511 627 776 0.00025 0.149 1:5 hundred A mid-sized building

Could the user pass a group of points (say, centroids of census tracts) to the findSnapPoints() function?

Yes, getGrid() returns a data.frame with id, lat, and lon columns, and findSnapPoints() takes exactly those arguments plus a transport mode ("WALK", "BICYCLE", or "CAR"), so it's easy to use them in combination. But findSnapPoints() can take any set of points, independently of their spatial arrangement.

@rafapereirabr
Copy link
Member

Great. The only thing we need to do then is to create an R function around them, allowing the uset to pass a POINT sf to findSnapPoints()

@mvpsaraiva
Copy link
Collaborator Author

What do you think are good names for the wrap functions?

  • get_grid(), build_grid(), generate_grid() ...
  • find_snap_points(), check_snap_points() ...

@luukvdmeer
Copy link

Does R5 include the "trip" from the given origin and destination points to their respective snapped points in the travel time estimation, assuming walking speed and as-the-crow-flies distance? That is what I get from their documentation, but I am not entirely sure.

For analyses with transit disabled, the total travel time from an origin to a destination includes time spent:
.. Walking from the selected origin to the nearest point on the street network
..Traveling to the point on the street network nearest to the destination, using the selected direct mode (walk, bicycle, or car)
..Walking from the street network to the destination

For analyses with transit enabled, the total travel time from an origin to a destination includes time spent:
..Walking from the selected origin to the nearest point on the street network
..Reaching nearby transit stops via the street network, using the selected access mode (walk, bicycle, or car)
..Waiting to board transit (initially and at transfers)
..Riding in transit vehicles
..Walking via the street network between transit stops for transfers
..Traveling from transit stops to the point on the street network nearest to the destination, using the selected egress mode
..Walking from that point on the street network the directly to the center of the grid cell

@mvpsaraiva
Copy link
Collaborator Author

mvpsaraiva commented May 17, 2021

Hi @luukvdmeer. Indeed, you are correct: those off-street segments from origin/destination points to the nearest street edges are taken into account and their travel times (as you guessed, considering walking speed and as-the-crow-flies distance) are added to the calculated on-road travel times. I've confirmed this by looking again at R5's source code.

Thanks for pointing this out and providing the link to Conveyal's documentation. I've did a quick test, and you can se the effects are quite significant. In the screenshot below, travel_times_or is the travel time from the original OD coordinates, and travel_times_sn is the travel time from/to the snapped points (thus dropping off-road segments):

Screenshot 2021-05-17 at 14 05 44

@mvpsaraiva
Copy link
Collaborator Author

getGrid() can return cells' as polygons as well, instead of just the centroid coordinates, which can be useful for mapping.

Screenshot 2021-05-21 at 08 10 19

@mvpsaraiva
Copy link
Collaborator Author

Since there are many options to easily generate regular grids outside r5r, most notably using the sf package, we've decided not to expose the getGrid() function. This issue will focus on findSnapPoints().

@mvpsaraiva mvpsaraiva changed the title r5r 0.5-0 new features: regular grid and check snap points r5r 0.5-0 new feature: find snap points May 21, 2021
@mvpsaraiva
Copy link
Collaborator Author

Added the find_snap() R wrapper function around Java's findSnapPoints() 0cbc443

Now the user can pass a data.frame containing id, lat, and lon columns to find_snap() to obtain a new data.frame with the snapped coordinate locations as well as the distance from the original coordinates:

Screenshot 2021-05-21 at 17 24 00

R5 tries to link points to the street network in two rounds, first using a search radius of 300m, then expanding the radius to 1.6km if the first round is unsuccessful. Points that aren't linked to the street network after those two rounds are returned with NA coordinates and found = FALSE.

@mvpsaraiva
Copy link
Collaborator Author

I think this function is complete, including documentation and tests. Shall we close this issue now?

@rafapereirabr
Copy link
Member

I agree this is complete. The issue will be automatically closed when we merge the dev branch into the master

@rafapereirabr
Copy link
Member

Setting this issue as priority, to be incorporated in the next package release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants