Previously, I asked the question "How can I find a list of street intersections from OpenStreetMap data?". I fixed the code in the previous post that finds nodes that are shared by two or more <way>
s based on the response to the previous question. It (almost) works now and I can collect coordinates of street intersections. (Using only the <way>
s that has tag attributes 'primary', 'secondary', 'residential', or 'tertiary' to find the nodes that are shared by multiple <way>
s solved the problem. I filtered out other <way>
s such as the ones with the tag attribute 'building')
The problem I am facing now is that the intersection coordinates I collect is not exhaustive, and I don't know wheter this is due to the limitation of the OpenStreetMap data or my code is still messed up. Please see the following image.
The pins on the Google Map indicate the lat/lng coordinates of intersections collected from OpenStreeMap. Although the pins placed are correctly positioned on the intersections, the technique I used misses to find some intersections such as the ones pointed by red arrows on the same figure.
The osm file (xml file) I used to get these coordinates is: https://dl.dropboxusercontent.com/u/1047998/WashingtonDC.osm (This file is in the public folder of my dropbox. Sorry if it becomes unavailable.)
The code I used to scrape the data is as follows:
def get_intersections(self, osm, input_type='file'):
"""
This method reads the passed osm file (xml) and finds intersections (nodes that are shared by two or more roads)
:param osm: An osm file or a string from get_osm()
"""
intersection_coordinates = []
if input_type == 'file':
tree = ET.parse(osm)
root = tree.getroot()
children = root.getchildren()
elif input_type == 'str':
tree = ET.fromstring(osm)
children = tree.getchildren()
counter = {}
for child in children:
if child.tag == 'way':
# Check if the way represents a "highway (road)"
# If the way that we are focusing right now is not a road,
# continue without checking any nodes
road = False
road_types = ('primary', 'secondary', 'residential', 'tertiary', 'service')
for item in child:
if item.tag == 'tag' and item.attrib['k'] == 'highway' and item.attrib['v'] in road_types:
road = True
if not road:
continue
for item in child:
if item.tag == 'nd':
nd_ref = item.attrib['ref']
if not nd_ref in counter:
counter[nd_ref] = 0
counter[nd_ref] += 1
# Find nodes that are shared with more than one way, which
# might correspond to intersections
intersections = filter(lambda x: counter[x] > 1, counter)
# Extract intersection coordinates
# You can plot the result using this url.
# http://www.darrinward.com/lat-long/
for child in children:
if child.tag == 'node' and child.attrib['id'] in intersections:
coordinate = child.attrib['lat'] + ',' + child.attrib['lon']
intersection_coordinates.append(coordinate)
return intersection_coordinates
I appreciate any comments, suggestions, and solutions. It is also great if you could suggest me any other ways to collect intersection coordinates.