diff --git a/Project.toml b/Project.toml index 01f0bc6..7b7e877 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "LightOSM" uuid = "d1922b25-af4e-4ba3-84af-fe9bea896051" authors = ["Jack Chan "] -version = "0.3.0" +version = "0.3.2" [deps] DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" diff --git a/src/graph.jl b/src/graph.jl index 45bb58b..5a2c438 100644 --- a/src/graph.jl +++ b/src/graph.jl @@ -1,11 +1,13 @@ """ graph_from_object(osm_data_object::Union{XMLDocument,Dict}; - network_type::Symbol=:drive, - weight_type::Symbol=:time, - graph_type::Symbol=:static, - precompute_dijkstra_states::Bool=false, - largest_connected_component::Bool=true - )::OSMGraph + network_type::Symbol=:drive, + weight_type::Symbol=:time, + graph_type::Symbol=:static, + precompute_dijkstra_states::Bool=false, + largest_connected_component::Bool=true, + filter_network_type::Bool=true, + tags_filter::Dict{String, Vector{String}}=Dict{String, Vector{String}}() + )::OSMGraph Creates an `OSMGraph` object from download OpenStreetMap network data, use with `download_osm_network`. @@ -41,15 +43,18 @@ function graph_from_object(osm_data_object::Union{XMLDocument,Dict}; graph_type::Symbol=:static, precompute_dijkstra_states::Bool=false, largest_connected_component::Bool=true, - filter_network_type::Bool=true + filter_network_type::Bool=true, + tags_filter::Dict{String, Vector{String}}=Dict{String, Vector{String}}() )::OSMGraph - g = init_graph_from_object(osm_data_object, network_type, filter_network_type=filter_network_type) + + g = init_graph_from_object(osm_data_object, network_type, tags_filter, filter_network_type=filter_network_type) add_node_and_edge_mappings!(g) add_weights!(g, weight_type) add_graph!(g, graph_type) # Finding connected components can only be done after LightGraph object has been constructed largest_connected_component && trim_to_largest_connected_component!(g, g.graph, weight_type, graph_type) # Pass in graph to make type stable add_node_tags!(g) + !isempty(tags_filter) && add_custom_node_tags!(g, tags_filter) !(network_type in [:bike, :walk]) && add_indexed_restrictions!(g) if precompute_dijkstra_states @@ -95,7 +100,8 @@ function graph_from_file(file_path::String; graph_type::Symbol=:static, precompute_dijkstra_states::Bool=false, largest_connected_component::Bool=true, - filter_network_type::Bool=true + filter_network_type::Bool=true, + tags_filter::Dict{String, Vector{String}}=Dict{String, Vector{String}}() )::OSMGraph !isfile(file_path) && throw(ArgumentError("File $file_path does not exist")) @@ -107,7 +113,8 @@ function graph_from_file(file_path::String; graph_type=graph_type, precompute_dijkstra_states=precompute_dijkstra_states, largest_connected_component=largest_connected_component, - filter_network_type=filter_network_type) + filter_network_type=filter_network_type, + tags_filter=tags_filter) end """ @@ -264,6 +271,31 @@ function add_node_tags!(g::OSMGraph) push!(g.node_coordinates, [data.location.lat, data.location.lon]) end end + """ + add_custom_node_tags!(g::OSMGraph, tags_filter::Dict{String, Vector} = Dict{String, String}()) + +Based on the provided dictionary of custom tags adds them to the node +""" +function add_custom_node_tags!(g::OSMGraph, tags_filter) + for (id, data) in g.nodes + tags_filter_dict = Dict{String, Any}() + ways = g.node_to_way[id] + for way_id in ways + way = g.ways[way_id] + for (key, value) in pairs(tags_filter) + !haskey(way.tags, key) && continue + !haskey(tags_filter_dict, key) && (tags_filter_dict[key] = Dict()) + for v in value + !haskey(way.tags[key], v) && continue + !haskey(tags_filter_dict[key], v) && (tags_filter_dict[key][v] = []) + push!(tags_filter_dict[key][v], way.tags[key][v]) + end + end + end + g.nodes[id].tags = tags_filter_dict + end +end + """ adjacent_node(g::OSMGraph, node::T, way::T)::Union{T,Vector{<:T}} where T <: DEFAULT_OSM_ID_TYPE @@ -292,6 +324,8 @@ function adjacent_node(g::OSMGraph, node::T, way::T)::Union{T,Vector{<:T}} where end end + + """ add_indexed_restrictions!(g::OSMGraph{U,T,W}) where {U <: DEFAULT_OSM_INDEX_TYPE, T <: DEFAULT_OSM_ID_TYPE, W <: Real} diff --git a/src/parse.jl b/src/parse.jl index e34fb69..f45e110 100644 --- a/src/parse.jl +++ b/src/parse.jl @@ -198,8 +198,9 @@ end Parse OpenStreetMap data into `Node`, `Way` and `Restriction` objects. """ function parse_osm_network_dict(osm_network_dict::AbstractDict, - network_type::Symbol=:drive; - filter_network_type::Bool=true + network_type::Symbol=:drive, + tags_filter::Dict{String, Vector{String}}=Dict{String, Vector{String}}(); + filter_network_type::Bool=true, )::OSMGraph U = DEFAULT_OSM_INDEX_TYPE @@ -217,6 +218,8 @@ function parse_osm_network_dict(osm_network_dict::AbstractDict, tags["lanes"] = lanes(tags) tags["oneway"] = is_oneway(tags) tags["reverseway"] = is_reverseway(tags) + # Check if custom tags need to be added + !isempty(tags_filter) && (tags = add_custom_way_tags(tags, tags_filter, way)) nds = way["nodes"] union!(highway_nodes, nds) id = way["id"] @@ -231,6 +234,8 @@ function parse_osm_network_dict(osm_network_dict::AbstractDict, tags["maxspeed"] = maxspeed(tags) tags["oneway"] = is_oneway(tags) tags["reverseway"] = is_reverseway(tags) + # Check if custom tags need to be added + !isempty(tags_filter) && (tags = add_custom_way_tags(tags, tags_filter, way)) nds = way["nodes"] union!(highway_nodes, nds) id = way["id"] @@ -339,13 +344,15 @@ end Initialises the OSMGraph object from OpenStreetMap data downloaded in `:xml` or `:osm` format. """ function init_graph_from_object(osm_xml_object::XMLDocument, - network_type::Symbol=:drive; - filter_network_type::Bool=true + network_type::Symbol=:drive, + tags_filter::Dict{String, Vector{String}}=Dict{String, Vector{String}}(); + filter_network_type::Bool=true, )::OSMGraph dict_to_parse = osm_dict_from_xml(osm_xml_object) return parse_osm_network_dict( - dict_to_parse, - network_type; + dict_to_parse, + network_type, + tags_filter; filter_network_type=filter_network_type ) end @@ -354,13 +361,15 @@ end Initialises the OSMGraph object from OpenStreetMap data downloaded in `:json` format. """ function init_graph_from_object(osm_json_object::AbstractDict, - network_type::Symbol=:drive; + network_type::Symbol=:drive, + tags_filter::Dict{String, Vector{String}}=Dict{String, Vector{String}}(); filter_network_type::Bool=true )::OSMGraph dict_to_parse = osm_dict_from_json(osm_json_object) return parse_osm_network_dict( - dict_to_parse, - network_type; + dict_to_parse, + network_type, + tags_filter; filter_network_type=filter_network_type ) end @@ -385,4 +394,15 @@ function get_id_type(osm_network_dict::AbstractDict)::Type else throw(ErrorException("OSM ID type not supported: $(typeof(first_id))")) end +end + +function add_custom_way_tags(tags, tags_filter, way) + for (key, value) in pairs(tags_filter) + !haskey(way, key) && continue + tags[key] = Dict() + for v in value + haskey(way[key], v) && (tags[key][v] = way[key][v]) + end + end + return tags end \ No newline at end of file diff --git a/src/types.jl b/src/types.jl index 79bc494..9a85555 100644 --- a/src/types.jl +++ b/src/types.jl @@ -66,8 +66,11 @@ struct Way{T <: Union{Integer, String}} tags::Dict{String,Any} end Way(id::T, nodes, tags::Dict{String, Any}) where T <: Union{Integer, String} = Way(id, convert(Vector{T}, nodes), tags) - - +# # If "all" then we add all. +# # Use true false +# {"vmt_tags" => ["local_road_name", ], +# "dtp_other_tags" => ["rma", ] +# } """ EdgePoint{T<:Integer}