From becf68f7e1d9c5f09e008b191418f59248edb6bc Mon Sep 17 00:00:00 2001 From: Sergey Vartanov Date: Tue, 28 Jul 2015 12:40:12 +0300 Subject: [PATCH] Mapper. --- flinger.py | 120 ++++++++++ icons.svg | 301 ++++++++++++++++++++++++ mapper.py | 658 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1079 insertions(+) create mode 100644 flinger.py create mode 100644 icons.svg create mode 100644 mapper.py diff --git a/flinger.py b/flinger.py new file mode 100644 index 0000000..31bb980 --- /dev/null +++ b/flinger.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python + +""" +Author: Sergey Vartanov (me@enzet.ru) +""" + +import math +import sys + +sys.path.append('lib') + +from vector import Vector + + +class Flinger(object): + """ + Flinger. Coordinates repositioning. + """ + def __init__(self, minimum, maximum, target_minimum=None, target_maximum=None, ratio=None): + self.minimum = minimum + self.maximum = maximum + + if not target_minimum: + target_minimum = Vector() + if not target_maximum: + target_maximum = maximum - minimum + + space = Vector() + + if ratio: + if ratio == 'geo': + ratio = math.sin((90.0 - ((self.maximum.y + self.minimum.y) / 2.0)) / 180.0 * math.pi) + + current_ratio = (self.maximum.x - self.minimum.x) * ratio / (self.maximum.y - self.minimum.y) + target_ratio = (target_maximum.x - target_minimum.x) / (target_maximum.y - target_minimum.y) + + if current_ratio >= target_ratio: + n = (target_maximum.x - target_minimum.x) / (maximum.x - minimum.x) / ratio + space.y = ((target_maximum.y - target_minimum.y) - (maximum.y - minimum.y) * n) / 2.0 + space.x = 0 + else: + n = (target_maximum.y - target_minimum.y) / (maximum.y - minimum.y) + space.x = ((target_maximum.x - target_minimum.x) - (maximum.x - minimum.x) * n) / 2.0 + space.y = 0 + + target_minimum.x += space + target_maximum.x += space + + self.target_minimum = target_minimum + self.target_maximum = target_maximum + + def fling(self, current): + """ + Fling current point to the surface. + """ + x = map_(current.x, self.minimum.x, self.maximum.x, self.target_minimum.x, self.target_maximum.x) + y = map_(current.y, self.minimum.y, self.maximum.y, self.target_minimum.y, self.target_maximum.y) + return Vector(x, y) + + +class Geo: + def __init__(self, lat, lon): + self.lat = lat + self.lon = lon + def __add__(self, other): + return Geo(self.lat + other.lat, self.lon + other.lon) + def __sub__(self, other): + return Geo(self.lat - other.lat, self.lon - other.lon) + def __repr__(self): + return `self.lat` + ', ' + `self.lon` + + +class GeoFlinger: + def __init__(self, minimum, maximum, target_minimum=None, target_maximum=None): + self.minimum = minimum + self.maximum = maximum + + # Ratio is depended of latitude. It is always <= 1. + # In one latitude degree is always 40 000 / 360 km. + # In one current longitude degree is about 40 000 / 360 * ratio km. + + ratio = math.sin((90.0 - ((self.maximum.lat + self.minimum.lat) / 2.0)) / 180.0 * math.pi) + + # Longitude displayed as x. + # Latitude displayed as y. + + # Ratio is x / y. + + space = Vector() + current_ratio = (self.maximum.lon - self.minimum.lon) * ratio / (self.maximum.lat - self.minimum.lat) + target_ratio = (target_maximum.x - target_minimum.x) / (target_maximum.y - target_minimum.y) + + if current_ratio >= target_ratio: + n = (target_maximum.x - target_minimum.x) / (maximum.lon - minimum.lon) / ratio + space.y = ((target_maximum.y - target_minimum.y) - (maximum.lat - minimum.lat) * n) / 2.0 + space.x = 0 + else: + n = (target_maximum.y - target_minimum.y) / (maximum.lat - minimum.lat) * ratio + space.x = ((target_maximum.x - target_minimum.x) - (maximum.lon - minimum.lon) * n) / 2.0 + space.y = 0 + + self.target_minimum = target_minimum + space + self.target_maximum = target_maximum - space + + self.space = space + + def fling(self, current): + x = map_(current.lon, self.minimum.lon, self.maximum.lon, + self.target_minimum.x, self.target_maximum.x) + y = map_(self.maximum.lat + self.minimum.lat - current.lat, + self.minimum.lat, self.maximum.lat, + self.target_minimum.y, self.target_maximum.y) + return Vector(x, y) + + +def map_(value, current_min, current_max, target_min, target_max): + """ + Map current value in bounds of current_min and current_max to bounds of target_min and target_max. + """ + return target_min + (value - current_min) / (current_max - current_min) * (target_max - target_min) diff --git a/icons.svg b/icons.svg new file mode 100644 index 0000000..c888f22 --- /dev/null +++ b/icons.svg @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mapper.py b/mapper.py new file mode 100644 index 0000000..0e1fdb3 --- /dev/null +++ b/mapper.py @@ -0,0 +1,658 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- from __future__ import unicode_literals + +# Author: Sergey Vartnov + +import os +import re +import sys +import xml.dom.minidom + +from flinger import GeoFlinger, Geo + +sys.path.append('lib') + +import svg +from vector import Vector + +# class OSMGetter: +# def get(x1, x2, y1, y2): +# input_file = open(cache_folder + '/osm-' + `x1` + '-' + `y1` + '-' + \ +# `x2` + '-' + `y2` +# if not os.path.isfile(input_file): + +input_file_name = sys.argv[1] + +if not os.path.isfile(input_file_name): + sys.exit(1) + +print 'Reading input OSM file...' + +input_file = open(input_file_name) +content = xml.dom.minidom.parse(input_file) +input_file.close() + +print 'Done.' + +output_file = svg.SVG(open(sys.argv[2], 'w+')) + +w, h = 2000, 2000 + +background_color = 'EEEEEE' +grass_color = 'C8DC94' +sand_color = 'F0E0D0' +beach_color = 'F0E0C0' +desert_color = 'F0E0D0' +playground_color = '884400' +parking_color = 'DDCC99' +water_color = 'AACCFF' +water_border_color = '6688BB' +wood_color = 'B8CC84' + +output_file.begin(w, h) +output_file.rect(0, 0, w, h, color=background_color) + +minimum = Geo(180, 180) +maximum = Geo(-180, -180) + +if len(sys.argv) > 3: + min1 = Geo(float(sys.argv[5]), float(sys.argv[3])) + max1 = Geo(float(sys.argv[6]), float(sys.argv[4])) + +authors = {} +missed_tags = {} + +d_street_lamp = 'm 7,1 -3.5,3 1.59375,0 1,5 1.40625,0 0,6 1,0 0,-6 1.40625,0 1,-5 L 12.5,4 9,1 z M 6.125,4 9.875,4 9.09375,8 6.90625,8 z' +d_clinic = 'M 7,5 7,7 5,7 5,9 7,9 7,11 9,11 9,9 11,9 11,7 9,7 9,5 7,5' +d_crossing = 'm 3,5 0,6 1,0 0,-6 z m 4,0 0,6 1,0 0,-6 z m 4,0 0,6 1,0 0,-6 z' +d_traffic_signal = 'M 7,1 C 6.446,1 6,1.446 6,2 L 6,4 C 6,4.1879013 6.0668244,4.3501348 6.15625,4.5 6.0668244,4.6498652 6,4.8120987 6,5 L 6,7 C 6,7.1879013 6.0668244,7.3501348 6.15625,7.5 6.0668244,7.6498652 6,7.8120987 6,8 l 0,2 c 0,0.554 0.446,1 1,1 l 0.5,0 0,3 -1.5,0 0,1 4,0 0,-1 -1.5,0 0,-3 0.5,0 c 0.554,0 1,-0.446 1,-1 L 10,8 C 10,7.8120987 9.9331756,7.6498652 9.84375,7.5 9.9331756,7.3501348 10,7.1879013 10,7 L 10,5 C 10,4.8120987 9.9331756,4.6498652 9.84375,4.5 9.9331756,4.3501348 10,4.1879013 10,4 L 10,2 C 10,1.446 9.554,1 9,1 z M 7,2 9,2 9,4 7,4 z M 7,5 9,5 9,7 7,7 z m 0,3 2,0 0,2 -2,0 z' +d_tree = 'M 7 2 C 6.446 2 6 2.446 6 3 C 5.446 3 5 3.4460001 5 4 L 5 7 C 5 7.5539999 5.446 8 6 8 C 6 8.554 6.446 9 7 9 L 7.5625 9 L 7.5625 12 L 8.4375 12 L 8.4375 9 L 9 9 C 9.554 9 10 8.554 10 8 C 10.554 8 11 7.5539999 11 7 L 11 4 C 11 3.4460001 10.554 3 10 3 C 10 2.446 9.554 2 9 2 L 7 2 z' + +def get_d_from_file(file_name): + if os.path.isfile('icons/' + file_name + '.svg'): + file_name = 'icons/' + file_name + '.svg' + size = 16 + elif os.path.isfile('icons/' + file_name + '.16.svg'): + file_name = 'icons/' + file_name + '.16.svg' + size = 16 + elif os.path.isfile('icons/' + file_name + '-12.svg'): + file_name = 'icons/' + file_name + '-12.svg' + size = 12 + elif os.path.isfile('icons/' + file_name + '.12.svg'): + file_name = 'icons/' + file_name + '.12.svg' + size = 12 + elif os.path.isfile('icons/' + file_name + '.10.svg'): + file_name = 'icons/' + file_name + '.10.svg' + size = 10 + else: + print 'Unknown file:', file_name + return 'M 4,4 L 4,10 10,10 10,4 4,4', 16 + f = open(file_name).read().split('\n') + for line in f: + m = re.match('.* d="(?P[AaMmCcLlZz0-9Ee., -]*)".*', line) + if m: + return m.group('path'), size + +# Construct node map + +def construct_node_map(): + """ + Construct map of nodes. + """ + print 'Construct node map...' + node_map = {} + for element in content.childNodes[0].childNodes: + if element.nodeType != element.TEXT_NODE: + if 'user' in element.attributes.keys(): + author = element.attributes['user'].value + if author in authors: + authors[author] += 1 + else: + authors[author] = 1 + if not ('lat' in element.attributes.keys()): + continue + node_map[element.attributes['id'].value] = \ + Geo(float(element.attributes['lat'].value), + float(element.attributes['lon'].value)) + if float(element.attributes['lat'].value) > maximum.lat: + maximum.lat = float(element.attributes['lat'].value) + if float(element.attributes['lat'].value) < minimum.lat: + minimum.lat = float(element.attributes['lat'].value) + if float(element.attributes['lon'].value) > maximum.lon: + maximum.lon = float(element.attributes['lon'].value) + if float(element.attributes['lon'].value) < minimum.lon: + minimum.lon = float(element.attributes['lon'].value) + print 'Done.' + return node_map + +node_map = construct_node_map() + +if len(sys.argv) > 3: + flinger = GeoFlinger(min1, max1, Vector(0, 0), Vector(w, h)) +else: + flinger = GeoFlinger(minimum, maximum, Vector(25, 25), Vector(975, 975)) + + +def draw_path(nodes, style, shift=Vector()): + prev_node = None + for node_id in nodes: + flinged1 = flinger.fling(node_map[node_id]) + shift + if prev_node: + flinged2 = flinger.fling(prev_node) + shift + output_file.write('L ' + `flinged1.x` + ',' + `flinged1.y` + ' ') + else: + output_file.write('\n') + +def draw_point_shape(name, x, y, fill): + shape, size = get_d_from_file(name) + draw_point(shape, x, y, fill, size=size) + +def draw_point(shape, x, y, fill, size=16): + x = int(float(x)) + y = int(float(y)) + output_file.write('\n') + output_file.write('\n') + +def draw_text(text, x, y, fill): + if type(text) == unicode: + text = text.encode('utf-8') + text = text.replace('&', 'and') + if text[:7] == 'http://' or text[:8] == 'https://': + text = 'link' + fill = '0000FF' + return + output_file.write('' + text + '') + output_file.write('' + text + '') + +def point(k, v, x, y, fill): + if ('node ' + k + ': ' + v) in missed_tags: + missed_tags['node ' + k + ': ' + v] += 1 + else: + missed_tags['node ' + k + ': ' + v] = 1 + output_file.circle(x, y, 2, fill=fill, color=fill) + text = k + ': ' + v + if type(text) == unicode: + text = text.encode('utf-8') + output_file.write('' + text + '') + +# Ways drawing + +def construct_way_map(): + """ + Construct map of ways and distribute them by layers. One layer may contain + elements of different types. + """ + print 'Construct way map...' + + layers = {} + way_map = {} + + for element in content.childNodes[0].childNodes: + if element.nodeName == 'way': + way = {'nodes': [], 'tags': {}} + way_map[element.attributes['id'].value] = way + + for element in content.childNodes[0].childNodes: + if element.nodeName == 'relation': + relation = {'members': [], 'tags': {}} + for child_node in element.childNodes: + if isinstance(child_node, xml.dom.minidom.Element): + if child_node.tagName == 'tag': + k = child_node.attributes['k'].value + v = child_node.attributes['v'].value + relation['tags'][k] = v + for child_node in element.childNodes: + if isinstance(child_node, xml.dom.minidom.Element): + if child_node.tagName == 'member': + index = child_node.attributes['ref'].value + if index in way_map: + way = way_map[index] + for tag in relation['tags']: + way['tags'][tag] = relation['tags'][tag] + + for element in content.childNodes[0].childNodes: + if element.nodeName == 'way': + way = way_map[element.attributes['id'].value] + for child_node in element.childNodes: + if isinstance(child_node, xml.dom.minidom.Element): + if child_node.tagName == 'tag': + k = child_node.attributes['k'].value + v = child_node.attributes['v'].value + way['tags'][k] = v + if child_node.tagName == 'nd': + way['nodes'].append(child_node.attributes['ref'].value) + if not ('layer' in way['tags']): + way['tags']['layer'] = 0 + if not (int(way['tags']['layer']) in layers): + layers[int(way['tags']['layer'])] = \ + {'b': [], 'h1': [], 'h2': [], 'r': [], 'n': [], 'l': [], + 'a': [], 'le': [], 'ba': [], 'bo': []} + layer = layers[int(way['tags']['layer'])] + if 'building' in way['tags']: + layer['b'].append(way) + if 'natural' in way['tags']: + layer['n'].append(way) + if 'landuse' in way['tags']: + layer['l'].append(way) + if 'railway' in way['tags']: + layer['r'].append(way) + if 'amenity' in way['tags']: + layer['a'].append(way) + if 'leisure' in way['tags']: + layer['le'].append(way) + if 'barrier' in way['tags']: + layer['ba'].append(way) + if 'highway' in way['tags']: + layer['h1'].append(way) + layer['h2'].append(way) + if 'boundary' in way['tags']: + layer['bo'].append(way) + #else: + # empty = True + # for key in way['tags'].keys(): + # if not (key in ['layer', 'note']): + # empty = False + # if not empty: + # print 'Unknown kind of way:', way['tags'] + return layers, way_map + + +layers, way_map = construct_way_map() + +def draw_raw_ways(): + for way_id in way_map: + way = way_map[way_id] + draw_path(way['nodes'], 'stroke:#FFFFFF;fill:none;stroke-width:0.2;') + +def draw_ways(): + for level in sorted(layers.keys()): + layer = layers[level] + #for entity in ['b', 'h1', 'h2', 'r', 'n', 'l', 'a', 'le', 'ba']: + for way in layer['le']: + if way['tags']['leisure'] == 'park': + style = 'fill:#' + grass_color + ';' + else: + continue + draw_path(way['nodes'], style) + for way in layer['l']: + ma = Vector() + mi = Vector(10000, 10000) + for node_id in way['nodes']: + node = node_map[node_id] + flinged = flinger.fling(node) + if flinged.x > ma.x: ma.x = flinged.x + if flinged.y > ma.y: ma.y = flinged.y + if flinged.x < mi.x: mi.x = flinged.x + if flinged.y < mi.y: mi.y = flinged.y + c = Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0) + if way['tags']['landuse'] == 'grass': + style = 'fill:#' + grass_color + ';stroke:none;' + draw_path(way['nodes'], style) + elif way['tags']['landuse'] == 'conservation': + style = 'fill:#' + grass_color + ';stroke:none;' + draw_path(way['nodes'], style) + elif way['tags']['landuse'] == 'forest': + style = 'fill:#' + wood_color + ';stroke:none;' + draw_path(way['nodes'], style) + elif way['tags']['landuse'] == 'garages': + style = 'fill:#' + parking_color + ';stroke:none;' + draw_path(way['nodes'], style) + draw_point_shape('parking', c.x, c.y, '444444') + elif way['tags']['landuse'] in ['residential', 'commercial']: + continue + else: + style = 'fill:#0000FF;stroke:none;' + draw_path(way['nodes'], style) + for way in layer['a']: + ma = Vector() + mi = Vector(10000, 10000) + for node_id in way['nodes']: + node = node_map[node_id] + flinged = flinger.fling(node) + if flinged.x > ma.x: ma.x = flinged.x + if flinged.y > ma.y: ma.y = flinged.y + if flinged.x < mi.x: mi.x = flinged.x + if flinged.y < mi.y: mi.y = flinged.y + c = Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0) + if way['tags']['amenity'] == 'parking': + style = 'fill:#' + parking_color + ';stroke:none;' + draw_path(way['nodes'], style) + draw_point_shape('parking', c.x, c.y, '444444') + elif way['tags']['amenity'] == 'school': + continue + else: + style = 'fill:#0000FF;stroke:none;' + draw_path(way['nodes'], style) + for way in layer['n']: + if way['tags']['natural'] == 'wood': + style = 'fill:#' + wood_color + ';stroke:none;' + elif way['tags']['natural'] == 'scrub': + style = 'fill:#' + wood_color + ';stroke:none;' + elif way['tags']['natural'] == 'sand': + style = 'fill:#' + sand_color + ';stroke:none;' + elif way['tags']['natural'] == 'beach': + style = 'fill:#' + beach_color + ';stroke:none;' + elif way['tags']['natural'] == 'desert': + style = 'fill:#' + desert_color + ';stroke:none;' + elif way['tags']['natural'] == 'water': + style = 'fill:#' + water_color + ';stroke:#' + water_border_color + ';stroke-width:1.0;' + elif way['tags']['natural'] == 'forest': + style = 'fill:#' + wood_color + ';stroke:none;' + else: + continue + draw_path(way['nodes'], style) + for way in layer['r']: + v = way['tags']['railway'] + style = 'fill:none;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:butt;stroke-width:' + if v == 'subway': style += '10;stroke:#DDDDDD;' + if v in ['narrow_gauge', 'tram']: + style += '2;stroke:#000000;' + else: + continue + draw_path(way['nodes'], style) + for way in layer['h1']: + if 'tunnel' in way['tags'] and way['tags']['tunnel'] == 'yes': + style = 'fill:none;stroke:#FFFFFF;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:butt;stroke-width:10;' + draw_path(way['nodes'], style) + for way in layer['h1']: + v = way['tags']['highway'] + style = 'fill:none;stroke:#AAAAAA;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:butt;stroke-width:' + if v == 'motorway': style += '30' + elif v == 'trunk': style += '25' + elif v == 'primary': style += '20;stroke:#AA8800' + elif v == 'secondary': style += '13' + elif v == 'tertiary': style += '11' + elif v == 'unclassified': style += '9' + elif v == 'residential': style += '8' + elif v == 'service': style += '7' + elif v == 'track': style += '3' + elif v in ['footway', 'pedestrian']: style += '2' + elif v == 'steps': style += '5;stroke-dasharray:1,2;stroke-linecap:butt' + elif v == 'path': style += '1;stroke-dasharray:5,5;stroke-linecap:butt' + else: + continue + style += ';' + draw_path(way['nodes'], style) + for way in layer['h2']: + v = way['tags']['highway'] + style = 'fill:none;stroke:#FFFFFF;stroke-linecap:butt;stroke-linejoin:round;stroke-width:' + if v == 'motorway': style += '28' + elif v == 'trunk': style += '23' + elif v == 'primary': style += '19;stroke:#FFDD66' + elif v == 'secondary': style += '11' + elif v == 'tertiary': style += '9' + elif v == 'unclassified': style += '7' + elif v == 'residential': style += '6' + elif v == 'service': style += '5' + else: + continue + style += ';' + draw_path(way['nodes'], style) + for way in layer['b']: + floors = 0 + text_y = 0 + #if 'building:levels' in way['tags']: + #floors = float(way['tags']['building:levels']) + draw_path(way['nodes'], 'fill:#D0D0C0;stroke:#AAAAAA;opacity:1.0;') + ma = Vector() + mi = Vector(10000, 10000) + for node_id in way['nodes']: + node = node_map[node_id] + flinged = flinger.fling(node) + if flinged.x > ma.x: ma.x = flinged.x + if flinged.y > ma.y: ma.y = flinged.y + if flinged.x < mi.x: mi.x = flinged.x + if flinged.y < mi.y: mi.y = flinged.y + c = Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0) + for tag in way['tags']: + v = way['tags'][tag] + if tag == 'building': + if v == 'yes': + pass + elif v == 'apartments': + draw_point_shape('apartments', c.x, c.y, '444444') + elif v == 'kindergarten': + draw_point_shape('playground', c.x, c.y, '444444') + elif tag == 'amenity': + if v == 'cafe': + draw_point_shape('cafe', c.x, c.y, '444444') + elif v == 'theatre': + draw_point_shape('theatre', c.x, c.y, '444444') + elif v == 'fast_food': + draw_point_shape('fast_food', c.x, c.y, '444444') + elif v == 'snack_cart': + draw_point_shape('cafe', c.x, c.y, '444444') + elif tag == 'shop': + if v == 'clothes': + draw_point_shape('shop_clothes', c.x, c.y, '444444') + elif v == 'gift': + draw_point_shape('shop_gift', c.x, c.y, '444444') + elif tag == 'power': + draw_point_shape('electricity', c.x, c.y, '444444') + elif tag in ['name', 'addr:housenumber', 'cladr:code', + 'addr:city', 'addr:street', 'website', + 'wikidata'] or \ + 'name' in tag or 'wikipedia' in tag: + draw_text(v, str(c.x), str(c.y + 18 + text_y), '444444') + text_y += 10 + elif tag == 'addr:country': + if v == 'RU': + draw_text('Россия', str(c.x), str(c.y + 18 + text_y), '444444') + else: + draw_text(v, str(c.x), str(c.y + 18 + text_y), '444444') + text_y += 10 + elif tag in ['layer', 'height']: + pass + elif tag in ['building:levels']: + pass + else: + kk = tag + vv = unicode(v) + if ('way ' + kk + ': ' + vv) in missed_tags: + missed_tags['way ' + kk + ': ' + vv] += 1 + else: + missed_tags['way ' + kk + ': ' + vv] = 1 + for way in layer['le']: + ma = Vector() + mi = Vector(10000, 10000) + for node_id in way['nodes']: + node = node_map[node_id] + flinged = flinger.fling(node) + if flinged.x > ma.x: ma.x = flinged.x + if flinged.y > ma.y: ma.y = flinged.y + if flinged.x < mi.x: mi.x = flinged.x + if flinged.y < mi.y: mi.y = flinged.y + c = Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0) + if way['tags']['leisure'] == 'playground': + style = 'fill:#' + playground_color + ';opacity:0.2;' + draw_point_shape('playground', c.x, c.y, '444444') + elif way['tags']['leisure'] == 'garden': + style = 'fill:#' + grass_color + ';' + elif way['tags']['leisure'] == 'pitch': + style = 'fill:#' + playground_color + ';opacity:0.2;' + elif way['tags']['leisure'] == 'park': + continue + else: + style = 'fill:#FF0000;opacity:0.2;' + draw_path(way['nodes'], style) + for way in layer['ba']: + if way['tags']['barrier'] == 'hedge': + style += 'fill:none;stroke:#' + wood_color + ';stroke-width:4;' + else: + style += 'fill:none;stroke:#000000;stroke-width:1;opacity:0.4;' + draw_path(way['nodes'], style) + for way in layer['bo']: + style += 'fill:none;stroke:#FF0000;stroke-width:0.5;stroke-dahsarray:10,20;' + draw_path(way['nodes'], style) + +print 'Done.' + +# Nodes drawing + +def draw_raw_nodes(): + for node_id in node_map: + node = node_map[node_id] + flinged = flinger.fling(node) + output_file.circle(flinged.x, flinged.y, 0.2, color='FFFFFF') + +def draw_nodes(): + print 'Draw nodes...' + + for element in content.childNodes[0].childNodes: + if element.nodeName != 'node': + continue + flinged = flinger.fling(Geo(float(element.attributes['lat'].value), + float(element.attributes['lon'].value))) + text_y = 0 + pairs = {} + for child_node in element.childNodes: + if isinstance(child_node, xml.dom.minidom.Element): + if child_node.tagName == 'tag': + pairs[child_node.attributes['k'].value] = child_node.attributes['v'].value + fill = '444444' + if 'colour' in pairs: + if pairs['colour'] == 'blue': + fill='2233AA' + radius=3 + for k in pairs: + v = pairs[k] + x = `flinged.x` + y = `flinged.y` + if k == 'amenity': + if v in ['bench', 'bicycle_parking', 'waste_basket', + 'restaurant', 'pharmacy', 'drinking_water', 'toilets', + 'fast_food', 'theatre']: + draw_point_shape(v, x, y, fill) + elif v == 'clinic': + draw_point(d_clinic, x, y, fill) + elif v == 'fountain': + draw_point_shape('fountain', x, y, water_border_color) + elif v == 'recycling': + if not 'recycling_type' in pairs: + draw_point_shape('recycling', x, y, fill) + else: + point(k, v, flinged.x, flinged.y, fill) + elif k == 'artwork_type': + if v == 'statue': + draw_point_shape('monument', x, y, fill) + if v == 'sculpture': + draw_point_shape('monument', x, y, fill) + else: + point(k, v, flinged.x, flinged.y, fill) + elif k == 'barrier': + if v == 'lift_gate': + draw_point_shape('liftgate', x, y, fill) + elif k in ['crossing', 'crossing_ref']: + if v == 'zebra': + draw_point(d_crossing, x, y, fill) + elif k == 'entrance': + draw_point_shape('entrance', x, y, fill) + elif k == 'highway': + if v == 'street_lamp': + draw_point(d_street_lamp, x, y, fill) + elif v == 'bus_stop': + draw_point_shape('bus_stop', x, y, fill) + elif v == 'traffic_signals': + draw_point(d_traffic_signal, x, y, fill) + elif v == 'crossing': + if not ('crossing' in pairs): + draw_point(d_crossing, x, y, fill) + else: + point(k, v, flinged.x, flinged.y, fill) + elif k == 'man_made': + if v == 'pole': + draw_point_shape('pole', x, y, fill) + elif v == 'flagpole': + draw_point_shape('flagpole', x, y, fill) + else: + point(k, v, flinged.x, flinged.y, fill) + elif k == 'natural': + if v == 'tree': + if 'denotation' in pairs and pairs['denotation'] == 'urban': + draw_point_shape('urban_tree', x, y, wood_color) + else: + draw_point(d_tree, x, y, wood_color) + elif v == 'cave_entrance': + draw_point_shape('cave', x, y, fill) + elif v == 'bush': + draw_point_shape('bush', x, y, wood_color) + else: + point(k, v, flinged.x, flinged.y, fill) + elif k == 'recycling_type': + if v == 'centre': + draw_point_shape('recycling', x, y, fill) + else: + draw_point_shape('recycling', x, y, fill) + elif k == 'shop': + if v == 'florist': + draw_point_shape('florist', x, y, fill) + elif v in ['clothes', 'shoes', 'gift']: + draw_point_shape('shop_' + v, x, y, fill) + else: + point(k, v, flinged.x, flinged.y, fill) + elif k == 'traffic_calming': + if v == 'bump': + draw_point_shape('bump', x, y, fill) + else: + point(k, v, flinged.x, flinged.y, fill) + elif k == 'emergency': + if v == 'fire_hydrant': + draw_point_shape(v, x, y, fill) + elif k == 'historic': + if v == 'memorial': + draw_point_shape('monument', x, y, fill) + elif k == 'tourism': + if v == 'artwork': + if not ('artwork_type' in pairs): + draw_point_shape('monument', x, y, fill) + if v == 'attraction': + draw_point_shape('monument', x, y, fill) + elif k in [ + 'operator', 'contact:facebook', 'contact:phone', + 'opening_hours', 'cuisine', 'network', 'website', + 'contact:website', 'phone', 'branch', 'route_ref', + 'addr:flats', 'brand', 'ref', 'addr:street', 'wikipedia', + ] or ('name' in k): + if k == 'route_ref': + v = v.replace(';', ' ') + draw_text(v, x, str(flinged.y + 18 + text_y), fill) + text_y += 10 + elif k in ['layer', 'level', 'source', 'note', 'description']: + pass # NOTHING TO DRAW + else: + point(k, v, flinged.x, flinged.y, fill) + +print 'Done.' + +#draw_raw_nodes() +#draw_raw_ways() + +draw_ways() +draw_nodes() + +if flinger.space.x == 0: + output_file.rect(0, 0, w, flinger.space.y, color='FFFFFF') + output_file.rect(0, h - flinger.space.y, w, flinger.space.y, color='FFFFFF') + +output_file.end() + +print '\nMissing tags:\n' +top_missed_tags = reversed(sorted(missed_tags.keys(), key=lambda x: -missed_tags[x])) +for tag in top_missed_tags: + print tag + ' (' + str(missed_tags[tag]) + ')' + +sys.exit(1) + +top_authors = sorted(authors.keys(), key=lambda x: -authors[x]) +for author in top_authors: + print author + ': ' + str(authors[author])