Giter VIP home page Giter VIP logo

Comments (6)

chris31415926535 avatar chris31415926535 commented on September 2, 2024

That sounds like a great use-case. I haven't used the exclude_polygons parameter, so I'll take a look. Can you post what you've tried?

from valhallr.

chris31415926535 avatar chris31415926535 commented on September 2, 2024

@jdsher I've pushed an update to GitHub that adds an option exclude_polygons option to route(), od_matrix(), and sources_to_targets(). You pass it either a tibble or a list of tibbles with lat and lon columns. Can you install the dev version and see if this works for you?

In short, exclude_polygons wasn't a costing option--it was its own high-level option, and needed some specific data parsing.

Here's a reprex (if you have OSM map tiles for Ontario, and if your Valhalla instance is running on IP 192.168.2.39) that shows some sample trips across Ottawa. The first case has no restrictions, the second restricts a section of the major crosstown artery, and the third also restricts the most direct downtown route. The Leaflet maps show the route winding between the polygons, as expected.

library(tidyverse)
library(valhallr)
library(leaflet)

# set up start/stop points (university of ottawa and a sports arena)
ottawa_points <- valhallr::test_data() %>%
  filter(lat > 45, lon > -78)

# set up polygons (one blocking major artery, another blocking downtown major street)
poly1 <- tibble::tribble(~lat, ~lon,
                         45.406729, -75.703046,
                         45.402346, -75.700519,
                         45.407185, -75.686590,
                         45.410834, -75.692833)

poly2 <- tibble::tribble(~lat, ~lon,
                         45.424620, -75.696708,
                         45.419283, -75.709161,
                         45.416166, -75.701505,
                         45.420895, -75.692013)

# put them in a list to pass multiple at once
e_polys <- list(poly1, poly2)

########### route()
# no exclusion
route_0 <- route(from = ottawa_points[1,],
                to = ottawa_points[3,],
                hostname = "192.168.2.39")

# 1 polygon passed as tibble
route_1 <- route(from = ottawa_points[1,],
                to = ottawa_points[3,],
                hostname = "192.168.2.39",
                exclude_polygons = exclude_poly_small)

# 2 polygons passed as list
route_2 <- route(from = ottawa_points[1,],
                to = ottawa_points[3,],
                hostname = "192.168.2.39",
                exclude_polygons = e_polys)

# inspect results
map_trip(route_0)

map_trip(route_1) %>%
  addPolygons(data = exclude_poly_small, lat = ~lat, lng = ~lon)

map_trip(route_2) %>%
  addPolygons(data = exclude_poly_small, lat = ~lat, lng = ~lon) %>%
  addPolygons(data = poly_small_2, lat = ~lat, lng = ~lon)

########### Also testing with sources_to_targets

st_0 <- sources_to_targets(froms = ottawa_points[1,],
                   tos = ottawa_points[3,],
                   hostname = "192.168.2.39")

st_1 <- sources_to_targets(froms = ottawa_points[1,],
                                   tos = ottawa_points[3,],
                                   hostname = "192.168.2.39",
                                   exclude_polygons = poly1)

st_2 <- sources_to_targets(froms = ottawa_points[1,],
                                    tos = ottawa_points[3,],
                                    hostname = "192.168.2.39",
                                   exclude_polygons = e_polys)

####### Testing with od_table
# no polygons
od_0 <- od_table(froms = ottawa_points[1,],
         from_id_col = "name",
         tos = ottawa_points[3,],
         to_id_col= "name",
         hostname = "192.168.2.39")

# 1 polygon passed as tibble
od_1 <- od_table(froms = ottawa_points[1,],
         from_id_col = "name",
         tos = ottawa_points[3,],
         to_id_col= "name",
         exclude_polygons = poly1,
         hostname = "192.168.2.39")

# 2 polygons passed as list
od_2 <- od_table(froms = ottawa_points[1,],
         from_id_col = "name",
         tos = ottawa_points[3,],
         to_id_col= "name",
         exclude_polygons = e_polys,
         hostname = "192.168.2.39")

### Make summary table
results <- tibble(polygons = 0:2, 
                  route = c(route_0$summary$length, route_1$summary$length, route_2$summary$length),
                  od_matrix = c(od_0$distance, od_1$distance, od_2$distance),
                  sources_to_targets = c(st_0$distance, st_1$distance, st_2$distance)
)

And the results look like this:

polygons route od_matrix sources_to_targets
0 27.157 27.157 27.157
1 26.858 26.858 26.858
2 27.844 27.844 27.844

The table shows the results match across all 3 functions, and since we've verified the route() function visually this looks good to me.

EDIT TO ADD: I just realized I could copy/paste images.

Downtown route, no restrictions:
image

Downtown route, one restriction:
image

Downtown route, two restrictions:
image

from valhallr.

jdsher avatar jdsher commented on September 2, 2024

Wow, that was fast! I will test the new dev version this week and report back but that seems to be a much simpler method at first glance, thankfully.

I was feeding the arguments like so:

inundation_dists <- sources_to_targets(froms = orig,
                                       tos = dest,
                                       minimum_reachability = 50,
                                       hostname = host,
                                       port = port,
                                       costing_options = list('avoid_polygons' = '[[[-122.443993,47.220645],[-122.443993,47.289334],[-122.318552,47.289334],[-122.318552,47.220645],[-122.443993,47.220645]]]'))

So, small wonder it wasn't working in any format I suppose. Do you happen to know if the call will fail if I feed the argument a multipolygon or list of multipolygons? The Valhalla API docs seem to suggest that might be the case...

from valhallr.

chris31415926535 avatar chris31415926535 commented on September 2, 2024

Re. multipolygons, it should be possible with some wrangling. Valhalla only supports lat/lon numbers, not shapefiles, so at present you need to feed the valhallr functions tibbles with lat and lon columns. I don't know if there's an elegant function in sf to do this, but a combination of unlist(), matrix(), and tibble() will probably get you there in the end.

So if you get the polygons/multipolygons into that format, you can pass od_table() a list() of tibbles like I did above in the example with 2 polygons.

Note that I got an error from Valhalla when I used a big polygon (circumference too long, error 167 I think)--there may be internal Valhalla settings you can adjust.

Let me know how it goes!

from valhallr.

jdsher avatar jdsher commented on September 2, 2024

I believe I got it working at least with a small singular polygon, but you are right: that perimeter limitation is a real drag. I've tried chopping up my large irregular multipolygons with st_intersection() on a regular grid and then group_by %>% group_split(), but the results don't seem quite right. Will maybe try some other methods for now, but thank you again for the quick amendments to the code!

from valhallr.

chris31415926535 avatar chris31415926535 commented on September 2, 2024

It looks like you can adjust the max polygon size if you have control over your Valhalla instance. In valhalla.json (link to default) there's an entry called max_exclude_polygons_length that's by default set to 10000. Setting it to 99999999999999 (or something very big) might let you use your original polygons.

Either way good luck! I'm marking this as closed since that's now a Valhalla issue not related to the valhallr package.

If you make something neat please cite the package, and I'd love to see any public or published results.

from valhallr.

Related Issues (5)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.