New tags for skip, write, and draw; options for parsing and drawing.

This commit is contained in:
Sergey Vartanov 2015-08-01 01:19:22 +03:00
parent feb073032a
commit e2cc8d8a14
4 changed files with 158 additions and 67 deletions

152
mapper.py
View file

@ -26,18 +26,6 @@ sys.path.append('lib')
import svg
from vector import Vector
input_file_name = sys.argv[1]
if not os.path.isfile(input_file_name):
print 'Fatal: no such file: ' + input_file_name + '.'
sys.exit(1)
node_map, way_map, relation_map = osm_reader.parse_osm_file(input_file_name)
output_file = svg.SVG(open(sys.argv[2], 'w+'))
w, h = 2650, 2650
background_color = 'EEEEEE'
grass_color = 'C8DC94'
sand_color = 'F0E0D0'
@ -49,33 +37,39 @@ water_color = 'AACCFF'
water_border_color = '6688BB'
wood_color = 'B8CC84'
tags_to_write = ['operator', 'opening_hours', 'cuisine', 'network', 'website',
tags_to_write = set(['operator', 'opening_hours', 'cuisine', 'network', 'website',
'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']
'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',
# To draw
'naptan:Bearing', 'species', 'taxon', 'seats', 'capacity',
'fhrs:rating', 'fhrs:confidence_management', 'fhrs:hygiene',
'genus', 'platforms', 'naptan:BusStopType'])
prefix_to_write = ['addr', 'contact', 'name', 'operator', 'wikipedia',
prefix_to_write = set(['addr', 'contact', 'name', 'operator', 'wikipedia',
'alt_name', 'description', 'old_name', 'inscription',
'route_ref', 'is_in', 'website']
'route_ref', 'is_in', 'website',
# To draw
'species', 'taxon'])
tags_to_skip = ['note', 'layer', 'source', 'building:part', 'fixme', 'comment']
tags_to_skip = set(['note', 'layer', 'source', 'building:part', 'fixme', 'comment',
'FIXME', 'source_ref', 'naptan:verified:note'])
prefix_to_skip = ['source']
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 = {}
prefix_to_skip = set(['source'])
def get_d_from_file(file_name):
path, x, y = icons.get_path(file_name)
@ -126,14 +120,6 @@ def get_min_max(node_map):
return minimum, maximum
minimum, maximum = get_min_max(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:
@ -185,10 +171,6 @@ def draw_text(text, x, y, fill):
'" style="font-size:10;text-anchor:middle;font-family:Myriad Pro;fill:#' + fill + ';">' + text + '</text>')
def point(k, v, x, y, fill, text_y):
if ('node ' + k + ': ' + v) in missed_tags:
missed_tags['node ' + k + ': ' + v] += 1
else:
missed_tags['node ' + k + ': ' + v] = 1
text = k + ': ' + v
if type(text) == unicode:
text = text.encode('utf-8')
@ -206,11 +188,11 @@ def construct_layers():
way = way_map[way_id]
if not ('layer' in way['tags']):
way['tags']['layer'] = 0
if not (int(way['tags']['layer']) in layers):
layers[int(way['tags']['layer'])] = \
if not (float(way['tags']['layer']) in layers):
layers[float(way['tags']['layer'])] = \
{'b': [], 'h1': [], 'h2': [], 'r': [], 'n': [], 'l': [],
'a': [], 'le': [], 'ba': [], 'bo': [], 'w': []}
layer = layers[int(way['tags']['layer'])]
layer = layers[float(way['tags']['layer'])]
if 'building' in way['tags']:
layer['b'].append(way)
if 'natural' in way['tags']:
@ -242,8 +224,6 @@ def construct_layers():
return layers
layers = construct_layers()
def draw_raw_ways():
for way_id in way_map:
way = way_map[way_id]
@ -478,7 +458,7 @@ def draw_raw_nodes():
def no_draw(key):
if key in tags_to_write or key in tags_to_skip:
return True
for prefix in prefix_to_write + prefix_to_skip:
for prefix in prefix_to_write.union(prefix_to_skip):
if key[:len(prefix) + 1] == prefix + ':':
return True
return False
@ -549,7 +529,7 @@ def get_icon(tags, scheme, fill='444444'):
scheme['cache'][tags_hash] = returned
return returned
def draw_nodes(show_missed_tags=False, overlap=14):
def draw_nodes(show_missed_tags=False, overlap=14, draw=True):
print 'Draw nodes...'
start_time = datetime.datetime.now()
@ -579,14 +559,30 @@ def draw_nodes(show_missed_tags=False, overlap=14):
p = {}
shapes, fill, processed = get_icon(p, scheme)
processed_tags += len(processed)
skipped_tags += len(p) - len(processed)
for k in p:
if k in processed or no_draw(k):
processed_tags += 1
else:
skipped_tags += 1
for k in []: # p:
if to_write(k):
draw_text(k + ': ' + p[k], x, y + 18 + text_y, '444444')
text_y += 10
if show_missed_tags:
for k in p:
v = p[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
if show_missed_tags:
for k in p:
if not no_draw(k) and not k in processed:
@ -617,20 +613,56 @@ def draw_nodes(show_missed_tags=False, overlap=14):
str(skipped_tags) + ' (' + \
str(processed_tags / float(processed_tags + skipped_tags) * 100) + ' %).'
# Actions
input_file_name = sys.argv[1]
if not os.path.isfile(input_file_name):
print 'Fatal: no such file: ' + input_file_name + '.'
sys.exit(1)
node_map, way_map, relation_map = osm_reader.parse_osm_file(input_file_name,
parse_ways=False, parse_relations=False)
output_file = svg.SVG(open(sys.argv[2], 'w+'))
w, h = 2650, 2650
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 = {}
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.'
#layers = construct_layers()
#draw_raw_nodes()
#draw_raw_ways()
text_y = 0
icons = extract_icon.IconExtractor('icons.svg')
#sys.exit(0)
#draw_ways()
#draw_nodes(show_missed_tags=True, overlap=12)
draw_nodes(show_missed_tags=False, overlap=12, draw=True)
#draw_ways()
draw_nodes()
#draw_nodes()
if flinger.space.x == 0:
output_file.rect(0, 0, w, flinger.space.y, color='FFFFFF')
@ -638,10 +670,12 @@ if flinger.space.x == 0:
output_file.end()
print '\nTop missed tags:\n'
top_missed_tags = sorted(missed_tags.keys(), key=lambda x: -missed_tags[x])
for tag in top_missed_tags[:10]:
print tag + ' (' + str(missed_tags[tag]) + ')'
missed_tags_file = open('missed_tags.yml', '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)

View file

@ -86,19 +86,26 @@ def parse_tag(text):
v = text[v_index + 3:text.find('"', v_index + 4)]
return k, v
def parse_osm_file(file_name):
print 'Reading OSM file ' + file_name
def parse_osm_file(file_name, parse_nodes=True, parse_ways=True,
parse_relations=True):
start_time = datetime.datetime.now()
try:
node_map, way_map, relation_map = parse_osm_file_fast(file_name)
node_map, way_map, relation_map = parse_osm_file_fast(file_name,
parse_nodes=parse_nodes, parse_ways=parse_ways,
parse_relations=parse_relations)
except Exception as e:
print 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()
print 'Opening OSM file ' + file_name + '...'
input_file = open(input_file_name)
print 'Done.'
print 'Parsing OSM file ' + file_name + '...'
content = xml.dom.minidom.parse(input_file)
input_file.close()
print 'Done.'
else:
return None, None, None
print 'File readed in ' + \
@ -107,13 +114,17 @@ def parse_osm_file(file_name):
str(len(way_map)) + ', relations: ' + str(len(relation_map)) + '.'
return node_map, way_map, relation_map
def parse_osm_file_fast(file_name):
def parse_osm_file_fast(file_name, parse_nodes=True, parse_ways=True,
parse_relations=True):
node_map = {}
way_map = {}
relation_map = {}
print 'Line number counting for ' + file_name + '...'
with open(file_name) as f:
for lines_number, l in enumerate(f):
pass
print 'Done.'
print 'Parsing OSM file ' + file_name + '...'
input_file = open(file_name)
line = input_file.readline()
line_number = 0
@ -124,6 +135,11 @@ def parse_osm_file_fast(file_name):
# Node parsing.
if line[:6] in [' <node', '\t<node']:
if not parse_nodes:
if parse_ways or parse_relations:
continue
else:
break
if line[-3] == '/':
node = parse_node(line[7:-3])
node_map[node['id']] = node
@ -136,6 +152,11 @@ def parse_osm_file_fast(file_name):
# Way parsing.
elif line[:5] in [' <way', '\t<way']:
if not parse_ways:
if parse_relations:
continue
else:
break
if line[-3] == '/':
way = parse_way(line[6:-3])
way_map[node['id']] = way
@ -149,6 +170,8 @@ def parse_osm_file_fast(file_name):
# Relation parsing.
elif line[:10] in [' <relation', '\t<relation']:
if not parse_relations:
break
if line[-3] == '/':
relation = parse_relation(line[11:-3])
relation_map[relation['id']] = relation

View file

@ -6,10 +6,12 @@ colors:
'blue': '2233AA'
'brown': '964B00'
'darkgreen': '446722'
'gold': 'FFD700' # Wikipedia
'gray': '888888'
'green': '4E9A06'
'grey': '888888'
'lightblue': '2288CC'
'slate_blue': '2288CC' # The same
'lightgreen': '73D216'
'maroon': '800000'
'orange': 'FCAF3E'
@ -28,6 +30,7 @@ colors:
'grass': 'C8DC94'
'sand': 'F0E0D0'
'beach': 'F0E0C0'
'deciduous': 'FCAF3E'
'desert': 'F0E0D0'
'playground': '884400'
'parking': 'DDCC99'
@ -57,10 +60,14 @@ tags:
icon: [restaurant]
- tags: {amenity: pharmacy}
icon: [pharmacy]
- tags: {amenity: post_box}
icon: [post_box]
- tags: {amenity: drinking_water}
icon: [drinking_water]
- tags: {amenity: toilets}
icon: [toilets]
- tags: {amenity: telephone}
icon: [telephone]
- tags: {amenity: theatre}
icon: [theatre]
- tags: {amenity: bar}
@ -90,6 +97,9 @@ tags:
add_icon: [microphone]
- tags: {building: '*', 'roof:material': metal}
icon: [metal_roof]
# Trees
- tags: {natural: tree}
icon: [tree]
color: wood
@ -102,6 +112,8 @@ tags:
- tags: {natural: tree, type: conifer}
icon: [needleleaved]
color: wood
- tags: {natural: tree, leaf_cycle: deciduous}
color: deciduous
- tags: {natural: tree, denotation: urban}
over_icon: [urban_tree_pot]
under_icon: [tree, broadleaved, needleleaved]
@ -110,6 +122,7 @@ tags:
under_icon: [tree, broadleaved, needleleaved]
# Entrance
- tags: {entrance: 'yes'}
icon: [entrance]
- tags: {entrance: main}
@ -141,6 +154,10 @@ tags:
add_icon: [no_traffic_signals]
- tags: {highway: crossing, crossing: traffic_signals}
add_icon: [traffic_signals]
- tags: {highway: mini_roundabout}
icon: [mini_roundabout]
- tags: {highway: turning_circle}
icon: [turning_circle]
- tags: {highway: traffic_signals}
icon: [traffic_signals]
- tags: {traffic_calming: bump}
@ -163,12 +180,20 @@ tags:
icon: [mausoleum]
- tags: {barrier: gate}
icon: [gate]
- tags: {barrier: bollard}
icon: [bollard]
- tags: {barrier: lift_gate}
icon: [lift_gate]
- tags: {barrier: turnstile}
icon: [turnstile]
- tags: {barrier: stile}
icon: [stile]
- tags: {man_made: pole}
icon: [pole]
- tags: {power: pole}
icon: [pole]
- tags: {power: tower}
icon: [power_tower]
- tags: {man_made: pole, highway: street_lamp}
icon: [pole_lamp]
- tags: {man_made: flagpole}
@ -209,3 +234,7 @@ tags:
add_icon: [trolleybus]
- tags: {access: private}
add_icon: [private]
- tags: {direction: clockwise}
add_icon: [clockwise]
- tags: {smoking: 'no'}
add_icon: [no_smoking]

13
ui.py
View file

@ -6,15 +6,20 @@ Author: Sergey Vartanov (me@enzet.ru).
import sys
def write_line(number, total):
length = 20
parts = length * 8
boxes = [' ', '', '', '', '', '', '', '']
if number == -1:
print ('%3s' % '100') + ' % ' + (length * '') + ''
print ('%3s' % '100') + ' % ' + (length * '') + ''
elif number % 1000 == 0:
p = number / float(total)
l = int(p * length)
print ('%3s' % str(int(p * 1000) / 10)) + ' %' + (l * '') + \
((length - l) * ' ') + ''
l = int(p * parts)
fl = l / 8
pr = int(l - fl * 8)
print ('%3s' % str(int(p * 1000) / 10)) + ' %' + (fl * '') + \
boxes[pr] + ((length - fl - 1) * ' ') + ''
sys.stdout.write("\033[F")