Hi. I was confused about how to use osm data to create a road network, and I would really appreciate it if someone could point me to any references or comments. So, I downloaded .osm.pbf file data from the internet and then use osmium cat
command to transfer it into .osm file, say a.osm. After that, since I’d like all the highways, I use the following command to get all the highways,
osmosis --read-xml myMap.osm --tf accept-ways highway=* --used-node --write-xml myHighways.osm
myHighways.osm is like 2GB, which is too big. Then, I use
osmosis --read-xml myMap.osm --tf accept-ways highway=motorway highway=motorway_link highway=trunk highway=trunk_link highway=primary highway=primary_link highway=secondary highway=secondary_link highway=tertiary highway=tertiary_link highway=unclassified highway=residential --used-node --write-xml myHighway.osm
The output file is like 300 MB.
The output statistics is like this:
the total number of nodes in mapdata: 1458735
roadways size: 195411
intersection size: 343552
edges size: 662120
obtained mapdata info:
mapdata min lat: 55.02652
mapdata max lat: 69.06643
mapdata min lon: 10.54138
mapdata max lon: 24.22472
Then, when I was trying to calculate the distance / route between two given locations using OpenStreetMapX package , say
location 1: 29.871436313505953*50.44155769066605
location 2: 20.99776468754424*64.75335912990957
or
location 1: 21.031682438798892*64.1644372892049
location 2: 20.99776468754424*64.75335912990957
The routes I got have distances 0. I think the reasons are as the following: for the first location pair, the longitude of location 1 is outside of the mapdata boundary; for the second pair, the two locations are very close I guess. I hope I understand this correctly. Or does anyone have any suggestions?
Moreover, I do not understand the purpose of the crop function in the function get_map_data of the file parseMap.jl.
"""
get_map_data(filepath::String,filename::Union{String,Nothing}=nothing;
road_levels::Set{Int} = Set(1:length(OpenStreetMapX.ROAD_CLASSES)),
use_cache::Bool = true, only_intersections::Bool=true)::MapData
High level function - parses .osm file and create the road network based on the map data.
**Arguments**
* `filepath` : path with an .osm file (directory or path to a file)
* `filename` : name of the file (when the first argument is a directory)
* `road_levels` : a set with the road categories (see: OpenStreetMapX.ROAD_CLASSES for more informations)
* `use_cache` : a *.cache file will be crated with a serialized map image in the `datapath` folder
* `only_intersections` : include only road system data
"""
function get_map_data(filepath::String,filename::Union{String,Nothing}=nothing; road_levels::Set{Int} = Set(1:length(OpenStreetMapX.ROAD_CLASSES)),use_cache::Bool = false,only_intersections=true)::MapData
#preprocessing map file
datapath = (filename==nothing) ? dirname(filepath) : filepath;
if filename == nothing
filename = basename(filepath)
end
cachefile = joinpath(datapath,filename*".cache")
if use_cache && isfile(cachefile)
f=open(cachefile,"r");
res=Serialization.deserialize(f);
close(f);
@info "Read map data from cache $cachefile"
else
osmdata = OpenStreetMapX.parseOSM(joinpath(datapath,filename))
println(" immediately after parseOSM info: ")
println(" nodes size: ", length(osmdata.nodes) )
println(" ways size: ", length(osmdata.ways))
println(" relations size: ", length(osmdata.relations))
println(" ******************* osmdata bounds ********************** ")
println(" osmdata bounds min lat: ", osmdata.bounds.min_y )
println(" osmdata bounds max lat: ", osmdata.bounds.max_y)
println(" osmdata bounds min lon: ", osmdata.bounds.min_x)
println(" osmdata bounds max lon: ", osmdata.bounds.max_x)
# OpenStreetMapX.crop!(osmdata,crop_relations = false) #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#preparing data
bounds = osmdata.bounds
nodes = OpenStreetMapX.ENU(osmdata.nodes,OpenStreetMapX.center(bounds))
highways = OpenStreetMapX.filter_highways(OpenStreetMapX.extract_highways(osmdata.ways))
roadways = OpenStreetMapX.filter_roadways(highways, levels= road_levels)
intersections = OpenStreetMapX.find_intersections(roadways)
segments = OpenStreetMapX.find_segments(nodes,roadways,intersections)
println("nodes size: ", length(nodes))
println("highways size: ", length(highways))
println("roadways size: ", length(roadways))
println("intersections size: ", length(intersections))
println("segments length: ", length(segments))
#remove unuseful nodes
roadways_nodes = unique(vcat(collect(way.nodes for way in roadways)...))
nodes = Dict(key => nodes[key] for key in roadways_nodes)
# e - Edges in graph, stored as a tuple (source,destination)
# class - Road class of each edgey
if only_intersections
vals = Dict((segment.node0,segment.node1) => (segment.distance,segment.parent) for segment in segments)
println(length(vals))
e = collect(keys(vals))
vals = collect(values(vals))
weights = map(val -> val[1],vals)
classified_roadways = OpenStreetMapX.classify_roadways(roadways)
class = [classified_roadways[id] for id in map(val -> val[2],vals)]
else
e,class = OpenStreetMapX.get_edges(nodes,roadways)
weights = OpenStreetMapX.distance(nodes,e)
end
# (node id) => (graph vertex)
v = OpenStreetMapX.get_vertices(e)
n = Dict(reverse.(collect(v)))
edges = [v[id] for id in reinterpret(Int, e)]
I = edges[1:2:end]
J = edges[2:2:end]
# w - Edge weights, indexed by graph id
w = SparseArrays.sparse(I, J, weights, length(v), length(v))
g = LightGraphs.DiGraph(w)
res = OpenStreetMapX.MapData(bounds,nodes,roadways,intersections,g,v,n,e,w,class)
if use_cache
f=open(cachefile,"w");
Serialization.serialize(f,res);
@info "Saved map data to cache $cachefile"
close(f);
end
end
println("obtained mapdata info: ")
println("mapdata min lat: ", res.bounds.min_y )
println("mapdata max lat: ", res.bounds.max_y )
println("mapdata min lon: ", res.bounds.min_x )
println("mapdata max lon: ", res.bounds.max_x )
return res
end
For my situation, if I keep the line OpenStreetMapX.crop!(osmdata,crop_relations = false)
, the edge set obtained has size 0, which is rather strange also.
Any comments are greatly appreciated.