codekasten/osm/rostock_import_height_2009/add_height.py

129 lines
3.5 KiB
Python
Raw Normal View History

#!/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)