diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/osmux.py | 166 |
1 files changed, 0 insertions, 166 deletions
diff --git a/scripts/osmux.py b/scripts/osmux.py deleted file mode 100644 index f0cdf48..0000000 --- a/scripts/osmux.py +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -''' - -OSMux - A query multiplexer for the Overpass OpenStreetMap-API - -Version 2011-10-22 - -(c) 2011 - Conrad Hoffmann <ch@bitfehler.net> - -This software is public domain and comes without warranty of any kind. - -This script splits queries for large areas into several smaller bounding boxes, sends them to them -to the server and merges the results into a single file (the result for the original query). - -Additionally, ways are returned as nodes, so they can be displayed in map overlays. Actually, for -a matching way the script returns the first node of the way - but with all the tags that were -originally attached to the way. - -Basic usage instructions available via the --help switch. - -See http://code.bitfehler.net/osmux for more details. - -''' - -from os import close -from os import remove -from sys import stderr -from time import sleep -from tempfile import mkstemp -from argparse import ArgumentParser -from urllib.request import urlretrieve -import xml.etree.ElementTree as etree - -QUERY_TEMPLATE = 'http://www.overpass-api.de/api/xapi?%s[bbox=%f,%f,%f,%f][%s=%s]' - -def log(msg): - ''' Print a message to the console, unless the 'quiet' flag was set. ''' - if not params.quiet: - print(msg) - -def extract(xmlfile): - ''' Extract nodes from a query result. - - Regular nodes are just added to the result. For ways, the ways tags are copied to the first - node of the way and this first node is added to the result. - - ''' - tree = etree.parse(xmlfile) - root = tree.getroot() - result = {} - nodes = {} - - for child in root: - if child.tag == 'node': - # Save all nodes in this temp structure, if we are parsing ways we need them later on. - nodes[child.attrib['id']] = child - # If the node also contains the tag we are looking for, add it to the result. - for tag in child: - if tag.attrib['k'] == params.tag: - result[child.attrib['id']] = child - elif child.tag == 'way': - # Create a new custom node that contains all of the ways tags and add it to result. If - # a way is returned, it must contain the tag we are looking for, so no need to check. - node = nodes[child[0].attrib['ref']] - for sub in child: - if sub.tag == 'tag': - etree.SubElement(node, 'tag', sub.attrib) - result[node.attrib['id']] = node - elif child.tag == 'remark': - # This usually means the query timed out or ran out of memory. - print('Potential error: %s' % child.text, file=stderr) - - return result - -# Parse command line arguments. -parser = ArgumentParser(description='Generate an OpenLayers OSM file using the Overpass API.', - epilog='See http://code.bitfehler.net for more details.') -parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help='suppress progress messages') -parser.add_argument('-S', '--step', dest='step', metavar='D', default=1.0, type=float, help='split into steps of D degrees') -parser.add_argument('-p', '--pause', dest='pause', metavar='P', default=1, type=int, help='pause for P seconds between requests to reduce server load (default: 1, must be >= 0)') -parser.add_argument('-t', '--tag', dest='tag', metavar='<tag>', type=str, required=True, help='return only elements with this tag') -parser.add_argument('-v', '--value', dest='value', metavar='<value>', default='*', type=str, help='return only elements with this value (omit for \'*\')') -parser.add_argument('-s', '--south', dest='south', metavar='S', type=float, required=True, help='latitude of the southern border of the bounding box') -parser.add_argument('-w', '--west', dest='west', metavar='W', type=float, required=True, help='longitude of the western border of the bounding box') -parser.add_argument('-n', '--north', dest='north', metavar='N', type=float, required=True, help='latitude of the northern border of the bounding box') -parser.add_argument('-e', '--east', dest='east', metavar='E', type=float, required=True, help='longitude of the eastern border of the bounding box') -parser.add_argument('outfile', metavar='<output file>', type=str, help='the output file for the merged OSM data') -params = parser.parse_args() - -# Sanity checks for the arguments. -if params.pause < 0: - print('Value for --pause must be >= 0. Exiting.', file=stderr) - exit(1) -if params.step <= 0: - print('Value for --pause must be > 0. Exiting.', file=stderr) - exit(1) -try: - open(params.outfile, mode='a', encoding='utf-8') -except IOError as e: - (errno, strerror) = e.args - print('Failed to open output file for writing: %s. Exiting.' % strerror, file=stderr) - exit(1) -if min(params.south, params.north) != params.south: - print('Value for --south must be less then --north. Use negative numbers for southern hemisphere. Exiting.', file=stderr) - exit(1) -if min(params.east, params.west) != params.west: - print('Value for --west must be less then --east. Use e.g. --east 187.5 if you need to cover the 180th meridian. Exiting.', file=stderr) - exit(1) - - -(handle, tmpfile) = mkstemp(suffix='.xml', prefix='osm') -close(handle) -log("Using temporary file %s, step %f and pause %d." % (tmpfile, params.step, params.pause)) - -result = {} - -cur_lat = params.south -cur_lon = params.west - -while cur_lat < params.north: - - # While we are in this loop, there are more squares to fetch. - - # We know which square to go for, get its bbox: - bbox_lon = [cur_lon, min(cur_lon + params.step, params.east)] - bbox_lat = [cur_lat, min(cur_lat + params.step, params.north)] - - nquery = QUERY_TEMPLATE % ('node', bbox_lon[0], bbox_lat[0], bbox_lon[1], bbox_lat[1], params.tag, params.value) - wquery = QUERY_TEMPLATE % ('way', bbox_lon[0], bbox_lat[0], bbox_lon[1], bbox_lat[1], params.tag, params.value) - - log("Fetching %s" % nquery) - urlretrieve(nquery, tmpfile) - result.update(extract(tmpfile)) - - log("Fetching %s" % wquery) - urlretrieve(wquery, tmpfile) - result.update(extract(tmpfile)) - - # Calculate the next sub-bbox: - if cur_lon + params.step < params.east: - # Proceed with next square in current "row": - cur_lon += params.step - else: - # Reset longitude, continue with next "row", if any: - cur_lon = params.west - cur_lat += params.step - - # Wait a moment - might help the server. - sleep(params.pause) - - -log("Removing temporary data file...") -remove(tmpfile) - -log("Generating data...") -with open(params.outfile, mode='w', encoding='utf-8') as out: - out.write('''<?xml version='1.0' encoding='UTF-8'?> -<osm version="0.6" generator="OSMux (http://code.bitfehler.net/osmux"> -<bound box="%f,%f,%f,%f" origin="Osmosis SNAPSHOT-rexported"/> -''' % (params.west, params.south, params.east, params.north)) - for nid in result: - node = result[nid] - out.write(etree.tostring(node, encoding='utf-8').decode('utf-8')) - out.write('</osm>') - |