#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import unicode_literals """ Simple tool for working with OpenStreetMap data. Author: Sergey Vartanov (me@enzet.ru). """ import copy import datetime import os import process import re import sys import xml.dom.minidom import yaml import extract_icon import osm_reader import ui from flinger import GeoFlinger, Geo sys.path.append('../lib') import svg from vector import Vector background_color = 'DDDDDD' # 'DDDDDD' outline_color = 'FFFFFF' beach_color = 'F0E0C0' building_color = 'EEEEEE' # 'D0D0C0' building_border_color = 'C4C4C4' # 'AAAAAA' construction_color = 'CCCCCC' cycle_color = '4444EE' desert_color = 'F0E0D0' #foot_color = '888844' foot_color = 'B89A74' foot_border_color = 'FFFFFF' grass_color = 'CFE0A8' grass_border_color = 'BFD098' parking_color = 'DDCC99' playground_color = '884400' primary_border_color = '888888' # 'AA8800' primary_color = 'FFFFFF' # 'FFDD66' private_access_color = '884444' road_border_color = 'CCCCCC' sand_color = 'F0E0D0' water_color = 'AACCFF' water_border_color = '6688BB' wood_color = 'B8CC84' wood_border_color = 'A8BC74' icons_file_name = '../icons/icons.svg' tags_file_name = '../data/tags.yml' colors_file_name = '../data/colors.yml' missed_tags_file_name = '../missed_tags.yml' tags_to_write = set(['operator', 'opening_hours', 'cuisine', 'network', 'website', 'website_2', 'STIF:zone', 'opening_hours:url', 'phone', 'branch', 'route_ref', 'brand', 'ref', 'wikipedia', 'description', 'level', 'wikidata', 'name', 'alt_name', 'image', 'fax', 'old_name', 'artist_name', 'int_name', 'official_name', 'full_name', 'email', 'designation', 'min_height', 'height', 'inscription', 'start_date', 'created_by', 'naptan:verified', 'url', 'naptan:AtcoCode', 'naptan:Landmark', 'naptan:Indicator', 'collection_times', 'naptan:Street', 'naptan:PlusbusZoneRef', 'naptan:Crossing', 'local_ref', 'naptan:CommonName', 'survey:date', 'naptan:NaptanCode', 'postal_code', 'uk_postcode_centroid', 'fhrs:rating_date', 'fhrs:local_authority_id', 'destination', 'fhrs:id', 'naptan:ShortCommonName', 'flickr', 'royal_cypher', 'is_in', 'booth', 'naptan:AltStreet', 'media:commons', 'ref_no', 'uri', 'fhrs:inspectiondate', 'telephone', 'naptan:AltCommonName', 'end_date', 'facebook', 'naptan:Notes', 'voltage', 'last_collection', 'twitter', 'ele', 'information', 'phone_1', 'cyclestreets_id', 'cladr:code', # To draw 'naptan:Bearing', 'species', 'taxon', 'seats', 'capacity', 'fhrs:rating', 'fhrs:confidence_management', 'fhrs:hygiene', 'genus', 'platforms', 'naptan:BusStopType']) prefix_to_write = set(['addr', 'contact', 'name', 'operator', 'wikipedia', 'alt_name', 'description', 'old_name', 'inscription', 'route_ref', 'is_in', 'website', 'ref', # To draw 'species', 'taxon', 'genus']) tags_to_skip = set(['note', 'layer', 'source', 'building:part', 'fixme', 'comment', 'FIXME', 'source_ref', 'naptan:verified:note', 'building:levels', 'ref:opendataparis:adresse', 'ref:opendataparis:geo_point_2d', 'created_by']) prefix_to_skip = set(['source']) def get_d_from_file(file_name): path, x, y = icons.get_path(file_name) if path: return path, x, y else: # print 'No such icon: ' + file_name # TODO: add to missed icons return 'M 4,4 L 4,10 10,10 10,4 z', 0, 0 def get_min_max(node_map): key = node_map.keys()[0] maximum = Geo(node_map[key]['lon'], node_map[key]['lat']) minimum = Geo(node_map[key]['lon'], node_map[key]['lat']) for node_id in node_map: node = node_map[node_id] if node['lat'] > maximum.lat: maximum.lat = node['lat'] if node['lat'] < minimum.lat: minimum.lat = node['lat'] if node['lon'] > maximum.lon: maximum.lon = node['lon'] if node['lon'] < minimum.lon: minimum.lon = node['lon'] return minimum, maximum def get_path(nodes, shift=Vector()): path = '' prev_node = None for node_id in nodes: node = node_map[node_id] flinged1 = flinger.fling(Geo(node['lat'], node['lon'])) + shift if prev_node: flinged2 = flinger.fling(Geo(prev_node['lat'], prev_node['lon'])) + shift path += ('L ' + `flinged1.x` + ',' + `flinged1.y` + ' ') else: path += ('M ' + `flinged1.x` + ',' + `flinged1.y` + ' ') prev_node = node_map[node_id] if nodes[0] == nodes[-1]: path += 'Z' return path def draw_point_shape(name, x, y, fill): if not isinstance(name, list): name = [name] for one_name in name: shape, xx, yy = get_d_from_file(one_name) draw_point_outline(shape, x, y, fill, size=16, xx=xx, yy=yy) for one_name in name: shape, xx, yy = get_d_from_file(one_name) draw_point(shape, x, y, fill, size=16, xx=xx, yy=yy) def draw_point_outline(shape, x, y, fill, size=16, xx=0, yy=0): x = int(float(x)) y = int(float(y)) opacity = 0.5 r = int(fill[0:2], 16) g = int(fill[2:4], 16) b = int(fill[4:6], 16) Y = 0.2126 * r + 0.7152 * g + 0.0722 * b if Y > 200: outline_fill = '000000' opacity = 0.3 output_file.write('\n') def draw_point(shape, x, y, fill, size=16, xx=0, yy=0): x = int(float(x)) y = int(float(y)) output_file.write('\n') def draw_text(text, x, y, fill, size=10): if type(text) == unicode: text = text.encode('utf-8') text = text.replace('&', 'and') output_file.write('' + text + '') output_file.write('' + text + '') def point(k, v, x, y, fill, text_y): text = k + ': ' + v if type(text) == unicode: text = text.encode('utf-8') draw_text(text, x, float(y) + text_y + 18, '734A08') def construct_text(tags, processed): for key in tags: tags[key] = tags[key].replace('"', '"') texts = [] addr = None name = None alt_name = None if 'name' in tags: name = tags['name'] tags.pop('name', None) if 'name:ru' in tags: if not name: name = tags['name:ru'] tags.pop('name:ru', None) tags.pop('name:ru', None) if 'name:en' in tags: if not name: name = tags['name:en'] tags.pop('name:en', None) tags.pop('name:en', None) if 'alt_name' in tags: if alt_name: alt_name += ', ' else: alt_name = '' alt_name += tags['alt_name'] if 'old_name' in tags: if alt_name: alt_name += ', ' else: alt_name = '' alt_name += 'бывш. ' + tags['old_name'] if 'addr:postcode' in tags: if addr: addr += ', ' else: addr = '' addr += tags['addr:postcode'] tags.pop('addr:postcode', None) if 'addr:country' in tags: if tags['addr:country'] == 'RU': addr = 'Россия' else: addr = tags['addr:country'] tags.pop('addr:country', None) if 'addr:city' in tags: if addr: addr += ', ' else: addr = '' addr += tags['addr:city'] tags.pop('addr:city', None) if 'addr:street' in tags: if addr: addr += ', ' else: addr = '' street = tags['addr:street'] if street.startswith('улица '): street = 'ул. ' + street[len('улица '):] addr += street tags.pop('addr:street', None) if 'addr:housenumber' in tags: if addr: addr += ', ' else: addr = '' addr += tags['addr:housenumber'] tags.pop('addr:housenumber', None) if name: texts.append({'text': name, 'fill': '000000'}) if alt_name: texts.append({'text': '(' + alt_name + ')'}) if addr: texts.append({'text': addr}) if 'route_ref' in tags: texts.append({'text': tags['route_ref'].replace(';', ' ')}) tags.pop('route_ref', None) if 'cladr:code' in tags: texts.append({'text': tags['cladr:code'], 'size': 7}) tags.pop('cladr:code', None) if 'website' in tags: link = tags['website'] if link[:7] == 'http://': link = link[7:] if link[:8] == 'https://': link = link[8:] if link[:4] == 'www.': link = link[4:] if link[-1] == '/': link = link[:-1] link = link[:50] + ('...' if len(tags['website']) > 50 else '') texts.append({'text': link, 'fill': '000088'}) tags.pop('website', None) for k in ['phone']: if k in tags: texts.append({'text': tags[k], 'fill': '444444'}) tags.pop(k) for tag in tags: if to_write(tag) and not (tag in processed): #texts.append({'text': tag + ': ' + tags[tag]}) texts.append({'text': tags[tag]}) return texts def wr(text, x, y, fill, text_y, size=10): if type(text) == unicode: text = text.encode('utf-8') draw_text(text, x, float(y) + text_y + 8, fill, size=size) # Ways drawing 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 line_center(node_ids): ma = Vector() mi = Vector(10000, 10000) for node_id in node_ids: node = node_map[node_id] flinged = flinger.fling(Geo(node['lat'], node['lon'])) 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 return Vector((ma.x + mi.x) / 2.0, (ma.y + mi.y) / 2.0) def get_float(string): try: return float(string) except ValueError: return 0 def get_user_color(user): if user == '': return '000000' rgb = hex(abs(hash(options.seed + user)))[-6:] r = int(rgb[0:2], 16) g = int(rgb[2:4], 16) b = int(rgb[4:6], 16) c = (r + g + b) / 3. cc = 0 r = r * (1 - cc) + c * cc g = g * (1 - cc) + c * cc b = b * (1 - cc) + c * cc h = hex(int(r))[2:] + hex(int(g))[2:] + hex(int(b))[2:] return '0' * (6 - len(h)) + h def construct_ways(drawing): for way_id in way_map: way = way_map[way_id] user = way['user'] if 'user' in way else '' construct_way(drawing, way['nodes'], way['tags'], None, user) def construct_way(drawing, nodes, tags, path, user): is_area = None if nodes: is_area = nodes[0] == nodes[-1] layer = 0 if 'layer' in tags: layer = get_float(tags['layer']) if nodes: c = line_center(nodes) user_color = get_user_color(user) if options.user_coloring: drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'path': path, 'style': 'fill:none;stroke:#' + user_color + ';stroke-width:1.5;'}) return if 'natural' in tags: v = tags['natural'] style = 'stroke:none;' if v == 'wood': style += 'fill:#' + wood_color + ';' layer += 0.2 elif v == 'scrub': style += 'fill:#' + wood_color + ';' layer += 0.2 elif v == 'sand': style += 'fill:#' + sand_color + ';' layer += 0.1 elif v == 'beach': style += 'fill:#' + beach_color + ';' layer += 0.1 elif v == 'desert': style += 'fill:#' + desert_color + ';' layer += 0.1 elif v == 'forest': style += 'fill:#' + wood_color + ';' layer += 0.2 elif v == 'tree_row': style += 'fill:none;stroke:#' + wood_color + ';stroke-width:5;' layer += 0.2 elif v == 'water': style = 'fill:#' + water_color + ';stroke:#' + \ water_border_color + ';stroke-width:1.0;' layer += 0.2 drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'landuse' in tags: style = 'fill:none;stroke:none;' if tags['landuse'] == 'grass': style = 'fill:#' + grass_color + ';stroke:#' + grass_border_color + ';' layer += 0.1 elif tags['landuse'] == 'conservation': style = 'fill:#' + grass_color + ';stroke:none;' layer += 0.1 elif tags['landuse'] == 'forest': style = 'fill:#' + wood_color + ';stroke:none;' layer += 0.2 elif tags['landuse'] == 'garages': style = 'fill:#' + parking_color + ';stroke:none;' layer += 0.2 shapes, fill, processed = \ process.get_icon(tags, scheme, '444444') if nodes: drawing['nodes'].append({'shapes': shapes, 'tags': tags, 'x': c.x, 'y': c.y, 'color': fill, 'path': path, 'processed': processed}) elif tags['landuse'] == 'construction': layer += 0.1 style = 'fill:#' + construction_color + ';stroke:none;' elif tags['landuse'] in ['residential', 'commercial']: return drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'building' in tags: style = 'fill:none;stroke:none;' text_y = 0 layer += 0.6 style = 'fill:#' + building_color + ';stroke:#' + \ building_border_color + ';opacity:1.0;' shapes, fill, processed = process.get_icon(tags, scheme, '444444') if 'height' in tags: layer += float(tags['height']) if nodes: drawing['nodes'].append({'shapes': shapes, 'x': c.x, 'y': c.y, 'color': fill, 'priority': 1, 'processed': processed, 'tags': tags, 'path': path}) drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'amenity' in tags: style = 'fill:none;stroke:none;' layer += 0.2 if tags['amenity'] == 'parking': style = 'fill:#' + parking_color + ';stroke:none;opacity:0.5;' shapes, fill, processed = process.get_icon(tags, scheme, '444444') if nodes: drawing['nodes'].append({'shapes': shapes, 'x': c.x, 'y': c.y, 'color': fill, 'priority': 1, 'processed': processed, 'tags': tags, 'path': path}) drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'waterway' in tags: style = 'fill:none;stroke:none;' layer += 0.2 if tags['waterway'] == 'riverbank': style = 'fill:#' + water_color + ';stroke:#' + \ water_border_color + ';stroke-width:1.0;' elif tags['waterway'] == 'river': style = 'fill:none;stroke:#' + water_color + ';stroke-width:10.0;' drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'railway' in tags: style = 'fill:none;stroke:none;' layer += 0.45 v = tags['railway'] style = 'fill:none;stroke-dasharray:none;stroke-linejoin:round;' + \ 'stroke-linecap:round;stroke-width:' if v == 'subway': style += '10;stroke:#DDDDDD;' if v in ['narrow_gauge', 'tram']: style += '2;stroke:#000000;' else: return drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'highway' in tags: style = 'fill:none;stroke:none;' layer += 0.4 v = tags['highway'] if 'tunnel' in tags and tags['tunnel'] == 'yes': style = 'fill:none;stroke:#FFFFFF;stroke-dasharray:none;' + \ 'stroke-linejoin:round;stroke-linecap:round;stroke-width:10;' drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer - 100, 'priority': 50, 'style': style, 'path': path}) style = 'fill:none;stroke:#' + road_border_color + \ ';stroke-dasharray:none;' + \ 'stroke-linejoin:round;stroke-linecap:round;stroke-width:' if v == 'motorway': style += '30' elif v == 'trunk': style += '25' elif v == 'primary': style += '20;stroke:#' + primary_border_color elif v == 'secondary': style += '13' elif v == 'tertiary': style += '25' elif v == 'unclassified': style += '17' elif v == 'residential': style += '17' elif v == 'service': if 'service' in tags and tags['service'] == 'parking_aisle': style += '7' else: style += '11' elif v == 'track': style += '3' elif v in ['footway', 'pedestrian', 'cycleway']: style += '3;stroke:#' + foot_border_color else: style = None if style: style += ';' drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer - 0.1, 'priority': 50, 'style': style, 'path': path}) style = 'fill:none;stroke:#FFFFFF;stroke-linecap:round;' + \ 'stroke-linejoin:round;stroke-width:' if v == 'motorway': style += '28' elif v == 'trunk': style += '23' elif v == 'primary': style += '19;stroke:#' + primary_color elif v == 'secondary': style += '11' elif v == 'tertiary': style += '23' elif v == 'unclassified': style += '15' elif v == 'residential': style += '15' elif v == 'service': if 'service' in tags and tags['service'] == 'parking_aisle': style += '5' else: style += '9' elif v == 'cycleway': style += '1;stroke-dasharray:8,2;istroke-linecap:butt;' + \ 'stroke:#' + cycle_color elif v in ['footway', 'pedestrian']: if 'area' in tags and tags['area'] == 'yes': style += '1;stroke:none;fill:#DDDDDD' else: style += '1.5;stroke-dasharray:8,2;stroke-linecap:butt;' + \ 'stroke:#' + foot_color elif v == 'steps': style += '5;stroke-dasharray:1,2;stroke-linecap:butt;' + \ 'stroke:#' + foot_color elif v == 'path': style += '1;stroke-dasharray:5,5;stroke-linecap:butt;' + \ 'stroke:#' + foot_color style += ';' drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'access' in tags and tags['access'] == 'private': drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer + 0.1, 'priority': 50, 'path': path, 'style': 'fill:none;' + \ 'stroke:#' + private_access_color + ';' + \ 'stroke-linecap:butt;' + \ 'stroke-width:10;stroke-dasharray:1,5;' + \ 'opacity:0.4;'}) if 'leisure' in tags: style = 'fill:none;stroke:none;' layer += 0.2 if tags['leisure'] == 'playground': style = 'fill:#' + playground_color + ';opacity:0.2;' if nodes: draw_point_shape('toy_horse', c.x, c.y, '444444') elif tags['leisure'] == 'garden': style = 'fill:#' + grass_color + ';' elif tags['leisure'] == 'pitch': style = 'fill:#' + playground_color + ';opacity:0.2;' elif tags['leisure'] == 'park': return else: style = 'fill:#FF0000;opacity:0.2;' drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'barrier' in tags: style = 'fill:none;stroke:none;' layer += 0.5 if tags['barrier'] == 'hedge': style += 'fill:none;stroke:#' + wood_color + ';stroke-width:4;' elif tags['barrier'] == 'fense': style += 'fill:none;stroke:#000000;stroke-width:1;opacity:0.4;' elif tags['barrier'] == 'kerb': style += 'fill:none;stroke:#000000;stroke-width:1;opacity:0.2;' else: style += 'fill:none;stroke:#000000;stroke-width:1;opacity:0.3;' drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'border' in tags: style = 'fill:none;stroke:none;' style += 'fill:none;stroke:#FF0000;stroke-width:0.5;' + \ 'stroke-dahsarray:10,20;' drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) if 'area:highway' in tags: style = 'fill:none;stroke:none;' if tags['area:highway'] == 'yes': style += 'fill:#FFFFFF;stroke:#DDDDDD;stroke-width:1;' drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, 'priority': 50, 'style': style, 'path': path}) #drawing['ways'].append({'kind': 'way', 'nodes': nodes, 'layer': layer, # 'priority': 50, 'style': style, 'path': path}) def glue_ways(ways): new_ways = [] processed = [] for way in ways: if way['id'] in processed: continue if way['nodes'][0] == way['nodes'][-1]: new_ways.append(way['nodes']) processed.append(way['id']) for other_way in ways: if way == other_way: continue if way['id'] in processed or other_way['id'] in processed: break if way['nodes'][0] == other_way['nodes'][0]: o = other_way['nodes'][1:] o.reverse() way['nodes'] = o + way['nodes'] processed.append(other_way['id']) elif way['nodes'][0] == other_way['nodes'][-1]: way['nodes'] = other_way['nodes'][:-1] + way['nodes'] processed.append(other_way['id']) elif way['nodes'][-1] == other_way['nodes'][-1]: o = other_way['nodes'][:-1] o.reverse() way['nodes'] += o processed.append(other_way['id']) elif way['nodes'][-1] == other_way['nodes'][0]: way['nodes'] += other_way['nodes'][1:] processed.append(other_way['id']) if way['nodes'][0] == way['nodes'][-1]: new_ways.append(way['nodes']) processed.append(way['id']) for way in ways: if not (way['id'] in processed): new_ways.append(way['nodes']) return new_ways def construct_relations(drawing): for relation_id in relation_map: relation = relation_map[relation_id] tags = relation['tags'] if 'type' in tags and tags['type'] == 'multipolygon': style = 'fill:#FFEEEE;stroke:#FF0000;stroke-width:0.5;' inners, outers = [], [] for member in relation['members']: if member['type'] == 'way': if member['role'] == 'inner': if member['ref'] in way_map: inners.append(way_map[member['ref']]) elif member['role'] == 'outer': if member['ref'] in way_map: outers.append(way_map[member['ref']]) p = '' inners_path = glue_ways(inners) outers_path = glue_ways(outers) for way in outers_path: path = get_path(way) p += path + ' ' for way in inners_path: way.reverse() path = get_path(way) p += path + ' ' construct_way(drawing, None, tags, p, '') # 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 no_draw(key): if key in tags_to_write or key in tags_to_skip: return True for prefix in prefix_to_write.union(prefix_to_skip): if key[:len(prefix) + 1] == prefix + ':': return True return False def to_write(key): if key in tags_to_skip: return False if key in tags_to_write: return True for prefix in prefix_to_write: if key[:len(prefix) + 1] == prefix + ':': return True return False def draw_shapes(shapes, overlap, points, x, y, fill, show_missed_tags, tags, processed): text_y = 0 xxx = -(len(shapes) - 1) * 8 if overlap != 0: for shape in shapes: has_space = True for p in points[-1000:]: if x + xxx - overlap <= p.x <= x + xxx + overlap and \ y - overlap <= p.y <= y + overlap: has_space = False break if has_space: draw_point_shape(shape, x + xxx, y, fill) points.append(Vector(x + xxx, y)) xxx += 16 else: for shape in shapes: draw_point_shape(shape, x + xxx, y, fill) xxx += 16 if options.draw_captions: write_tags = construct_text(tags, processed) for text_struct in write_tags: fill = text_struct['fill'] if 'fill' in text_struct else '444444' size = text_struct['size'] if 'size' in text_struct else 10 text_y += size + 1 wr(text_struct['text'], x, y, fill, text_y, size=size) if show_missed_tags: for k in tags: if not no_draw(k) and not k in processed: point(k, tags[k], x, y, fill, text_y) text_y += 10 def construct_nodes(drawing): """ Draw nodes. """ print 'Draw nodes...' start_time = datetime.datetime.now() node_number = 0 processed_tags = 0 skipped_tags = 0 s = sorted(node_map.keys(), key=lambda x: -node_map[x]['lat']) for node_id in s: node_number += 1 ui.write_line(node_number, len(node_map)) node = node_map[node_id] flinged = flinger.fling(Geo(node['lat'], node['lon'])) x = flinged.x y = flinged.y if 'tags' in node: tags = node['tags'] else: tags = {} shapes, fill, processed = process.get_icon(tags, scheme) if options.user_coloring: fill = get_user_color(node['user']) for k in tags: if k in processed or no_draw(k): processed_tags += 1 else: skipped_tags += 1 for k in []: # tags: if to_write(k): draw_text(k + ': ' + tags[k], x, y + 18 + text_y, '444444') text_y += 10 #if show_missed_tags: # for k in tags: # v = tags[k] # if not no_draw(k) and not k in processed: # if ('node ' + k + ': ' + v) in missed_tags: # missed_tags['node ' + k + ': ' + v] += 1 # else: # missed_tags['node ' + k + ': ' + v] = 1 if not draw: continue drawing['nodes'].append({'shapes': shapes, 'x': x, 'y': y, 'color': fill, 'processed': processed, 'tags': tags}) ui.write_line(-1, len(node_map)) print 'Nodes drawed in ' + str(datetime.datetime.now() - start_time) + '.' print 'Tags processed: ' + str(processed_tags) + ', tags skipped: ' + \ str(skipped_tags) + ' (' + \ str(processed_tags / float(processed_tags + skipped_tags) * 100) + ' %).' def way_sorter(element): if 'layer' in element: return element['layer'] else: return 0 def node_sorter(element): if 'layer' in element: return element['layer'] else: return 0 def draw(drawing, show_missed_tags=False, overlap=14, draw=True): ways = sorted(drawing['ways'], key=way_sorter) for way in ways: if way['nodes']: path = get_path(way['nodes']) output_file.write('\n') else: output_file.write('\n') nodes = sorted(drawing['nodes'], key=node_sorter) for node in nodes: draw_shapes(node['shapes'], overlap, points, node['x'], node['y'], node['color'], show_missed_tags, node['tags'], node['processed']) # Actions options = ui.parse_options(sys.argv) if not options: sys.exit(1) input_file_name = options.input_file_name if not os.path.isfile(input_file_name): print 'Fatal: no such file: ' + input_file_name + '.' sys.exit(1) full = False # Full keys getting if options.user_coloring: full = True node_map, way_map, relation_map = osm_reader.parse_osm_file(input_file_name, parse_ways=options.draw_ways, parse_relations=options.draw_ways, full=full) output_file = svg.SVG(open(options.output_file_name, 'w+')) w, h = 2650, 2650 if 'size' in options: w = options.size[0] h = options.size[1] output_file.begin(w, h) output_file.rect(0, 0, w, h, color=background_color) minimum = Geo(180, 180) maximum = Geo(-180, -180) if 'boundary_box' in options: bb = options.boundary_box min1 = Geo(bb[2], bb[0]) max1 = Geo(bb[3], bb[1]) authors = {} missed_tags = {} points = [] icons_to_draw = [] # {shape, x, y, priority} scheme = yaml.load(open(tags_file_name)) scheme['cache'] = {} w3c_colors = yaml.load(open(colors_file_name)) for color_name in w3c_colors: scheme['colors'][color_name] = w3c_colors[color_name] if len(sys.argv) > 3: flinger = GeoFlinger(min1, max1, Vector(0, 0), Vector(w, h)) else: print 'Compute borders...' minimum, maximum = get_min_max(node_map) flinger = GeoFlinger(minimum, maximum, Vector(25, 25), Vector(975, 975)) print 'Done.' icons = extract_icon.IconExtractor(icons_file_name) drawing = {'nodes': [], 'ways': []} if options.draw_ways: construct_ways(drawing) construct_relations(drawing) construct_nodes(drawing) draw(drawing, show_missed_tags=options.show_missed_tags, overlap=options.overlap, draw=options.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') if options.show_index: print min1.lon, max1.lon print min1.lat, max1.lat lon_step = 0.001 lat_step = 0.001 matrix = [] lat_number = int((max1.lat - min1.lat) / lat_step) + 1 lon_number = int((max1.lon - min1.lon) / lon_step) + 1 for i in range(lat_number): row = [] for j in range(lon_number): row.append(0) matrix.append(row) for node_id in node_map: node = node_map[node_id] i = int((node['lat'] - min1.lat) / lat_step) j = int((node['lon'] - min1.lon) / lon_step) if (0 <= i < lat_number) and (0 <= j < lon_number): matrix[i][j] += 1 if 'tags' in node: matrix[i][j] += len(node['tags']) for way_id in way_map: way = way_map[way_id] if 'tags' in way: for node_id in way['nodes']: node = node_map[node_id] i = int((node['lat'] - min1.lat) / lat_step) j = int((node['lon'] - min1.lon) / lon_step) if (0 <= i < lat_number) and (0 <= j < lon_number): matrix[i][j] += len(way['tags']) / float(len(way['nodes'])) for i in range(lat_number): for j in range(lon_number): b = int(matrix[i][j] / 1) a = '%2x' % min(255, b) color = a + a + a color = color.replace(' ', '0') t1 = flinger.fling(Geo(min1.lat + i * lat_step, min1.lon + j * lon_step)) t2 = flinger.fling(Geo(min1.lat + (i + 1) * lat_step, min1.lon + (j + 1) * lon_step)) #output_file.write('\n') output_file.text(((t1 + t2) * 0.5).x, ((t1 + t2) * 0.5).y + 40, \ str(int(matrix[i][j])), size=80, color='440000', opacity=0.1, align='center') output_file.end() top_missed_tags = sorted(missed_tags.keys(), key=lambda x: -missed_tags[x]) missed_tags_file = open(missed_tags_file_name, 'w+') for tag in top_missed_tags: missed_tags_file.write('- {tag: "' + tag + '", count: ' + \ str(missed_tags[tag]) + '}\n') missed_tags_file.close() sys.exit(0) top_authors = sorted(authors.keys(), key=lambda x: -authors[x]) for author in top_authors: print author + ': ' + str(authors[author])