Git Product home page Git Product logo

gullies's Introduction

Gullies

Maps of routes draining into a common sink from all over a road network.

Prints of these images are available on my society6 page: https://society6.com/krithin

US roads draining into NYC

Inspired by moovel labs' Roads to Rome and Topi Tjukanov's Roads of America.

Usage

Prerequisites

In general, you'll need an OSM snapshot to process, an OSRM instance running against that same snapshot, and some intial set of destination points to route to (such as from one of the files in inputdata/ or as generated by getlocations.py).

In more detail:

  1. Grab an OSM extract for a region you're interested in. These are available from http://download.geofabrik.de/ or other sources listed in the OSM wiki.

    curl -O http://download.geofabrik.de/north-america/us/new-york-latest.osm.pbf

    If no predefined OSM extract matches the exact region you're interested in, you can cut one out of a larger extract with osmium-tool - see the osmium docs for how to use osmium getid followed by osmium extract to get an extract for a region bounded by an existing OSM relation.

  2. Get OSRM.

    As of August 2022 the instructions to build OSRM from source do not work due to dependency issues, so you'll have to run a prebuilt OSRM Docker image. We'll use this in the next two steps.

    docker pull osrm/osrm-backend
  3. Preprocess the OSM snapshot you downloaded earlier so OSRM can route against it. Assuming you're running this in the same directory where you downloaded the OSM snapshot earlier:

    # Create a scratch directory, because OSRM will produce *lots* of processed files from the input you give it.
    
    mkdir scratch && cd scratch
    mv ../new-york-latest.osm.pbf ./ny.osm.pbf
    
    docker run -t -v "$PWD:/data" osrm/osrm-backend osrm-extract -p /opt/car.lua /data/ny.osm.pbf
    docker run -t -v "$PWD:/data" osrm/osrm-backend osrm-partition /data/ny.osrm
    docker run -t -v "$PWD:/data" osrm/osrm-backend osrm-customize /data/ny.osrm

    Warning: This step might take a lot of memory. osrm-extract for a map of the whole of the US peaked at 46 GiB of RAM used.

  4. Start the OSRM server:

    docker run -t -i -p 5000:5000 -v "$PWD:/data" osrm/osrm-backend osrm-routed --algorithm mld /data/ny.osrm

    Leave this server running; we'll send it some requests in later steps.

Generating images

Get started by cloning this repo:

git clone https://github.com/krithin/gullies.git
cd gullies
  1. Install dependencies

    python -m venv venv
    source venv/bin/activate # (or the appropriate command for your shell)
    pip install -U pip && pip install -r requirements.txt
  2. Generate a set of destination points to route to:

    python getlocations.py scratch/ny.osm.pbf 10000 > nylocations.csv

    As an alternative to using getlocations.py to generate the locations, you can instead use one of the census datasets included in inputdata/.

  3. Generate routes to those points:

    cat nylocations.csv | python getroutes.py http://localhost:5000 > nyroutes.txt
  4. Collate the resulting routes:

    cat nyroutes.txt | python collatesegments.py scratch/ny.osm.pbf > nyroutescollated.txt
  5. Simplify the collated routes:

    cat nyroutescollated.txt | python simplifysegments.py 4 > nyroutessimplified.txt

    If you're running this process on a smallish region, say a single city, you can try skipping this step and feeding routescollated.txt directly into the plotting step below.

  6. And produce a plot:

    cat nyroutessimplified.txt | python plotmatplotlib.py new-york.png

    If you run this last step on a server machine without X or some other graphical interface installed, you might encounter a known Matplotlib issue for which the solution is to explicitly specify a plotting backend

Gallery

Australia from Sydney Australia roads

Roads from all over New York state, draining into New York City: New York roads

Singapore Singapore

Roads from all over the contiguous United States, draining into the mouth of the Mississippi at New Orleans: New Orleans roads

gullies's People

Contributors

krithin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

gullies's Issues

Use a real command line args library

like argparse or something, instead of reading out argv values by hand.

That will let us support nice things like overrideable default values for e.g. the lat-long coords of the point that all the routes drain into.

Remove the MAX_ROUTE_COUNT limit set in getroutes.py

That limit was put in place back when I was trying to use plotly to generate the output.

Now we're instead doing some custom line simplification in plotmatplotlib.py (and also using matplotlib instead of plotly js to do the actual rendering) it's no longer necessary, and in particular it confuses things when using the new getlocations.py script to generate a custom number of destination locations from an OSM snapshot.

Performance improvements needed for the line simplification step

When rendering an image with a huge number of destination points (>10k) the line simplification step starts to become very slow (> 1h for routes to 20k points)

There's an obvious quadratic step in there that could be sped up by shrinking the relevant bits of the mergeable_segments set. Ways to do that include:

  1. Using a pair of kd trees to store segments - indexed by both start and end points - and then using them to find the nearest neighbours of the segment endpoints

  2. Splitting out the mergeable_segments set by segment weight - that could help if the weights are well distributed. I suspect that a majority of the segments are going to be of weight 1, however, so this may not buy is very much.

Autodetect a good aspect ratio for the output plot when plotting with matplotlib

Right now we explicitly set an image size that results in an image with a 4:3 aspect ratio. This happens to work out okay for plots of the continental US or NY state, but for plotting other things we should probably figure out a good aspect ratio for the data we're plotting.

It's fine to start off by assuming that we'll want an equirectangular projection, so x and y coordinates on the plot map linearly to degrees of longitude and latitude; eventually that might change if we want to support 'real' map projections.

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.