Cache for nodes; icons overlap; colors; new icons.

This commit is contained in:
Sergey Vartanov 2015-07-31 12:21:39 +03:00
parent b976e4b5d8
commit 64aa1432ee
5 changed files with 1052 additions and 692 deletions

1560
icons.svg

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 122 KiB

Before After
Before After

View file

@ -32,12 +32,6 @@ if not os.path.isfile(input_file_name):
print 'Fatal: no such file: ' + input_file_name + '.' print 'Fatal: no such file: ' + input_file_name + '.'
sys.exit(1) sys.exit(1)
#start_time = datetime.datetime.now()
#input_file = open(input_file_name)
#content = xml.dom.minidom.parse(input_file)
#input_file.close()
#print 'File readed in ' + str(datetime.datetime.now() - start_time) + '.'
node_map, way_map, relation_map = osm_reader.parse_osm_file(input_file_name) node_map, way_map, relation_map = osm_reader.parse_osm_file(input_file_name)
output_file = svg.SVG(open(sys.argv[2], 'w+')) output_file = svg.SVG(open(sys.argv[2], 'w+'))
@ -60,7 +54,7 @@ tags_to_write = ['operator', 'opening_hours', 'cuisine', 'network', 'website',
'description', 'level', 'wikidata', 'name', 'alt_name', 'description', 'level', 'wikidata', 'name', 'alt_name',
'image', 'fax', 'old_name', 'artist_name', 'int_name', 'image', 'fax', 'old_name', 'artist_name', 'int_name',
'official_name', 'full_name', 'email', 'designation', 'official_name', 'full_name', 'email', 'designation',
'min_height', 'height'] 'min_height', 'height', 'inscription', 'start_date']
prefix_to_write = ['addr', 'contact', 'name', 'operator', 'wikipedia', prefix_to_write = ['addr', 'contact', 'name', 'operator', 'wikipedia',
'alt_name', 'description', 'old_name', 'inscription', 'alt_name', 'description', 'old_name', 'inscription',
@ -372,9 +366,9 @@ def draw_ways():
elif v == 'residential': style += '8' elif v == 'residential': style += '8'
elif v == 'service': style += '7' elif v == 'service': style += '7'
elif v == 'track': style += '3' elif v == 'track': style += '3'
elif v in ['footway', 'pedestrian']: style += '2' elif v in ['footway', 'pedestrian']: style += '1;stroke-dasharray:3,3;stroke-linecap:butt;stroke:#888888'
elif v == 'steps': style += '5;stroke-dasharray:1,2;stroke-linecap:butt' elif v == 'steps': style += '5;stroke-dasharray:1,2;stroke-linecap:butt'
elif v == 'path': style += '1;stroke-dasharray:5,5;stroke-linecap:round' elif v == 'path': style += '1;stroke-dasharray:5,5;stroke-linecap:butt'
else: else:
continue continue
style += ';' style += ';'
@ -498,6 +492,9 @@ def to_write(key):
return False return False
def get_icon(tags, scheme, fill='444444'): def get_icon(tags, scheme, fill='444444'):
tags_hash = ','.join(tags.keys()) + ':' + ','.join(tags.values())
if tags_hash in scheme['cache']:
return scheme['cache'][tags_hash]
main_icon = None main_icon = None
extra_icons = [] extra_icons = []
processed = set() processed = set()
@ -534,14 +531,21 @@ def get_icon(tags, scheme, fill='444444'):
for key in element['tags'].keys(): for key in element['tags'].keys():
processed.add(key) processed.add(key)
if main_icon: if main_icon:
return [main_icon] + extra_icons, fill, processed returned = [main_icon] + extra_icons, fill, processed
else: else:
return [], fill, processed returned = [], fill, processed
scheme['cache'][tags_hash] = returned
return returned
def draw_nodes(): def draw_nodes(show_missed_tags=False, overlap=14):
print 'Draw nodes...' print 'Draw nodes...'
start_time = datetime.datetime.now()
scheme = yaml.load(open('tags.yml')) scheme = yaml.load(open('tags.yml'))
scheme['cache'] = {}
if overlap != 0:
points = []
node_number = 0 node_number = 0
@ -567,16 +571,32 @@ def draw_nodes():
draw_text(k + ': ' + p[k], x, y + 18 + text_y, '444444') draw_text(k + ': ' + p[k], x, y + 18 + text_y, '444444')
text_y += 10 text_y += 10
for k in p: if show_missed_tags:
if not no_draw(k) and not k in processed: for k in p:
point(k, p[k], x, y, fill, text_y) if not no_draw(k) and not k in processed:
text_y += 10 point(k, p[k], x, y, fill, text_y)
text_y += 10
xxx = -(len(shapes) - 1) * 8 xxx = -(len(shapes) - 1) * 8
for shape in shapes:
draw_point_shape(shape, x + xxx, y, fill) if overlap != 0:
xxx += 16 for shape in shapes:
has_space = True
for p in points:
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
ui.write_line(-1, len(node_map)) ui.write_line(-1, len(node_map))
print 'Nodes drawed in ' + str(datetime.datetime.now() - start_time) + '.'
#draw_raw_nodes() #draw_raw_nodes()
#draw_raw_ways() #draw_raw_ways()
@ -588,7 +608,10 @@ icons = extract_icon.IconExtractor('icons.svg')
#sys.exit(0) #sys.exit(0)
#draw_ways() #draw_ways()
draw_nodes() draw_nodes(show_missed_tags=True, overlap=12)
#draw_ways()
#draw_nodes()
if flinger.space.x == 0: if flinger.space.x == 0:
output_file.rect(0, 0, w, flinger.space.y, color='FFFFFF') output_file.rect(0, 0, w, flinger.space.y, color='FFFFFF')

View file

@ -9,7 +9,7 @@ import ui
import sys import sys
def parse_node_full(node_data, silent=False): def parse_node_full(node_datae):
""" """
Parse full node parameters using regular expressions: id, visible, version, Parse full node parameters using regular expressions: id, visible, version,
etc. For faster parsing use parse_node(). etc. For faster parsing use parse_node().
@ -23,22 +23,21 @@ def parse_node_full(node_data, silent=False):
'user': m.group(5), 'uid': m.group(6), 'user': m.group(5), 'uid': m.group(6),
'lat': float(m.group(7)), 'lon': float(m.group(8))} 'lat': float(m.group(7)), 'lon': float(m.group(8))}
else: else:
if not silent: print 'Error: cannot parse node data: ' + node_data + '.'
print 'Error: cannot parse node data: ' + node_data + '.'
return None return None
def parse_node(text): def parse_node(text):
""" """
Just parse node identifier, latitude, and longitude. Just parse node identifier, latitude, and longitude.
""" """
id = text[4:text.find('"', 6)] node_id = text[4:text.find('"', 6)]
lat_index = text.find('lat') lat_index = text.find('lat="')
lon_index = text.find('lon') lon_index = text.find('lon="')
lat = text[lat_index + 5:text.find('"', lat_index + 7)] lat = text[lat_index + 5:text.find('"', lat_index + 7)]
lon = text[lon_index + 5:text.find('"', lon_index + 7)] lon = text[lon_index + 5:text.find('"', lon_index + 7)]
return {'id': int(id), 'lat': float(lat), 'lon': float(lon)} return {'id': int(node_id), 'lat': float(lat), 'lon': float(lon)}
def parse_way_full(way_data, silent=False): def parse_way_full(way_data):
""" """
Parse full way parameters using regular expressions: id, visible, version, Parse full way parameters using regular expressions: id, visible, version,
etc. For faster parsing use parse_way(). etc. For faster parsing use parse_way().
@ -50,8 +49,7 @@ def parse_way_full(way_data, silent=False):
'changeset': m.group(3), 'timestamp': m.group(4), 'changeset': m.group(3), 'timestamp': m.group(4),
'user': m.group(5), 'uid': m.group(6)} 'user': m.group(5), 'uid': m.group(6)}
else: else:
if not silent: print 'Error: cannot parse way data: ' + way_data + '.'
print 'Error: cannot parse way data: ' + way_data + '.'
return None return None
def parse_way(text): def parse_way(text):
@ -88,10 +86,28 @@ def parse_tag(text):
v = text[v_index + 3:text.find('"', v_index + 4)] v = text[v_index + 3:text.find('"', v_index + 4)]
return k, v return k, v
def parse_osm_file(file_name, silent=False): def parse_osm_file(file_name):
if not silent: print 'Reading OSM file ' + file_name
print 'Reading OSM file ' + file_name
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
try:
node_map, way_map, relation_map = parse_osm_file_fast(file_name)
except Exception as e:
print '\033[31mFast parsing failed.\033[0m'
a = raw_input('Do you want to use slow but correct XML parsing? [y/n] ')
if a in ['y', 'yes']:
start_time = datetime.datetime.now()
input_file = open(input_file_name)
content = xml.dom.minidom.parse(input_file)
input_file.close()
else:
return None, None, None
print 'File readed in ' + \
str(datetime.datetime.now() - start_time) + '.'
print 'Nodes: ' + str(len(node_map)) + ', ways: ' + \
str(len(way_map)) + ', relations: ' + str(len(relation_map)) + '.'
return node_map, way_map, relation_map
def parse_osm_file_fast(file_name):
node_map = {} node_map = {}
way_map = {} way_map = {}
relation_map = {} relation_map = {}
@ -158,9 +174,4 @@ def parse_osm_file(file_name, silent=False):
ui.write_line(-1, lines_number) # Complete progress bar. ui.write_line(-1, lines_number) # Complete progress bar.
if not silent:
print 'File readed in ' + \
str(datetime.datetime.now() - start_time) + '.'
print 'Nodes: ' + str(len(node_map)) + ', ways: ' + \
str(len(way_map)) + ', relations: ' + str(len(relation_map)) + '.'
return node_map, way_map, relation_map return node_map, way_map, relation_map

View file

@ -2,11 +2,14 @@ colors:
# Color names # Color names
'black': '000000'
'blue': '2233AA' 'blue': '2233AA'
'brown': '964B00'
'gray': '888888' 'gray': '888888'
'green': '4E9A06' 'green': '4E9A06'
'grey': '888888' 'grey': '888888'
'lightblue': '2288CC' 'lightblue': '2288CC'
'maroon': '800000'
'red': 'CC0000' 'red': 'CC0000'
'violet': '75507B' 'violet': '75507B'
'yellow': 'EDD400' 'yellow': 'EDD400'
@ -58,6 +61,8 @@ tags:
icon: [bank] icon: [bank]
- tags: {amenity: pub} - tags: {amenity: pub}
icon: [pub] icon: [pub]
- tags: {amenity: kindergarten}
icon: [kindergarten]
- tags: {amenity: post_office} - tags: {amenity: post_office}
icon: [post_office] icon: [post_office]
- tags: {amenity: fast_food, 'operator:en': "McDonald's"} - tags: {amenity: fast_food, 'operator:en': "McDonald's"}
@ -66,6 +71,8 @@ tags:
icon: [fast_food] icon: [fast_food]
- tags: {amenity: shop, shop: fishing} - tags: {amenity: shop, shop: fishing}
icon: [fishing] icon: [fishing]
- tags: {amenity: shop, shop: convenience}
icon: [shop_convenience]
- tags: {shop: gift} - tags: {shop: gift}
icon: [gift] icon: [gift]
- tags: {amenity: fountain} - tags: {amenity: fountain}
@ -75,8 +82,6 @@ tags:
add_icon: [microphone] add_icon: [microphone]
- tags: {building: '*', 'roof:material': metal} - tags: {building: '*', 'roof:material': metal}
icon: [metal_roof] icon: [metal_roof]
- tags: {railway: subway_entrance}
icon: [train]
- tags: {natural: tree} - tags: {natural: tree}
icon: [tree] icon: [tree]
color: wood color: wood
@ -95,22 +100,43 @@ tags:
- tags: {natural: tree, denotation: avenue} - tags: {natural: tree, denotation: avenue}
over_icon: [avenue_tree] over_icon: [avenue_tree]
under_icon: [tree, broadleaved, needleleaved] under_icon: [tree, broadleaved, needleleaved]
# Entrance
- tags: {entrance: 'yes'} - tags: {entrance: 'yes'}
icon: [entrance] icon: [entrance]
- tags: {entrance: main} - tags: {entrance: main}
icon: [main_entrance] icon: [main_entrance]
- tags: {entrance: staircase} - tags: {entrance: staircase}
icon: [staircase] icon: [staircase]
- tags: {railway: subway_entrance}
icon: [train]
- tags: {railway: subway_entrance, entrance: 'yes'}
icon: [train]
- tags: {highway: bus_stop} - tags: {highway: bus_stop}
icon: [bus_stop] icon: [bus_stop]
- tags: {highway: bus_stop, shelter: 'yes'}
icon: [bus_stop_with_shelter]
- tags: {highway: bus_stop, bench: 'yes'}
icon: [bus_stop_with_bench]
- tags: {highway: bus_stop, bench: 'yes', shelter: 'no'}
icon: [bus_stop_with_bench]
- tags: {highway: bus_stop, shelter: 'yes', bench: 'yes'}
icon: [bus_stop_with_shelter_and_bench]
- tags: {highway: crossing} - tags: {highway: crossing}
icon: [crossing] icon: [crossing]
- tags: {highway: crossing, crossing: zebra}
icon: [crossing]
- tags: {highway: crossing, crossing_ref: zebra}
icon: [crossing]
- tags: {highway: crossing, crossing: uncontrolled} - tags: {highway: crossing, crossing: uncontrolled}
add_icon: [no_traffic_signals] add_icon: [no_traffic_signals]
- tags: {highway: crossing, crossing: traffic_signals} - tags: {highway: crossing, crossing: traffic_signals}
add_icon: [traffic_signals] add_icon: [traffic_signals]
- tags: {highway: traffic_signals} - tags: {highway: traffic_signals}
icon: [traffic_signals] icon: [traffic_signals]
- tags: {traffic_calming: bump}
icon: [bump]
- tags: {highway: street_lamp} - tags: {highway: street_lamp}
icon: [street_lamp] icon: [street_lamp]
- tags: {historic: memorial} - tags: {historic: memorial}
@ -119,6 +145,8 @@ tags:
icon: [statue] icon: [statue]
- tags: {tourism: artwork, artwork_type: statue} - tags: {tourism: artwork, artwork_type: statue}
icon: [statue] icon: [statue]
- tags: {tourism: artwork, artwork_type: sculpture}
icon: [statue]
- tags: {historic: memorial, memorial: plaque} - tags: {historic: memorial, memorial: plaque}
icon: [plaque] icon: [plaque]
- tags: {historic: tomb} - tags: {historic: tomb}
@ -141,6 +169,16 @@ tags:
icon: [attraction] icon: [attraction]
- tags: {tourism: attraction, attraction: amusement_ride} - tags: {tourism: attraction, attraction: amusement_ride}
icon: [amusement_ride] icon: [amusement_ride]
- tags: {public_transport: platform}
icon: [railway_platform]
- tags: {barrier: entrance}
icon: [entrance]
- tags: {amenity: atm}
icon: [atm]
- tags: {public_transport: stop_position}
icon: [public_transport_stop]
- tags: {crossing_ref: toucan}
icon: [toucan_crossing]
- tags: {foot: 'yes'} - tags: {foot: 'yes'}
add_icon: [foot] add_icon: [foot]
@ -188,3 +226,23 @@ tags:
color: yellow color: yellow
- tags: {colour: yellow} - tags: {colour: yellow}
color: yellow color: yellow
- tags: {color: black}
color: black
- tags: {colour: black}
color: black
- tags: {color: maroon}
color: maroon
- tags: {colour: maroon}
color: maroon
- tags: {color: gray}
color: gray
- tags: {colour: gray}
color: gray
- tags: {color: grey}
color: grey
- tags: {colour: grey}
color: grey
- tags: {color: brown}
color: brown
- tags: {colour: brown}
color: brown

12
ui.py
View file

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*- from __future__ import unicode_literals
""" """
Author: Sergey Vartanov (me@enzet.ru). Author: Sergey Vartanov (me@enzet.ru).
""" """
@ -5,12 +7,14 @@ Author: Sergey Vartanov (me@enzet.ru).
import sys import sys
def write_line(number, total): def write_line(number, total):
length = 20
if number == -1: if number == -1:
print ('%3s' % '100') + ' %: [' + (100 * '=') + '].' print ('%3s' % '100') + ' %' + (length * '') + ''
elif number % 1000 == 0: elif number % 1000 == 0:
p = number / float(total) p = number / float(total)
l = int(p * 100) l = int(p * length)
print ('%3s' % str(int(p * 1000) / 10)) + ' %: [' + (l * '=') + \ print ('%3s' % str(int(p * 1000) / 10)) + ' %' + (l * '') + \
((100 - l) * ' ') + '].' ((length - l) * ' ') + ''
sys.stdout.write("\033[F") sys.stdout.write("\033[F")