forked from balrog-kun/osm-addr-tools
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathget-missing-streets.py
executable file
·132 lines (125 loc) · 3.88 KB
/
get-missing-streets.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#! /usr/bin/python2
# vim: fileencoding=utf-8 encoding=utf-8 et sw=4
#
# Reads an existing-highways.osm file and an addresses.osm file and
# writes an .osm file containing one node per potential missing street
# name -- such that no named highway containing every word from the
# addr:street is found within about ~1.5km
# Output name is hardcoded as missing-streets.osm
#
# The inputs can be generated with something like:
# wget -O existing-highways.osm 'http://overpass-api.de/api/xapi?way[highway=*][name=*][bbox=20.781,52.092,21.281,52.365]'
# wget -O addresses.osm 'http://overpass-api.de/api/xapi?*[addr:street=*][bbox=20.781,52.092,21.281,52.365]'
#
# Not sure about a need to escape the ':' in the second query somehow...
#
import sys
import os
import math
import xml.etree.cElementTree as ElementTree
i = 0
outroot = ElementTree.Element("osm", {"version": "0.6"})
inroot = ElementTree.parse(sys.argv[1]).getroot()
waynodes = {}
existingaddrs = {}
for elem in inroot:
if "id" not in elem.attrib:
continue
id = int(elem.attrib["id"])
tags = {}
for sub in elem:
if sub.tag != "tag":
continue
tags[sub.attrib["k"]] = sub.attrib["v"]
if elem.tag == "node":
lat = float(elem.attrib["lat"])
lon = float(elem.attrib["lon"])
waynodes[id] = (lat, lon)
if "addr:housenumber" not in tags or "addr:street" not in tags:
continue
if elem.tag == "node" and "amenity" in tags:
continue
strt = tags["addr:street"].lower()
if elem.tag not in ["way", "node"]:
continue
if elem.tag == "way":
j = 0
lat = 0.0
lon = 0.0
for sub in elem:
if sub.tag != "nd":
continue
ref = int(sub.attrib["ref"])
if ref not in waynodes:
continue
j += 1
lat += waynodes[ref][0]
lon += waynodes[ref][1]
lat /= j
lon /= j
existingaddrs[strt] = (lat, lon)
byword = {}
for elem in inroot:
if "id" not in elem.attrib:
continue
id = int(elem.attrib["id"])
tags = {}
nodes = []
for sub in elem:
if sub.tag == "nd":
nodes.append(waynodes[int(sub.attrib["ref"])])
if sub.tag != "tag":
continue
tags[sub.attrib["k"]] = sub.attrib["v"]
if elem.tag == "node":
lat = float(elem.attrib["lat"])
lon = float(elem.attrib["lon"])
waynodes[id] = (lat, lon)
continue
elif elem.tag not in ["way"]:
continue
if "highway" not in tags or "name" not in tags:
continue
name = tags["name"].lower().split()
if "alt_name" in tags:
name += tags["alt_name"].lower().replace(";", " ").split()
for word in name:
if word not in byword:
byword[word] = []
byword[word].append((name, nodes, id))
inroot = None
i = 0
for strt in existingaddrs:
lat, lon = existingaddrs[strt]
all = 0
hwys = {}
for word in strt.split():
all += 1
if word in byword:
for hwy in byword[word]:
hwys[hwy[2]] = hwy
cont = 0
for id in hwys:
name, nodes, _id = hwys[id]
same = 0
for word in strt.split():
if word in [u"Księdza", u"Kapitana", u"Generała"] or word in name:
same += 1
if same == all:
for nlat, nlon in nodes:
if math.hypot(lat - nlat, lon - nlon) < 0.01: # ~1km?
cont = 1
break
if cont:
break
if cont:
continue
i += 1
node = ElementTree.SubElement(
outroot,
"node",
{"lat": str(lat), "lon": str(lon), "version": str(1), "id": str(i)},
)
ElementTree.SubElement(node, "tag", {"k": "addr:street", "v": strt})
sys.stdout.write("Writing .osm's\n")
ElementTree.ElementTree(outroot).write("missing-streets.osm", "utf-8")