mirror of
https://github.com/enzet/map-machine.git
synced 2025-05-24 14:36:25 +02:00
Faster parsing; new drawing rules.
This commit is contained in:
parent
aa6720f30e
commit
3e10d9c1eb
2 changed files with 358 additions and 287 deletions
407
mapper.py
407
mapper.py
|
@ -2,16 +2,20 @@
|
|||
# -*- coding: utf-8 -*- from __future__ import unicode_literals
|
||||
|
||||
"""
|
||||
Simple tool for drawing OSM data.
|
||||
Simple tool for working with OpenStreetMap data.
|
||||
|
||||
Author: Sergey Vartnov
|
||||
Author: Sergey Vartanov (me@enzet.ru).
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import xml.dom.minidom
|
||||
|
||||
import extract_icon
|
||||
import osm_reader
|
||||
|
||||
from flinger import GeoFlinger, Geo
|
||||
|
||||
sys.path.append('lib')
|
||||
|
@ -19,24 +23,19 @@ 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):
|
||||
print 'Fatal: no such file: ' + input_file_name + '.'
|
||||
sys.exit(1)
|
||||
|
||||
print 'Reading input OSM file...'
|
||||
#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) + '.'
|
||||
|
||||
input_file = open(input_file_name)
|
||||
content = xml.dom.minidom.parse(input_file)
|
||||
input_file.close()
|
||||
|
||||
print 'Done.'
|
||||
node_map, way_map, relation_map = osm_reader.parse_osm_file(input_file_name)
|
||||
|
||||
output_file = svg.SVG(open(sys.argv[2], 'w+'))
|
||||
|
||||
|
@ -53,6 +52,11 @@ water_color = 'AACCFF'
|
|||
water_border_color = '6688BB'
|
||||
wood_color = 'B8CC84'
|
||||
|
||||
undraw = ['operator', 'contact:facebook', 'contact:phone', 'opening_hours',
|
||||
'cuisine', 'network', 'website', 'contact:website', 'phone',
|
||||
'branch', 'route_ref', 'addr:flats', 'brand', 'ref', 'addr:street',
|
||||
'wikipedia', 'description', 'layer', 'level']
|
||||
|
||||
output_file.begin(w, h)
|
||||
output_file.rect(0, 0, w, h, color=background_color)
|
||||
|
||||
|
@ -66,13 +70,13 @@ if len(sys.argv) > 3:
|
|||
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):
|
||||
path, x, y = icons.get_path(file_name)
|
||||
if path:
|
||||
return path, x, y
|
||||
else:
|
||||
print 'No such icon: ' + file_name
|
||||
return 'M 4,4 L 4,10 10,10 10,4 4,4', 0, 0
|
||||
if os.path.isfile('icons/' + file_name + '.svg'):
|
||||
file_name = 'icons/' + file_name + '.svg'
|
||||
size = 16
|
||||
|
@ -97,39 +101,21 @@ def get_d_from_file(file_name):
|
|||
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
|
||||
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
|
||||
|
||||
node_map = construct_node_map()
|
||||
|
||||
minimum, maximum = get_min_max(node_map)
|
||||
|
||||
if len(sys.argv) > 3:
|
||||
flinger = GeoFlinger(min1, max1, Vector(0, 0), Vector(w, h))
|
||||
|
@ -140,9 +126,10 @@ else:
|
|||
def draw_path(nodes, style, shift=Vector()):
|
||||
prev_node = None
|
||||
for node_id in nodes:
|
||||
flinged1 = flinger.fling(node_map[node_id]) + shift
|
||||
node = node_map[node_id]
|
||||
flinged1 = flinger.fling(Geo(node['lat'], node['lon'])) + shift
|
||||
if prev_node:
|
||||
flinged2 = flinger.fling(prev_node) + shift
|
||||
flinged2 = flinger.fling(Geo(prev_node['lat'], prev_node['lon'])) + shift
|
||||
output_file.write('L ' + `flinged1.x` + ',' + `flinged1.y` + ' ')
|
||||
else:
|
||||
output_file.write('<path d="M ' + `flinged1.x` + \
|
||||
|
@ -151,18 +138,18 @@ def draw_path(nodes, style, shift=Vector()):
|
|||
output_file.write('" style="' + style + '" />\n')
|
||||
|
||||
def draw_point_shape(name, x, y, fill):
|
||||
shape, size = get_d_from_file(name)
|
||||
draw_point(shape, x, y, fill, size=size)
|
||||
shape, xx, yy = get_d_from_file(name)
|
||||
draw_point(shape, x, y, fill, size=16, xx=xx, yy=yy)
|
||||
|
||||
def draw_point(shape, x, y, fill, size=16):
|
||||
def draw_point(shape, x, y, fill, size=16, xx=0, yy=0):
|
||||
x = int(float(x))
|
||||
y = int(float(y))
|
||||
output_file.write('<path d="' + shape + \
|
||||
'" style="fill:#FFFFFF;opacity:0.5;stroke:#FFFFFF;stroke-width:3;stroke-linejoin:round;" transform="translate(' + \
|
||||
str(x - size / 2.0) + ',' + str(y - size / 2.0) + ')" />\n')
|
||||
str(x - size / 2.0 - xx * 16) + ',' + str(y - size / 2.0 - yy * 16) + ')" />\n')
|
||||
output_file.write('<path d="' + shape + \
|
||||
'" style="fill:#' + fill + ';fill-opacity:1" transform="translate(' + \
|
||||
str(x - size / 2.0) + ',' + str(y - size / 2.0) + ')" />\n')
|
||||
str(x - size / 2.0 - xx * 16) + ',' + str(y - size / 2.0 - yy * 16) + ')" />\n')
|
||||
|
||||
def draw_text(text, x, y, fill):
|
||||
if type(text) == unicode:
|
||||
|
@ -177,64 +164,28 @@ def draw_text(text, x, y, fill):
|
|||
output_file.write('<text x="' + x + '" y="' + y + \
|
||||
'" style="font-size:10;text-anchor:middle;font-family:Myriad Pro;fill:#' + fill + ';">' + text + '</text>')
|
||||
|
||||
def point(k, v, x, y, fill):
|
||||
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
|
||||
output_file.circle(x, y, 2, fill=fill, color=fill)
|
||||
#output_file.circle(float(x), float(y), 2, fill=fill, color=fill)
|
||||
text = k + ': ' + v
|
||||
if type(text) == unicode:
|
||||
text = text.encode('utf-8')
|
||||
output_file.write('<text x="' + str(x) + '" y="' + str(int(y) + 10) + \
|
||||
output_file.write('<text x="' + str(x) + '" y="' + str(int(float(y)) + text_y + 10) + \
|
||||
'" style="font-size:10;text-anchor:middle;font-family:Myriad Pro;fill:#FF0000;">' + text + '</text>')
|
||||
|
||||
# Ways drawing
|
||||
|
||||
def construct_way_map():
|
||||
def construct_layers():
|
||||
"""
|
||||
Construct map of ways and distribute them by layers. One layer may contain
|
||||
elements of different types.
|
||||
Construct 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)
|
||||
for way_id in way_map:
|
||||
way = way_map[way_id]
|
||||
if not ('layer' in way['tags']):
|
||||
way['tags']['layer'] = 0
|
||||
if not (int(way['tags']['layer']) in layers):
|
||||
|
@ -268,37 +219,48 @@ def construct_way_map():
|
|||
# empty = False
|
||||
# if not empty:
|
||||
# print 'Unknown kind of way:', way['tags']
|
||||
return layers, way_map
|
||||
return layers
|
||||
|
||||
|
||||
layers, way_map = construct_way_map()
|
||||
layers = construct_layers()
|
||||
|
||||
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 draw_ways():
|
||||
for level in sorted(layers.keys()):
|
||||
layer = layers[level]
|
||||
#for entity in ['b', 'h1', 'h2', 'r', 'n', 'l', 'a', 'le', 'ba']:
|
||||
|
||||
# Pre part.
|
||||
|
||||
for way in layer['le']:
|
||||
if way['tags']['leisure'] == 'park':
|
||||
style = 'fill:#' + grass_color + ';'
|
||||
else:
|
||||
continue
|
||||
draw_path(way['nodes'], style)
|
||||
|
||||
# Post part.
|
||||
|
||||
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)
|
||||
text_y = 0
|
||||
c = line_center(way['nodes'])
|
||||
if way['tags']['landuse'] == 'grass':
|
||||
style = 'fill:#' + grass_color + ';stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
|
@ -317,17 +279,12 @@ def draw_ways():
|
|||
else:
|
||||
style = 'fill:#0000FF;stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
for tag in way['tags']:
|
||||
if not (tag in ['landuse', 'layer']):
|
||||
point(tag, str(way['tags'][tag]), c.x, c.y, '000000', text_y)
|
||||
text_y += 10
|
||||
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)
|
||||
c = line_center(way['nodes'])
|
||||
if way['tags']['amenity'] == 'parking':
|
||||
style = 'fill:#' + parking_color + ';stroke:none;'
|
||||
draw_path(way['nodes'], style)
|
||||
|
@ -357,7 +314,7 @@ def draw_ways():
|
|||
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:'
|
||||
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;'
|
||||
|
@ -366,11 +323,11 @@ def draw_ways():
|
|||
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;'
|
||||
style = 'fill:none;stroke:#FFFFFF;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:round;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:'
|
||||
style = 'fill:none;stroke:#AAAAAA;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:#AA8800'
|
||||
|
@ -381,15 +338,15 @@ def draw_ways():
|
|||
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'
|
||||
elif v == 'steps': style += '5;stroke-dasharray:1,2;stroke-linecap:round'
|
||||
elif v == 'path': style += '1;stroke-dasharray:5,5;stroke-linecap:round'
|
||||
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:'
|
||||
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:#FFDD66'
|
||||
|
@ -408,16 +365,7 @@ def draw_ways():
|
|||
#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)
|
||||
c = line_center(way['nodes'])
|
||||
for tag in way['tags']:
|
||||
v = way['tags'][tag]
|
||||
if tag == 'building':
|
||||
|
@ -461,22 +409,13 @@ def draw_ways():
|
|||
pass
|
||||
else:
|
||||
kk = tag
|
||||
vv = unicode(v)
|
||||
vv = 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)
|
||||
c = line_center(way['nodes'])
|
||||
if way['tags']['leisure'] == 'playground':
|
||||
style = 'fill:#' + playground_color + ';opacity:0.2;'
|
||||
draw_point_shape('playground', c.x, c.y, '444444')
|
||||
|
@ -509,89 +448,157 @@ def draw_raw_nodes():
|
|||
flinged = flinger.fling(node)
|
||||
output_file.circle(flinged.x, flinged.y, 0.2, color='FFFFFF')
|
||||
|
||||
def no_draw(key):
|
||||
return key in undraw or 'name' in key or 'addr' in key
|
||||
|
||||
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)))
|
||||
for node_id in node_map:
|
||||
node = node_map[node_id]
|
||||
flinged = flinger.fling(Geo(node['lat'], node['lon']))
|
||||
x = `flinged.x`
|
||||
y = `flinged.y`
|
||||
text_y = 0
|
||||
if 'tags' in node:
|
||||
pairs = node['tags']
|
||||
else:
|
||||
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',
|
||||
|
||||
if pairs == {}:
|
||||
pass
|
||||
elif 'amenity' in pairs:
|
||||
k = 'amenity'
|
||||
v = pairs['amenity']
|
||||
if v in ['bench', 'bicycle_parking', 'cafe', 'waste_basket', 'clinic',
|
||||
'restaurant', 'pharmacy', 'drinking_water', 'toilets',
|
||||
'fast_food', 'theatre']:
|
||||
'theatre', 'bar', 'bank', 'pub', 'post_office']:
|
||||
draw_point_shape(v, x, y, fill)
|
||||
elif v == 'clinic':
|
||||
draw_point(d_clinic, x, y, fill)
|
||||
elif v == 'fast_food':
|
||||
main = 'fast_food'
|
||||
if 'operator' in pairs:
|
||||
if pairs['operator'] == "McDonald's":
|
||||
main = 'mcdonalds'
|
||||
if 'operator:en' in pairs:
|
||||
if pairs['operator:en'] == "McDonald's":
|
||||
main = 'mcdonalds'
|
||||
draw_point_shape(main, x, y, fill)
|
||||
elif v == 'shop':
|
||||
if 'shop' in pairs:
|
||||
if pairs['shop'] in ['fishing']:
|
||||
draw_point_shape('shop_' + pairs['shop'], 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)
|
||||
point(k, v, flinged.x, flinged.y, fill, text_y)
|
||||
text_y += 10
|
||||
for k in pairs:
|
||||
if 'karaoke' in pairs:
|
||||
if pairs['karaoke'] == 'yes':
|
||||
draw_point_shape('microphone', flinged.x + 16, y, fill)
|
||||
else:
|
||||
point(k, pairs[k], x, y, fill, text_y)
|
||||
elif not no_draw(k) and k != 'amenity':
|
||||
point(k, pairs[k], x, y, fill, text_y)
|
||||
text_y += 10
|
||||
elif 'natural' in pairs:
|
||||
k = 'natural'
|
||||
v = pairs['natural']
|
||||
if v == 'tree':
|
||||
main = 'tree'
|
||||
if 'leaf_type' in pairs and pairs['leaf_type'] in ['broadleaved', 'needleleaved']:
|
||||
main = pairs['leaf_type']
|
||||
if 'denotation' in pairs and pairs['denotation'] == 'urban':
|
||||
draw_point_shape([main, 'urban_tree_pot'], x, y, wood_color)
|
||||
else:
|
||||
draw_point_shape(main, 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, text_y)
|
||||
text_y += 10
|
||||
elif 'entrance' in pairs:
|
||||
k = 'entrance'
|
||||
v = pairs['entrance']
|
||||
if v == 'yes':
|
||||
draw_point_shape('entrance', x, y, fill)
|
||||
elif v == 'staircase':
|
||||
draw_point_shape('staircase', x, y, fill)
|
||||
elif 'highway' in pairs:
|
||||
k = 'highway'
|
||||
v = pairs['highway']
|
||||
if v == 'crossing':
|
||||
shape = 'crossing'
|
||||
if 'crossing' in pairs:
|
||||
if pairs['crossing'] == 'zebra':
|
||||
shape = 'zebra'
|
||||
elif 'crossing_ref' in pairs:
|
||||
if pairs['crossing_ref'] == 'zebra':
|
||||
shape = 'zebra'
|
||||
draw_point_shape(shape, x, y, fill)
|
||||
elif v == 'street_lamp':
|
||||
draw_point_shape('street_lamp', x, y, fill)
|
||||
else:
|
||||
for k in pairs:
|
||||
if not no_draw(k):
|
||||
point(k, pairs[k], x, y, fill, text_y)
|
||||
text_y += 10
|
||||
|
||||
|
||||
for k in []:
|
||||
v = pairs[k]
|
||||
if k == 'amenity':
|
||||
if v in ['bench', 'bicycle_parking', 'cafe', 'waste_basket',
|
||||
'restaurant', 'pharmacy', 'drinking_water', 'toilets',
|
||||
'fast_food', 'theatre']:
|
||||
draw_point_shape(v, x, 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)
|
||||
point(k, v, flinged.x, flinged.y, fill, text_y)
|
||||
text_y += 10
|
||||
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)
|
||||
draw_point_shape('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)
|
||||
draw_point_shape('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)
|
||||
draw_point_shape('traffic_signal', x, y, fill)
|
||||
elif v == 'crossing':
|
||||
if not ('crossing' in pairs):
|
||||
draw_point(d_crossing, x, y, fill)
|
||||
draw_point_shape('crossing', x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
point(k, v, flinged.x, flinged.y, fill, text_y)
|
||||
text_y += 10
|
||||
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)
|
||||
point(k, v, flinged.x, flinged.y, fill, text_y)
|
||||
text_y += 10
|
||||
elif k == 'recycling_type':
|
||||
if v == 'centre':
|
||||
draw_point_shape('recycling', x, y, fill)
|
||||
|
@ -603,12 +610,14 @@ def draw_nodes():
|
|||
elif v in ['clothes', 'shoes', 'gift']:
|
||||
draw_point_shape('shop_' + v, x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
point(k, v, flinged.x, flinged.y, fill, text_y)
|
||||
text_y += 10
|
||||
elif k == 'traffic_calming':
|
||||
if v == 'bump':
|
||||
draw_point_shape('bump', x, y, fill)
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
point(k, v, flinged.x, flinged.y, fill, text_y)
|
||||
text_y += 10
|
||||
elif k == 'emergency':
|
||||
if v == 'fire_hydrant':
|
||||
draw_point_shape(v, x, y, fill)
|
||||
|
@ -621,12 +630,7 @@ def draw_nodes():
|
|||
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):
|
||||
elif k in undraw or ('name' in k):
|
||||
if k == 'route_ref':
|
||||
v = v.replace(';', ' ')
|
||||
draw_text(v, x, str(flinged.y + 18 + text_y), fill)
|
||||
|
@ -634,13 +638,20 @@ def draw_nodes():
|
|||
elif k in ['layer', 'level', 'source', 'note', 'description']:
|
||||
pass # NOTHING TO DRAW
|
||||
else:
|
||||
point(k, v, flinged.x, flinged.y, fill)
|
||||
point(k, v, flinged.x, flinged.y, fill, text_y)
|
||||
text_y += 10
|
||||
|
||||
print 'Done.'
|
||||
|
||||
#draw_raw_nodes()
|
||||
#draw_raw_ways()
|
||||
|
||||
text_y = 0
|
||||
|
||||
icons = extract_icon.IconExtractor('icons.svg')
|
||||
|
||||
#sys.exit(0)
|
||||
|
||||
draw_ways()
|
||||
draw_nodes()
|
||||
|
||||
|
@ -655,7 +666,7 @@ top_missed_tags = reversed(sorted(missed_tags.keys(), key=lambda x: -missed_tags
|
|||
for tag in top_missed_tags:
|
||||
print tag + ' (' + str(missed_tags[tag]) + ')'
|
||||
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
top_authors = sorted(authors.keys(), key=lambda x: -authors[x])
|
||||
for author in top_authors:
|
||||
|
|
112
osm_reader.py
112
osm_reader.py
|
@ -4,39 +4,81 @@ Reading OpenStreetMap data from XML file.
|
|||
Author: Sergey Vartanov
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
def parse_node_full(text):
|
||||
|
||||
def parse_node_full(node_data, silent=False):
|
||||
"""
|
||||
Parse full node parameters using regular expressions: id, visible, version,
|
||||
etc. For faster parsing use parse_node().
|
||||
"""
|
||||
m = re.match('id="(.*)" visible="(.*)" version="(.*)" changeset="(.*)" timestamp="(.*)" user="(.*)" uid="(.*)" lat="(.*)" lon="(.*)"', text)
|
||||
m = re.match('id="(.*)" visible="(.*)" version="(.*)" changeset="(.*)" ' + \
|
||||
'timestamp="(.*)" user="(.*)" uid="(.*)" ' + \
|
||||
'lat="(.*)" lon="(.*)"', node_data)
|
||||
if m:
|
||||
return {'id': m.group(1), 'visible': m.group(2), 'changeset': m.group(3), 'timestamp': m.group(4), 'user': m.group(5), 'uid': m.group(6), 'lat': m.group(7), 'lon': m.group(8)}
|
||||
return {'id': int(m.group(1)), 'visible': m.group(2),
|
||||
'changeset': m.group(3), 'timestamp': m.group(4),
|
||||
'user': m.group(5), 'uid': m.group(6),
|
||||
'lat': float(m.group(7)), 'lon': float(m.group(8))}
|
||||
else:
|
||||
print 'Error node'
|
||||
if not silent:
|
||||
print 'Error: cannot parse node data: ' + node_data + '.'
|
||||
return None
|
||||
|
||||
def parse_node(text):
|
||||
"""
|
||||
Parse just identifier, latitude, and longitude from node parameters.
|
||||
Just parse node identifier, latitude, and longitude.
|
||||
"""
|
||||
id = text[4:text.find('"', 6)]
|
||||
lat_index = text.find('lat')
|
||||
lon_index = text.find('lon')
|
||||
lat = text[lat_index + 5:text.find('"', lat_index + 7)]
|
||||
lon = text[lon_index + 5:text.find('"', lon_index + 7)]
|
||||
return {'id': id, 'lat': lat, 'lon': lon}
|
||||
return {'id': int(id), 'lat': float(lat), 'lon': float(lon)}
|
||||
|
||||
def parse_way_full(text):
|
||||
m = re.match('id="(.*)" visible="(.*)" version="(.*)" changeset="(.*)" timestamp="(.*)" user="(.*)" uid="(.*)"', text)
|
||||
def parse_way_full(way_data, silent=False):
|
||||
"""
|
||||
Parse full way parameters using regular expressions: id, visible, version,
|
||||
etc. For faster parsing use parse_way().
|
||||
"""
|
||||
m = re.match('id="(.*)" visible="(.*)" version="(.*)" changeset="(.*)" ' + \
|
||||
'timestamp="(.*)" user="(.*)" uid="(.*)"', way_data)
|
||||
if m:
|
||||
return {'id': m.group(1), 'visible': m.group(2), 'changeset': m.group(3), 'timestamp': m.group(4), 'user': m.group(5), 'uid': m.group(6)}
|
||||
return {'id': m.group(1), 'visible': m.group(2),
|
||||
'changeset': m.group(3), 'timestamp': m.group(4),
|
||||
'user': m.group(5), 'uid': m.group(6)}
|
||||
else:
|
||||
print 'Error way'
|
||||
if not silent:
|
||||
print 'Error: cannot parse way data: ' + way_data + '.'
|
||||
return None
|
||||
|
||||
def parse_way(text):
|
||||
"""
|
||||
Just parse way identifier.
|
||||
"""
|
||||
id = text[4:text.find('"', 6)]
|
||||
return {'id': id}
|
||||
return {'id': int(id)}
|
||||
|
||||
def parse_relation(text):
|
||||
"""
|
||||
Just parse relation identifier.
|
||||
"""
|
||||
id = text[4:text.find('"', 6)]
|
||||
return {'id': int(id)}
|
||||
|
||||
def parse_member(text):
|
||||
"""
|
||||
Parse member type, reference, and role.
|
||||
"""
|
||||
if text[6] == 'w':
|
||||
type = 'way'
|
||||
else:
|
||||
type = 'node'
|
||||
ref_index = text.find('ref')
|
||||
role_index = text.find('role')
|
||||
ref = text[ref_index + 5:text.find('"', ref_index + 7)]
|
||||
role = text[role_index + 6:text.find('"', role_index + 8)]
|
||||
return {'type': type, 'ref': int(ref), 'role': role}
|
||||
|
||||
def parse_tag(text):
|
||||
v_index = text.find('v="')
|
||||
|
@ -44,25 +86,19 @@ def parse_tag(text):
|
|||
v = text[v_index + 3:text.find('"', v_index + 4)]
|
||||
return k, v
|
||||
|
||||
def get_max_min(nodes):
|
||||
maximum = Geo(nodes[0]['lon'], nodes[0]['lat'])
|
||||
minimum = Geo(nodes[0]['lon'], nodes[0]['lat'])
|
||||
for node in nodes:
|
||||
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 parse_osm_file(file_name, silent=False):
|
||||
if not silent:
|
||||
print 'Reading OSM file ' + file_name
|
||||
start_time = datetime.datetime.now()
|
||||
node_map = {}
|
||||
way_map = {}
|
||||
relation_map = {}
|
||||
input_file = open(file_name)
|
||||
line = input_file.readline()
|
||||
while line != '':
|
||||
|
||||
# Node parsing.
|
||||
|
||||
if line[:6] == ' <node':
|
||||
if line[-3] == '/':
|
||||
node = parse_node(line[7:-3])
|
||||
|
@ -70,26 +106,50 @@ def parse_osm_file(file_name, silent=False):
|
|||
else:
|
||||
element = parse_node(line[7:-2])
|
||||
element['tags'] = {}
|
||||
elif line == ' </node>':
|
||||
node_map[node['id']] = element
|
||||
elif line == ' </node>\n':
|
||||
node_map[element['id']] = element
|
||||
|
||||
# Way parsing.
|
||||
|
||||
elif line[:5] == ' <way':
|
||||
if line[-3] == '/':
|
||||
way = parse_node(line[7:-3])
|
||||
way = parse_way(line[6:-3])
|
||||
node_map[node['id']] = node
|
||||
else:
|
||||
element = parse_way(line[6:-2])
|
||||
element['tags'] = {}
|
||||
element['nodes'] = []
|
||||
elif line == ' </way>\n':
|
||||
way_map[element['id']] = element
|
||||
|
||||
# Relation parsing.
|
||||
|
||||
elif line[:10] == ' <relation':
|
||||
if line[-3] == '/':
|
||||
relation = parse_relation(line[11:-3])
|
||||
relation_map[relation['id']] = relation
|
||||
else:
|
||||
element = parse_relation(line[11:-2])
|
||||
element['tags'] = {}
|
||||
element['members'] = []
|
||||
elif line == ' </relation>\n':
|
||||
relation_map[element['id']] = element
|
||||
|
||||
# Elements parsing.
|
||||
|
||||
elif line[:6] == ' <tag':
|
||||
k, v = parse_tag(line[7:-3])
|
||||
element['tags'][k] = v
|
||||
elif line[:5] == ' <nd':
|
||||
element['nodes'].append(line[11:-3])
|
||||
element['nodes'].append(int(line[11:-4]))
|
||||
elif line[:5] == ' <member':
|
||||
member = parse_member(line[10:-3])
|
||||
element['members'].append(member)
|
||||
line = input_file.readline()
|
||||
input_file.close()
|
||||
if not silent:
|
||||
print 'File readed in ' + \
|
||||
str(datetime.datetime.now() - start_time) + '.'
|
||||
return node_map, way_map
|
||||
return node_map, way_map, relation_map
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue