Skip to content

Commit

Permalink
docs api samples
Browse files Browse the repository at this point in the history
  • Loading branch information
pszufe committed Feb 10, 2019
1 parent d6d0490 commit 500652a
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 69 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# OpenStreetMapX.jl

* Package for spatial analysis, simulation and vizualization of Open Street Map data
* The plotting functionality is provided via a separate package [`OpenStreetMapXPlot.jl`](https://github.com/pszufe/OpenStreetMapXPlot.jl)

The goal of this package is to provide a backbone for multi-agent simulation of cities.


The goal of this package is to provide a backbone for multi-agent simulation of cities. The prototype simulator has been implemented in [`OpenStreetMapXSim.jl`](https://github.com/pszufe/OpenStreetMapXSim.jl)).

| **Documentation** | **Build Status** |
|---------------|--------------|
Expand Down Expand Up @@ -38,12 +41,12 @@ sudo apt install libexpat-dev

```julia
using OpenStreetMapX
map_data = OpenStreetMapX.get_map_data("/home/ubuntu/", "mymap.osm");
map_data = get_map_data("/home/ubuntu/mymap.osm");

println("The map contains $(length(map_data.nodes)) nodes")
```

See the `samples` directory for a more complete example.
See the [samples](https://github.com/pszufe/OpenStreetMapX.jl/tree/master/samples) directory for a more complete example and have a look at [`OpenStreetMapXPlot.jl`](https://github.com/pszufe/OpenStreetMapXPlot.jl) for a route plotting.

## Obtaining map data

Expand All @@ -69,10 +72,11 @@ In order to obtain the `*.osm` file follow the steps below:
Compared to the original package major changes include:

- `LightGraphs.jl` is used for map data storage
- Several changes with routing algorithm (currently finding a route in a 1 million people city takes around 250ms)
- Several changes with routing algorithm (currently finding a route in a 1 million people city takes around 150ms)
- Added support for using Google Maps API for routing
- Data structure adjustment to make the library more suitable to run simulations of cities.
- `Plots.jl` with GR is used as backend for map vizualization (via a separate package [`OpenStreetMapXPlot.jl`](https://github.com/pszufe/OpenStreetMapXPlot.jl))

The creation of this source code was partially financed by research project supported by the Ontario Centres of Excellence ("OCE") under Voucher for Innovation and Productivity (VIP) program, OCE Project Number: 30293, project name: "Agent-based simulation modelling of out-of-home advertising viewing opportunity conducted in cooperation with Environics Analytics of Toronto, Canada. </sup>
The creation of some parts of this source code was partially financed by research project supported by the Ontario Centres of Excellence ("OCE") under Voucher for Innovation and Productivity (VIP) program, OCE Project Number: 30293, project name: "Agent-based simulation modelling of out-of-home advertising viewing opportunity conducted in cooperation with Environics Analytics of Toronto, Canada. </sup>


2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

Documentation for OpenStreetMapX.jl

For details please go to the [Reference](https://pszufe.github.io/OpenStreetMapX/latest/reference/) section.
For details please go to the [Reference](https://pszufe.github.io/OpenStreetMapX.jl/latest/reference/) section.
10 changes: 10 additions & 0 deletions docs/src/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,14 @@ shortest_route(::MapData, ::Int, ::Int)
shortest_route(::MapData, ::Int, ::Int, ::Int)
fastest_route(::MapData, ::Int, ::Int, ::Dict{Int,Float64})
fastest_route(::MapData, ::Int, ::Int, ::Int, ::Dict{Int,Float64})
```

Google API routing
------------------
```@docs
get_google_route(::Int,::Int,::MapData,::String; ::Dict{Symbol,String})
get_google_route(::Int,::Int,::Int,::MapData,::String; ::Dict{Symbol,String})
node_to_string(::Int,::MapData)
googleAPI_parameters
```
26 changes: 9 additions & 17 deletions samples/routing.jl
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
using OpenStreetMapX

mapfile = "mymap.osm";
mapfile = "reno_east3.osm"; # This file can be found in test/data folder
datapath = "/home/ubuntu/";
map_data = OpenStreetMapX.get_map_data(datapath, mapfile);
map_data = get_map_data(datapath, mapfile,use_cache=false);

function generate_point_in_bounds(map_data::OpenStreetMapX.MapData)
boundaries = map_data.bounds
(rand() * (boundaries.max_y - boundaries.min_y) + boundaries.min_y,
rand() * (boundaries.max_x - boundaries.min_x) + boundaries.min_x)
end

function point_to_nodes(point::Tuple{Float64,Float64}, map_data::OpenStreetMapX.MapData)
point = OpenStreetMapX.LLA(point[1],point[2])
point = OpenStreetMapX.nearest_node(map_data.nodes,OpenStreetMapX.ENU(point, map_data.bounds), map_data.network)
end
using Random
Random.seed!(0);

origin = generate_point_in_bounds(map_data);
destination = generate_point_in_bounds(map_data);

pointA = point_to_nodes(origin, map_data)
pointB = point_to_nodes(destination, map_data)

shortest_route, shortest_distance, shortest_time = OpenStreetMapX.shortest_route(map_data.network, pointA, pointB)
fastest_route, fastest_distance, fastest_time = OpenStreetMapX.fastest_route(map_data.network, pointA, pointB)
shortest_route1, shortest_distance1, shortest_time1 = shortest_route(map_data, pointA, pointB)
fastest_route1, fastest_distance1, fastest_time1 = fastest_route(map_data, pointA, pointB)

println("shortest_route nodes: ",shortest_route)
println("fastest route nodes: ",fastest_route)
println("shortest_route nodes: ",shortest_route1)
println("fastest route nodes: ",fastest_route1)

### Create this file if you want to test routing with Google API
### The file should only contain your Google API key
google_api_file = joinpath(datapath,"googleapi.key")

if isfile(google_api_file)
google_api_key = readlines(google_api_file)[1]
google_route = OpenStreetMapX.get_google_route(pointA, pointB,map_data,google_api_key)[1]
google_route = get_google_route(pointA, pointB,map_data,google_api_key)[1]
println("Google API route nodes : ",google_route)
end
51 changes: 24 additions & 27 deletions src/google_routing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ const googleAPI_parameters = Dict{Symbol,String}(


"""
Convert node coordinates (stored in ENU system) to string with LLA system coordinates
node_to_string(node_id::Int,map_data::MapData)
**Arguments**
* `node_id` : unique node id
* `map_data` : `OpenStreetMapX.MapData` object
Convert node coordinates (stored in ENU system in the `nodes` field of `map_data`)
identified by `node_id` to string with LLA system coordinates
"""
function node_to_string(node_id::Int,map_data::OpenStreetMapX.MapData)
coords = OpenStreetMapX.LLA(map_data.nodes[node_id],map_data.bounds)
function node_to_string(node_id::Int,map_data::MapData)
coords = LLA(map_data.nodes[node_id],map_data.bounds)
return string(coords.lat,",",coords.lon)
end

Expand Down Expand Up @@ -119,9 +118,9 @@ Match Google route with vertices of map network
"""
function google_route_to_network(route::Array{Tuple{Float64,Float64},1},map_data::OpenStreetMapX.MapData)
route = [OpenStreetMapX.ENU(OpenStreetMapX.LLA(coords[1], coords[2]),map_data.bounds) for coords in route]
res = [OpenStreetMapX.nearest_node(map_data, route[1])]
function google_route_to_network(route::Array{Tuple{Float64,Float64},1},map_data::MapData)
route = [ENU(LLA(coords[1], coords[2]),map_data.bounds) for coords in route]
res = [nearest_node(map_data, route[1])]
index = 2
for i = 2:length(route)
node = OpenStreetMapX.nearest_node(map_data, route[i])
Expand All @@ -134,20 +133,19 @@ function google_route_to_network(route::Array{Tuple{Float64,Float64},1},map_data
end

"""
Get route based on Google Distances API with three points (origin, destination, waypoint between)
get_google_route(origin::Int, destination::Int, waypoint::Int,
map_data:MapData, googleapi_key::String;
googleapi_parameters::Dict{Symbol,String} = googleAPI_parameters)
**Arguments**
* `origin` : unique node id
* `destination` : unique node id
* `waypoint` : unique node id
* `map_data` : `OpenStreetMapX.MapData;` object
* `googleapi_key`: Google API key
* `googleapi_parameters` : dictionary with assumptions about Google Distances API request
Get route from to based on Google Distances API with three points
(`origin`, `destination` and `waypoint` between)
on map `map_data` using Google API key `googleapi_key` with optional
Google Distances API request parameters `googleapi_parameters`.
"""
function get_google_route(origin::Int,destination::Int,waypoint::Int,
map_data::OpenStreetMapX.OpenStreetMapX.MapData, googleapi_key::String;
googleapi_parameters::Dict{Symbol,String} = OpenStreetMapX.googleAPI_parameters)
googleapi_parameters::Dict{Symbol,String} = googleAPI_parameters)
url = OpenStreetMapX.get_googleapi_url(origin, destination, waypoint,map_data,googleapi_key,googleapi_parameters = googleapi_parameters)
status, routes = OpenStreetMapX.parse_google_url(url)
if status == "OK"
Expand All @@ -172,19 +170,18 @@ function get_google_route(origin::Int,destination::Int,waypoint::Int,
end

"""
Get route based on Google Distances API with two points (origin and destination)
get_google_route(origin::Int, destination::Int,
map_data:MapData, googleapi_key::String;
googleapi_parameters::Dict{Symbol,String} = googleAPI_parameters)
**Arguments**
* `origin` : unique node id
* `destination` : unique node id
* `map_data` : `OpenStreetMapX.MapData;` object
* `googleapi_key`: Google API key
* `googleapi_parameters` : dictionary with assumptions about Google Distances API request
Get route from to based on Google Distances API with two points (`origin` and `destination`)
on map `map_data` using Google API key `googleapi_key` with optional
Google Distances API request parameters `googleapi_parameters`.
"""
function get_google_route(origin::Int,destination::Int,
map_data::OpenStreetMapX.MapData,googleapi_key::String;
googleapi_parameters::Dict{Symbol,String} = OpenStreetMapX.googleAPI_parameters)
map_data::MapData,googleapi_key::String;
googleapi_parameters::Dict{Symbol,String} = googleAPI_parameters)
url = OpenStreetMapX.get_googleapi_url(origin, destination,map_data,googleapi_key,googleapi_parameters = googleapi_parameters)
status, routes = OpenStreetMapX.parse_google_url(url)
if status == "OK"
Expand Down
16 changes: 9 additions & 7 deletions src/nodes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ end
### Find the Nearest Node ###
#############################


### Find the nearest node to a given location ###
function nearest_node(nodes::Dict{Int,T}, loc::T) where T<:(Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF})
min_dist = Inf
Expand All @@ -36,8 +37,13 @@ function nearest_node(nodes::Dict{Int,T}, loc::T) where T<:(Union{OpenStreetMapX
return best_ind
end

function nearest_node(m::MapData, loc::ENU, vs_only::Bool=true)
vs_only ? nearest_node(m.nodes,loc, keys(m.v)) : nearest_node(m.nodes,loc)
end


### Find nearest node in a list of nodes ###
function nearest_node(nodes::Dict{Int,T}, loc::T, node_list::Vector{Int}) where T<:(Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF})
function nearest_node(nodes::Dict{Int,T}, loc::T, node_list::AbstractSet{Int}) where T<:(Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF})
min_dist = Inf
best_ind = 0

Expand All @@ -53,11 +59,6 @@ function nearest_node(nodes::Dict{Int,T}, loc::T, node_list::Vector{Int}) where
end


### Find nearest node serving as a vertex in a routing network ###
nearest_node(nodes::Dict{Int,T}, loc::T, m::OpenStreetMapX.MapData) where T<:(Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF}) = OpenStreetMapX.nearest_node(nodes,loc,collect(keys(m.v)))

nearest_node(loc::T, m::OpenStreetMapX.MapData) where T<:(Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF}) = OpenStreetMapX.nearest_node(m.nodes,loc,collect(keys(m.v)))

#############################
### Find Node Within Range###
#############################
Expand All @@ -78,7 +79,7 @@ function nodes_within_range(nodes::Dict{Int,T}, loc::T, range::Float64 = Inf) wh
end

### Find nodes within range of a location using a subset of nodes ###
function nodes_within_range(nodes::Dict{Int,T}, loc::T, node_list::Vector{Int}, range::Float64 = Inf) where T<:(Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF})
function nodes_within_range(nodes::Dict{Int,T}, loc::T, node_list::AbstractSet{Int}, range::Float64 = Inf) where T<:(Union{OpenStreetMapX.ENU,OpenStreetMapX.ECEF})
if range == Inf
return node_list
end
Expand Down Expand Up @@ -119,3 +120,4 @@ function centroid(nodes::Dict{Int,T}, node_list::Vector{Int}) where T<:(Union{Op
return OpenStreetMapX.ENU(sum_1/length(node_list),sum_2/length(node_list),sum_3/length(node_list))
end
end

9 changes: 5 additions & 4 deletions src/routing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function features_to_graph(m::OpenStreetMapX.MapData, features::Dict{Int,Tuple{S
sizehint!(features_to_nodes,length(features))
for (key,value) in features
if !haskey(m.v,key)
features_to_nodes[key] = OpenStreetMapX.nearest_node(m,nodes[key])
features_to_nodes[key] = OpenStreetMapX.nearest_node(m,features[key])
else
features_to_nodes[key] = key
end
Expand Down Expand Up @@ -359,7 +359,8 @@ end
"""
point_to_nodes(point::Tuple{Float64,Float64}, m::MapData)
Converts a pair of coordinates LLA `point` to a node on a map `m`
Converts a pair Latitude-Longitude of coordinates
`point` to a node on a map `m`
The result is a node indentifier.
"""
Expand All @@ -370,10 +371,10 @@ end
"""
point_to_nodes(point::LLA, m::MapData)
Converts a pair of coordinates LLA `point` to a node on a map `m`
Converts a pair of coordinates LLA (Latitude-Longitude-Altitude) `point` to a node on a map `m`
The result is a node indentifier.
"""
function point_to_nodes(point::LLA, m::MapData)
OpenStreetMapX.nearest_node(m.nodes,OpenStreetMapX.ENU(point, m.bounds), m)
nearest_node(m,OpenStreetMapX.ENU(point, m.bounds))
end
6 changes: 3 additions & 3 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ This is the main data structure used fot map data analytics.
* `class` : road class of each edge
"""
struct MapData
bounds::Bounds{OpenStreetMapX.LLA}
nodes::Dict{Int,OpenStreetMapX.ENU}
roadways::Array{OpenStreetMapX.Way,1}
bounds::Bounds{LLA}
nodes::Dict{Int,ENU}
roadways::Array{Way,1}
intersections::Dict{Int,Set{Int}}
# Transporation network graph data and helpers to increase routing speed
g::LightGraphs.SimpleGraphs.SimpleDiGraph{Int64} # Graph object
Expand Down
14 changes: 9 additions & 5 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@ import LightGraphs

@testset "maps" begin

m = OpenStreetMapX.get_map_data("data/reno_east3.osm",use_cache=false)
m = get_map_data("data/reno_east3.osm",use_cache=false);


@test length(m.nodes) == 9032

using Random
Random.seed!(0);
pA = generate_point_in_bounds(m)
@test all(isapprox.(pA,(39.53584630184622, -119.71506095062803)))
pB = generate_point_in_bounds(m)
@test all(isapprox.(pB,(39.507242155639005, -119.78506509516248)))
pointA = point_to_nodes(pA, m)
pointB = point_to_nodes(pB, m)

pointA = point_to_nodes(generate_point_in_bounds(m), m)
pointB = point_to_nodes(generate_point_in_bounds(m), m)
@test pointA == 3052967037
@test pointB == 140393352


sr1, shortest_distance1, shortest_time1 = OpenStreetMapX.shortest_route(m, pointA, pointB)
sr1, shortest_distance1, shortest_time1 = shortest_route(m, pointA, pointB)
@test (sr1[1], sr1[end]) == (pointA, pointB)

end;
end;

0 comments on commit 500652a

Please sign in to comment.