-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Improve pointlist output for isochrone (/spt endpoint) #1577
Conversation
Here is an example on how to visualize data with deckgl and R library(magrittr)
library(jsonlite)
library(deckgl)
lat <- 51.33399
lng <- 9.438801
# Get data
apiCall <- paste0(
"http://localhost:8989/isochrone?point=", lat, ",", lng,
"&time_limit=600&result=pointlist&pointlist_ext_header=prev_longitude,prev_latitude"
)
resp <- httr::GET(apiCall) %>%
httr::content("text") %>%
fromJSON(flatten = TRUE)
# Prepare data
tbl <- resp$items %>%
set_colnames(resp$header) %>%
tibble::as_tibble() %>%
subset(time != 0)
# Plot data
properties <- list(
getStrokeWidth = 3,
getSourcePosition = get_position("prev_latitude", "prev_longitude"),
getTargetPosition = get_position("latitude", "longitude"),
getTooltip = get_property("distance")
)
# Create deckgl widget
deck <- deckgl(latitude = lat, longitude = lng, pickingRadius = 2)
deck_black <- deckgl(
latitude = lat,
longitude = lng,
pickingRadius = 2,
style = list(background = "black")
)
# Arc layer
deck %>%
add_arc_layer(data = tbl, properties = properties)
# Create colors for line layer
pal <- leaflet::colorBin(tbl$distance)
tbl$color <- pal(tbl$distance)
# Line layer
deck_black %>%
add_line_layer(
data = tbl, properties = properties,
getColor = get_color_to_rgb_array("color")
) |
Thanks a lot!
Here it says something about the type:
|
Ups, using a different starting point fixed this for me. E.g. for Berlin: lat <- 52.509535
lng <- 13.40332 |
Nice, got some streetnetwork as output -> looks funny those curved streets. Thanks @crazycapivara! For the leaflet part I had to do:
But then I get:
|
Sorry, I posted an old version of the script, will send a working update. |
Start a container with Berlin data set: docker run -p 8989:8989 -d --name gh-berlin crazycapivara/graphhopper:ext_pointlist Run some visualizations wit R and deckgl: library(magrittr)
library(jsonlite)
library(deckgl)
lat <- 52.517057
lng <- 13.3992
# Get data
apiCall <- paste0(
"http://localhost:8989/isochrone?point=", lat, ",", lng,
"&time_limit=600&result=pointlist&pointlist_ext_header=prev_longitude,prev_latitude"
)
resp <- httr::GET(apiCall) %>%
httr::content("text") %>%
fromJSON(flatten = TRUE)
# Prepare data
tbl <- resp$items %>%
set_colnames(resp$header) %>%
tibble::as_tibble() %>%
subset(time != 0)
# Plot data
properties <- list(
getStrokeWidth = 3,
getSourcePosition = get_position("prev_latitude", "prev_longitude"),
getTargetPosition = get_position("latitude", "longitude"),
getTooltip = get_property("distance")
)
# Create deckgl widget
deck <- deckgl(latitude = lat, longitude = lng, pickingRadius = 2)
# Arc layer
deck %>%
add_arc_layer(data = tbl, properties = properties)
# Create colors for line layer
pal <- leaflet::colorBin("RdYlBu", tbl$distance)
tbl$color <- pal(tbl$distance)
# Create a deckgl widget with black background
deck_black <- deckgl(
latitude = lat,
longitude = lng,
pickingRadius = 2,
style = list(background = "black")
)
# Line layer
deck_black %>%
add_line_layer(
data = tbl, properties = properties,
getColor = get_color_to_rgb_array("color")
)
# Arc and line layer
deck %>%
add_data(tbl) %>%
add_arc_layer(data = get_data(), properties = properties) %>%
add_line_layer(
data = get_data(), properties = properties,
getColor = get_color_to_rgb_array("color")
) If you have valid mapbox api key you can add a basemap as well: deck %>%
... %>%
add_mapbox_basemap(api_key) |
Maybe we could add an
would return points where Furthermore, at the moment, the request returns a lot of points above the given |
Why would this help? To print parts of the result before everything arrived? The problem is that we would then have to remember the state somehow (cache) which I would like to avoid if possible.
Ah, yes. This is ugly and I can fix it here: https://github.com/graphhopper/graphhopper/blob/master/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/Isochrone.java#L94 |
Yes, this was one idea and to maybe allow larger |
Hmmh ... if we allow caching then we could return the isochrone-shortest-path-tree via the MVT endpoint (#1572), which would save us from a non-standard format. |
Ups, Nope, I would like to keep the format. It is perfect for a lot of use cases. I just connected the API to a postgis container, so that you can query the roads with |
Ah, ok. Thanks for the feedback!
This sounds great! |
@karussell Did you just invent CSV-over-JSON? ,-) |
Lol. I'm pretty sure this is already existent :D ... how do you like it ;) ? |
I like it! But maybe consider using CSV right away for this
@crazycapivara Any thoughts? (No need to decide, since this can be easily added as a second mediatype on the same endpoint. But just in case you're immediately convinced, we could switch.) |
For now I would like to add it as a second mediatype and compare both endpoints for my use cases. |
A related info: I just stumbled over https://www.interline.io/blog/geojsonl-extracts/ that mentions GeoJSON Line and also the following streamable JSON stuff: |
case "latitude": | ||
list.add(label.adjCoordinate.y); | ||
break; | ||
case "prev_longitude": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please add options to export previous node's time and distance, so we can get values in both ends of segment without a lookup join?
case "prev_distance":
list.add(Optional.ofNullable(index.get(label.baseNodeId)).map(i -> i.distance).orElse(0D));
break;
case "prev_time":
list.add(Optional.ofNullable(index.get(label.baseNodeId)).map(i -> i.time).orElse(0L));
break;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have an example why this would be useful for you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Builiding a constrained Delaunay triangulation and clipping it in PostGIS, I need to have two-point segments to feed into function. Here's more detail: https://www.patreon.com/posts/isochrones-are-20933638
This thing is useful for us. Format is fine, the only thing is - can we have travel times and distances in both ends of a segment, and export as such? Snippet attached. |
… distance with test; changed unit of time to seconds to save some bandwidth
Have added it. Please note that I have changed the time to seconds to reduce bandwidth a bit and ms does not make much sense - or is there a good reason to keep milliseconds? |
Ok, have now converted this endpoint into returning CSV. Additionally as dropwizard makes this very easy, the CSV is already streamed, i.e. even for large shortest path trees the client gets something to do right after the first nodes are traversed :) |
Oh, this means we can already fetch country-sized (or even continental-sized) shortest path trees without any memory problems. The client just waits a bit for the data transmission and sees the exploration in (near) real time. |
Country-sized SPTs are definitely doable with this endpoint: The JavaScript code snippet is here. But with leaflet ( Would be curious if the deck.gl for R work from @crazycapivara is able to handle that somehow :) |
Nice!
Yes. I think this would also overwhelm e.g. QGis. Layers with that many objects are a new thing. |
lat <- 52.321911
lng <- 10.393066
time_limit <- 7200
api_call <- paste0(
"http://localhost:8989/spt?point=",
lat, ",", lng,
"&time_limit=", time_limit,
"&columns=prev_longitude,prev_latitude,longitude,latitude,time"
)
dt <- data.table::fread(api_call, na.strings = "null") %>%
na.omit()
pal <- leaflet::colorBin("RdYlBu", dt$time)
dt$color <- pal(dt$time)
library(deckgl)
deckgl(
latitude = lat,
longitude = lng,
style = list(background = "black")
) %>%
add_line_layer(
data = dt,
getStrokeWidth = 3,
getSourcePosition = get_position("prev_latitude", "prev_longitude"),
getTargetPosition = get_position("latitude", "longitude"),
getTooltip = get_property("time"),
getColor = get_color_to_rgb_array("color")
) In this case it takes some time until the layer is rendered because first all data is downloaded and then passed to the widget (from R to json). But in the end when it shows up zooming is smooth. I need to add a csv-reader on javascript side to speed up loading. |
Love it! @karussell What do you think about this (from above):
I think that would make it more flexible (can also drop columns) and easier do document: "Specify the columns you want" instead of "specify the columns in addition to the default columns that you want". And I think two fewer lines of code. ;-) |
Yes, this was a good idea! And if I did not misunderstand it, then this is already done :D ? BTW: in some days or weeks we'll have #1548 i.e. information like road_class, max_speed, tunnel, toll etc then we can make this available here too. Furthermore we can allow to specify a filter if only main roads are required (or a smaller+faster output) or visualizing tunnels and bridges is required for risk analysis etc |
@karussell That sounds great, then we can also use this information for the styling. |
You can now request additional information like road_class (highway tag) and road_environment (tunnel, bridge, ...) and more. Do the following steps:
|
@michaz do you want to review this again? Especially as you were asking:
|
If no opposing opinion I'll merge this today |
I haven't run it but reading through description looks good. |
Ok. If there are problems we can easily create new issues :) |
Update: this is now a pure CSV endpoint:
where you can add more columns like
prev_latitude,prev_longitude
or path details likeroad_class
The client code example snippet is here and also see the deck.gl for R tool.
Original text:
The pointlist option was not really useful as it came with just the coordinates.
Have now created a compact but extendable JSON format(read update).Thx @crazycapivara for the valuable discussion! He created a deck.gl for R tool and future versions will likely work with graphhopper. See also the work here with deck.gl and a forked graphhopper (this should be possible after this PR without forking). See also related #1572.
TODOs:
List<IsoLabelWithCoordinates>
in IsochroneResource to make Isochrone method more powerful?allow paging through the pointlist result with some caching?later