128 lines
3.5 KiB
Python
Executable file
128 lines
3.5 KiB
Python
Executable file
#!/usr/bin/env python
|
|
#
|
|
# This script requies OsmApi (http://wiki.openstreetmap.org/wiki/PythonOsmApi)
|
|
#
|
|
# download:
|
|
# wget http://svn.openstreetmap.org/applications/utils/python_lib/OsmApi/OsmApi.py
|
|
# run this script:
|
|
# PYTHONPATH=. python THIS_SCRIPT_NAME <LIST_OF_WAY_IDs_AND_HEIGHTS
|
|
#
|
|
# The input file should contain the way ids in the first column and the height
|
|
# in the second column separated by a space or tab.
|
|
#
|
|
# Update your username and password below!
|
|
#
|
|
|
|
import OsmApi
|
|
import sys
|
|
import types
|
|
|
|
username = u"YOUR_USER_NAME"
|
|
password = u"YOUR_PASSWORD"
|
|
|
|
value_key = u"building:height"
|
|
forbidden_tags = [value_key, u"height"]
|
|
required_tags = [u"building"]
|
|
bounding_box = {
|
|
"min_lat": 54.027,
|
|
"max_lat": 54.197,
|
|
"min_lon": 11.984,
|
|
"max_lon": 12.267,
|
|
}
|
|
|
|
|
|
def remove_trailing_zeros(text):
|
|
value = text
|
|
while (value.find(".") >= 0) and (value.endswith("0") or value.endswith(".")):
|
|
value = value[:-1]
|
|
return value
|
|
|
|
|
|
def process_input_line(line):
|
|
try:
|
|
id, value = line.split()
|
|
# convert the id string into a number
|
|
id = int(id)
|
|
# remove trailing zeros from input number
|
|
value = remove_trailing_zeros(value)
|
|
# all values are in meter
|
|
value += " m"
|
|
except ValueError:
|
|
return None
|
|
return (id, value)
|
|
|
|
|
|
def read_id_value_file(filename):
|
|
result = []
|
|
try:
|
|
if type(filename) is types.FileType:
|
|
handle = filename
|
|
else:
|
|
handle = file(filename)
|
|
for line in handle.readlines():
|
|
item = process_input_line(line)
|
|
if item is None:
|
|
sys.stderr.write("Ignored invalid input line: %s\n" % str(line))
|
|
else:
|
|
result.append(item)
|
|
handle.close()
|
|
except IOError, err_msg:
|
|
sys.stderr.write("Failed to open input file (%s): %s\n" % (filename, err_msg))
|
|
return result
|
|
|
|
def validate_way(way, height, api):
|
|
"""check if the given way is safe to be updated
|
|
returns an error description string or an empty string (-> way is ok)
|
|
"""
|
|
# check for forbidden tags
|
|
for forbid_tag in forbidden_tags:
|
|
if way[u"tag"].has_key(forbid_tag):
|
|
if forbid_tag == value_key:
|
|
if height == way[u"tag"][forbid_tag]:
|
|
return "tag already set correctly"
|
|
else:
|
|
return "tag already contains different value"
|
|
else:
|
|
return "contains forbidden tag '%s'" % forbid_tag
|
|
# check for required tags
|
|
for required_tag in required_tags:
|
|
if not way[u"tag"].has_key(required_tag):
|
|
return "missing required tag '%s'" % required_tag
|
|
# check if all the nodes are within the bounding box
|
|
for node_id in way[u"nd"]:
|
|
node = api.NodeGet(node_id)
|
|
if (node[u"lat"] < bounding_box["min_lat"]) or (node[u"lat"] > bounding_box["max_lat"]):
|
|
return "latitude of node %d out of range" % node_id
|
|
if (node[u"lon"] < bounding_box["min_lon"]) or (node[u"lon"] > bounding_box["max_lon"]):
|
|
return "longitude of node %d out of range" % node_id
|
|
return ""
|
|
|
|
def update_way(way, height):
|
|
way[u"tag"][value_key] = height
|
|
return way
|
|
|
|
def send_changeset(api, changes):
|
|
api.ChangesetCreate({u"comment": u"Importing heights of houses from KVL Rostock"})
|
|
for change in changes:
|
|
api.WayUpdate(change)
|
|
api.ChangesetClose()
|
|
|
|
if __name__ == "__main__":
|
|
# read the input file content
|
|
input = read_id_value_file(sys.stdin)
|
|
|
|
api = OsmApi.OsmApi(username=username, password=password)
|
|
|
|
changes = []
|
|
for item in input:
|
|
way = api.WayGet(item[0])
|
|
warning = validate_way(way, item[1], api)
|
|
if not warning:
|
|
changes.append(update_way(way, item[1]))
|
|
print "Accepting valid way (%d/%s): %s" % (item[0], item[1], str(way))
|
|
else:
|
|
print "Ignoring invalid way (%d/%s): %s (%s)" % (item[0], item[1], warning, str(way))
|
|
|
|
if len(changes) > 0:
|
|
send_changeset(api, changes)
|
|
|