User coloring.

This commit is contained in:
Sergey Vartanov 2015-12-20 17:08:23 +03:00
parent 75aa8e4996
commit edef3a69f2
9 changed files with 465 additions and 327 deletions

View file

@ -1,4 +1,7 @@
Röntgen project focuses on displaying every [OpenStreetMap](http://openstreetmap.org) data tag on the map.
<!-- PLEASE DO NOT EDIT THIS FILE.
IT WAS GENERATED BY MOIRE. -->
Röntgen project focuses on displaying every \[OpenStreetMap\](http://openstreetmap.org) data tag on the map.
Why do we need yet another map style?
-------------------------------------
@ -8,7 +11,7 @@ It is actually not just another map style since it is **not** *a map for users*
Map generation
--------------
![Sample map](doc/map.png)
!\[Sample map\](doc/map.png)
**Requirements**: Python 2.7.
@ -28,13 +31,13 @@ There are simple Python renderer that generates SVG map from OpenStreetMap data.
</td></tr><tr><td><tt>-bbox</tt>, <tt>--boundary-box</tt>
</td><td><tt>&lt;longitude 1&gt;,&lt;longitude 2&gt;,&lt;latitude 1&gt;,&lt;latitude 2&gt;</tt> (decimal float)
</td><td><tt>,,,</tt> (decimal float)
</td><td>Boundary box to draw
</td></tr><tr><td><tt>-s</tt>, <tt>--size</tt>
</td><td><tt>&lt;width&gt;,&lt;height&gt;</tt> (pixels)
</td><td><tt>,</tt> (pixels)
</td><td>Result image size
@ -45,11 +48,13 @@ Icon set
If tag is drawable it is displayed using icon combination and colors.
All icons are under [CC BY 4.0](http://creativecommons.org/licenses/by/4.0/) license. So, do whatever you want but give appropriate credit.
All icons are under \[CC BY 4.0\](http://creativecommons.org/licenses/by/4.0/) license. So, do whatever you want but give appropriate credit.
Double size:
![Icons](doc/grid.png)
!\[Icons\](doc/grid.png)
Feel free to request new icons via issues for whatever you want to see on the map. No matter how frequently the tag is used in OpenStreetMap since final goal is to cover all tags. However, common used tags have priority, other things being equal.

View file

@ -220,12 +220,21 @@ tags:
color: deciduous
- tags: {natural: tree, leaf_cycle: evergreen}
color: evergreen
# Tree genus
- tags: {natural: tree, genus: Betula}
icon: [betula]
color: tree
# Tree over icons
- tags: {natural: tree, denotation: urban}
over_icon: [urban_tree_pot]
under_icon: [tree, broadleaved, needleleaved]
under_icon: [tree, broadleaved, needleleaved, betula]
- tags: {natural: tree, denotation: avenue}
over_icon: [avenue_tree]
under_icon: [tree, broadleaved, needleleaved]
under_icon: [tree, broadleaved, needleleaved, betula]
# Entrance

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View file

@ -1,6 +1,6 @@
Röntgen project focuses on displaying every \href {http://openstreetmap.org} {OpenStreetMap} data tag on the map.
\2 {Why do we need yet another map style?}
\2 {Why do we need yet another map style?} {map_style}
It is actually not just another map style since it is \b {not} \i {a map for users} but \i {map for OpenStreetMap contributors}. Suppose, you spent time adding colors for building walls, benches and shelters for bus stops but they do not represented on the map. Röntgen helps to display all changes you made.
@ -15,7 +15,7 @@ There are simple Python renderer that generates SVG map from OpenStreetMap data.
\code
{python mapper.py -i <input OSM XML file name> -o <output SVG file name>}
\3 {Options}
\3 {Options} {options}
\table
{
@ -32,7 +32,7 @@ There are simple Python renderer that generates SVG map from OpenStreetMap data.
}
}
\2 {Icon set}
\2 {Icon set} {icons}
If tag is drawable it is displayed using icon combination and colors.
@ -43,3 +43,4 @@ Double size:
\image {doc/grid.png} {Icons}
Feel free to request new icons via issues for whatever you want to see on the map. No matter how frequently the tag is used in OpenStreetMap since final goal is to cover all tags. However, common used tags have priority, other things being equal.

View file

@ -27,7 +27,8 @@ sys.path.append('../lib')
import svg
from vector import Vector
background_color = 'DDDDDD'
background_color = 'DDDDDD' # 'DDDDDD'
outline_color = 'FFFFFF'
beach_color = 'F0E0C0'
building_color = 'EEEEEE' # 'D0D0C0'
building_border_color = 'C4C4C4' # 'AAAAAA'
@ -86,8 +87,10 @@ prefix_to_write = set(['addr', 'contact', 'name', 'operator', 'wikipedia',
# To draw
'species', 'taxon', 'genus'])
tags_to_skip = set(['note', 'layer', 'source', 'building:part', 'fixme', 'comment',
'FIXME', 'source_ref', 'naptan:verified:note', 'building:levels'])
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'])
@ -144,7 +147,6 @@ def draw_point_shape(name, x, y, fill):
def draw_point_outline(shape, x, y, fill, size=16, xx=0, yy=0):
x = int(float(x))
y = int(float(y))
outline_fill = 'FFFFFF'
opacity = 0.5
r = int(fill[0:2], 16)
g = int(fill[2:4], 16)
@ -154,8 +156,8 @@ def draw_point_outline(shape, x, y, fill, size=16, xx=0, yy=0):
outline_fill = '000000'
opacity = 0.3
output_file.write('<path d="' + shape + \
'" style="fill:#' + outline_fill + ';opacity:' + str(opacity) + ';' + \
'stroke:#' + outline_fill + ';stroke-width:3;stroke-linejoin:round;" ' + \
'" style="fill:#' + outline_color + ';opacity:' + str(opacity) + ';' + \
'stroke:#' + outline_color + ';stroke-width:3;stroke-linejoin:round;" ' + \
'transform="translate(' + \
str(x - size / 2.0 - xx * 16) + ',' + str(y - size / 2.0 - yy * 16) + ')" />\n')
@ -181,7 +183,7 @@ def point(k, v, x, y, fill, text_y):
text = text.encode('utf-8')
draw_text(text, x, float(y) + text_y + 18, '734A08')
def construct_text(tags):
def construct_text(tags, processed):
for key in tags:
tags[key] = tags[key].replace('&quot;', '"')
texts = []
@ -193,13 +195,13 @@ def construct_text(tags):
tags.pop('name', None)
if 'name:ru' in tags:
if not name:
name = tags['name']
tags.pop('name', None)
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']
tags.pop('name', None)
name = tags['name:en']
tags.pop('name:en', None)
tags.pop('name:en', None)
if 'alt_name' in tags:
if alt_name:
@ -239,8 +241,8 @@ def construct_text(tags):
else:
addr = ''
street = tags['addr:street']
if street[:6] == 'улица ':
street = 'ул. ' + street[6:]
if street.startswith('улица '):
street = 'ул. ' + street[len('улица '):]
addr += street
tags.pop('addr:street', None)
if 'addr:housenumber' in tags:
@ -280,7 +282,7 @@ def construct_text(tags):
texts.append({'text': tags[k], 'fill': '444444'})
tags.pop(k)
for tag in tags:
if to_write(tag):
if to_write(tag) and not (tag in processed):
#texts.append({'text': tag + ': ' + tags[tag]})
texts.append({'text': tags[tag]})
return texts
@ -298,6 +300,7 @@ def draw_raw_ways():
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)
@ -311,244 +314,276 @@ def line_center(node_ids):
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]
construct_way(drawing, way['nodes'], way['tags'], None)
user = way['user'] if 'user' in way else ''
construct_way(drawing, way['nodes'], way['tags'], None, user)
def construct_way(drawing, nodes, tags, path):
is_area = None
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:
is_area = nodes[0] == nodes[-1]
layer = float(tags['layer']) if ('layer' in tags) else 0
if nodes:
c = line_center(nodes)
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;'
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 '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;'
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:
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 += '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,
'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
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 = '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;'
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 += '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})
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):
@ -616,7 +651,7 @@ def construct_relations(drawing):
way.reverse()
path = get_path(way)
p += path + ' '
construct_way(drawing, None, tags, p)
construct_way(drawing, None, tags, p, '')
# Nodes drawing
@ -636,6 +671,8 @@ def no_draw(key):
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:
@ -665,21 +702,25 @@ def draw_shapes(shapes, overlap, points, x, y, fill, show_missed_tags, tags,
draw_point_shape(shape, x + xxx, y, fill)
xxx += 16
write_tags = construct_text(tags)
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)
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
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()
@ -704,6 +745,9 @@ def construct_nodes(drawing):
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
@ -772,22 +816,27 @@ options = ui.parse_options(sys.argv)
if not options:
sys.exit(1)
input_file_name = options['input_file_name']
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)
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 = False # Full keys getting
output_file = svg.SVG(open(options['output_file_name'], 'w+'))
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]
w = options.size[0]
h = options.size[1]
output_file.begin(w, h)
output_file.rect(0, 0, w, h, color=background_color)
@ -796,7 +845,7 @@ minimum = Geo(180, 180)
maximum = Geo(-180, -180)
if 'boundary_box' in options:
bb = options['boundary_box']
bb = options.boundary_box
min1 = Geo(bb[2], bb[0])
max1 = Geo(bb[3], bb[1])
@ -823,20 +872,20 @@ icons = extract_icon.IconExtractor(icons_file_name)
drawing = {'nodes': [], 'ways': []}
if options['draw_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'])
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']:
if options.show_index:
print min1.lon, max1.lon
print min1.lat, max1.lat

View file

@ -6,10 +6,11 @@ Author: Sergey Vartanov
import datetime
import ui
import re
import sys
def parse_node_full(node_datae):
def parse_node_full(node_data):
"""
Parse full node parameters using regular expressions: id, visible, version,
etc. For faster parsing use parse_node().
@ -19,9 +20,10 @@ def parse_node_full(node_datae):
'lat="(.*)" lon="(.*)"', node_data)
if m:
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))}
'version': m.group(3),
'changeset': m.group(4), 'timestamp': m.group(5),
'user': m.group(6), 'uid': m.group(7),
'lat': float(m.group(8)), 'lon': float(m.group(9))}
else:
print 'Error: cannot parse node data: ' + node_data + '.'
return None
@ -46,8 +48,8 @@ def parse_way_full(way_data):
'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)}
'changeset': m.group(4), 'timestamp': m.group(5),
'user': m.group(6), 'uid': m.group(7)}
else:
print 'Error: cannot parse way data: ' + way_data + '.'
return None
@ -87,12 +89,12 @@ def parse_tag(text):
return k, v
def parse_osm_file(file_name, parse_nodes=True, parse_ways=True,
parse_relations=True):
parse_relations=True, full=False):
start_time = datetime.datetime.now()
try:
node_map, way_map, relation_map = parse_osm_file_fast(file_name,
parse_nodes=parse_nodes, parse_ways=parse_ways,
parse_relations=parse_relations)
parse_relations=parse_relations, full=full)
except Exception as e:
print e
print '\033[31mFast parsing failed.\033[0m'
@ -107,7 +109,7 @@ def parse_osm_file(file_name, parse_nodes=True, parse_ways=True,
input_file.close()
print 'Done.'
else:
return None, None, None
sys.exit(0)
print 'File readed in ' + \
str(datetime.datetime.now() - start_time) + '.'
print 'Nodes: ' + str(len(node_map)) + ', ways: ' + \
@ -115,7 +117,7 @@ def parse_osm_file(file_name, parse_nodes=True, parse_ways=True,
return node_map, way_map, relation_map
def parse_osm_file_fast(file_name, parse_nodes=True, parse_ways=True,
parse_relations=True):
parse_relations=True, full=False):
node_map = {}
way_map = {}
relation_map = {}
@ -141,10 +143,16 @@ def parse_osm_file_fast(file_name, parse_nodes=True, parse_ways=True,
else:
break
if line[-3] == '/':
node = parse_node(line[7:-3])
if not full:
node = parse_node(line[7:-3])
else:
node = parse_node_full(line[7:-3])
node_map[node['id']] = node
else:
element = parse_node(line[7:-2])
if not full:
element = parse_node(line[7:-2])
else:
element = parse_node_full(line[7:-2])
element['tags'] = {}
elif line in [' </node>\n', '\t</node>\n']:
node_map[element['id']] = element
@ -158,10 +166,16 @@ def parse_osm_file_fast(file_name, parse_nodes=True, parse_ways=True,
else:
break
if line[-3] == '/':
way = parse_way(line[6:-3])
if not full:
way = parse_way(line[6:-3])
else:
way = parse_way_full(line[6:-3])
way_map[node['id']] = way
else:
element = parse_way(line[6:-2])
if not full:
element = parse_way(line[6:-2])
else:
element = parse_way_full(line[6:-2])
element['tags'] = {}
element['nodes'] = []
elif line in [' </way>\n', '\t</way>\n']:

View file

@ -4,45 +4,47 @@
Author: Sergey Vartanov (me@enzet.ru).
"""
import argparse
import sys
def parse_options(args):
options = {'draw_nodes': True, 'draw_ways': False, 'overlap': 12,
'show_missed_tags': False, 'show_index': False}
args = iter(args[1:])
for arg in args:
if arg in ['-i', '--input']:
options['input_file_name'] = next(args)
elif arg in ['-o', '--output']:
options['output_file_name'] = next(args)
elif arg in ['-bbox', '--boundary-box']:
arg = next(args)
options['boundary_box'] = map(lambda x: float(x), arg.split(','))
elif arg in ['-n', '--draw-nodes']:
options['draw_nodes'] = True
elif arg in ['-w', '--draw-ways']:
options['draw_ways'] = True
elif arg in ['-nn', '--no-draw-nodes']:
options['draw_nodes'] = False
elif arg in ['-nw', '--no-draw-ways']:
options['draw_ways'] = False
elif arg in ['--show-missed-tags']:
options['show_missed_tags'] = True
elif arg in ['--no-show-missed-tags']:
options['show_missed_tags'] = False
elif arg in ['--overlap']:
options['overlap'] = int(next(args))
elif arg in ['-s', '--size']:
options['size'] = map(lambda x: float(x), next(args).split(','))
elif arg in ['--show-index']:
options['show_index'] = True
elif arg in ['--no-show-index']:
options['show_index'] = False
else:
print 'Unknown option: ' + arg
return None
return options
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', dest='input_file_name',
required=True)
parser.add_argument('-o', '--output', dest='output_file_name',
required=True)
parser.add_argument('-bbox', '--boundary-box', dest='boundary_box',
required=True)
parser.add_argument('-nn', '--no-draw-nodes', dest='draw_nodes',
action='store_false', default=True)
parser.add_argument('-nw', '--no-draw-ways', dest='draw_ways',
action='store_false', default=True)
parser.add_argument('-nc', '--no-draw-captions', dest='draw_captions',
action='store_false', default=True)
parser.add_argument('--show-missed-tags', dest='show_missed_tags',
action='store_true')
parser.add_argument('--no-show-missed-tags', dest='show_missed_tags',
action='store_false')
parser.add_argument('--overlap', dest='overlap', default=12, type=int)
parser.add_argument('-s', '--size', dest='size')
parser.add_argument('--show-index', dest='show_index',
action='store_true')
parser.add_argument('--no-show-index', dest='show_index',
action='store_false')
parser.add_argument('--user-coloring', dest='user_coloring',
action='store_true', default=False)
parser.add_argument('--seed', dest='seed', default='')
arguments = parser.parse_args(args[1:])
arguments.boundary_box = \
map(lambda x: float(x), arguments.boundary_box.split(','))
arguments.size = map(lambda x: float(x), arguments.size.split(','))
return arguments
def write_line(number, total):

View file

@ -24,9 +24,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="191.13126"
inkscape:cy="368.67156"
inkscape:zoom="5.656854"
inkscape:cx="330.04973"
inkscape:cy="498.87454"
inkscape:current-layer="layer1"
inkscape:document-units="px"
showgrid="true"
@ -36,8 +36,8 @@
inkscape:snap-bbox="true"
inkscape:window-width="1425"
inkscape:window-height="995"
inkscape:window-x="67"
inkscape:window-y="18"
inkscape:window-x="66"
inkscape:window-y="24"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
@ -3492,7 +3492,7 @@
rx="1" />
<path
style="fill:#000000;stroke:none"
d="m 388,99 0,11 7,0 0,-2 0.90625,0 0.0937,0 0,-0.0312 c 0.54727,0.0521 1.06536,-0.1396 1.40625,-0.5 C 397.76971,107.08444 398,106.55159 398,106 l 0,-3 c 0,-1.09865 -1.01734,-1.50867 -2,-2 l -1,0 0,-2 z m 1.5,1 1,0 3,0 c 0.277,0 0.5,0.223 0.5,0.5 0,0.277 -0.223,0.5 -0.5,0.5 l -1.5,0 c -0.55228,0 -1,0.44772 -1,1 l 0,2.5 c 0,0.277 -0.223,0.5 -0.5,0.5 -0.277,0 -0.5,-0.223 -0.5,-0.5 l 0,-0.9375 c 0.003,-0.0216 0,-0.0401 0,-0.0625 0,-0.24069 -0.17967,-0.42115 -0.40625,-0.46875 C 389.56115,103.01055 389.5346,103 389.5,103 c -0.277,0 -0.5,-0.223 -0.5,-0.5 l 0,-2 c 0,-0.277 0.223,-0.5 0.5,-0.5 z m 5.5,2 1,0 c 0.55821,0 1,0.44179 1,1 l 0,3 c 0,0.27684 -0.13025,0.58857 -0.3125,0.78125 -0.18225,0.19268 -0.36556,0.25678 -0.59375,0.21875 l -0.0625,0 -0.0312,0 -1,0 z"
d="m 388,99 0,11 7,0 0,-2 0.90625,0 0.0937,0 0,-0.0312 c 0.54727,0.0521 1.06536,-0.1396 1.40625,-0.5 C 397.76971,107.08444 398,106.55159 398,106 l 0,-3 c 0,-1.09865 -0.84338,-2 -2,-2 l -1,0 0,-2 z m 1.5,1 1,0 3,0 c 0.277,0 0.5,0.223 0.5,0.5 0,0.277 -0.223,0.5 -0.5,0.5 l -1.5,0 c -0.55228,0 -1,0.44772 -1,1 l 0,2.5 c 0,0.277 -0.223,0.5 -0.5,0.5 -0.277,0 -0.5,-0.223 -0.5,-0.5 l 0,-0.9375 c 0.003,-0.0216 0,-0.0401 0,-0.0625 0,-0.24069 -0.17967,-0.42115 -0.40625,-0.46875 C 389.56115,103.01055 389.5346,103 389.5,103 c -0.277,0 -0.5,-0.223 -0.5,-0.5 l 0,-2 c 0,-0.277 0.223,-0.5 0.5,-0.5 z m 5.5,2 1,0 c 0.55821,0 1,0.44179 1,1 l 0,3 c 0,0.27684 -0.13025,0.58857 -0.3125,0.78125 -0.18225,0.19268 -0.36556,0.25678 -0.59375,0.21875 l -0.0625,0 -0.0312,0 -1,0 z"
id="beer"
inkscape:label="#rect4413"
inkscape:connector-curvature="0"
@ -5395,5 +5395,63 @@
style="fill:#000000;fill-opacity:1;stroke:none"
d="M 231 226 L 231 228 L 228 232 L 228 239 L 235 239 L 235 232 L 232 228 L 232 226 L 231 226 z M 231.5 229.03125 L 233.71875 232 L 229.28125 232 L 231.5 229.03125 z "
id="milk" />
<path
sodipodi:nodetypes="cccccccccccccccccsscscsscscsscc"
inkscape:connector-curvature="0"
inkscape:label="#rect4452"
id="betula"
d="m 245,233 c 0,0.554 0.446,1 1,1 l 1,0 0,3 1,0 0,1 -1,0 0,1 2,0 0,-3 -1,0 0,-1 1,0 0,-1 1,0 c 0.554,0 1,-0.446 1,-1 l 0,-1 c 0.554,0 1,-0.446 1,-1 l 0,-2 c 0,-0.554 -0.446,-1 -1,-1 l 0,-1 c 0,-0.554 -0.446,-1 -1,-1 0,-0.554 -0.446,-1 -1,-1 l -2,0 c -0.554,0 -1,0.446 -1,1 -0.554,0 -1,0.446 -1,1 l 0,1 c -0.554,0 -1,0.446 -1,1 l 0,2 c 0,0.554 0.446,1 1,1 z"
style="fill:#000000;stroke:none" />
<rect
ry="1"
rx="1"
y="209"
x="246"
height="6"
width="4"
id="rect3794"
style="fill:#808080;stroke:none" />
<rect
ry="1"
rx="1"
y="210"
x="245"
height="8"
width="6"
id="rect3796"
style="fill:#808080;stroke:none" />
<rect
ry="1"
rx="1"
y="212"
x="244"
height="4"
width="8"
id="rect3798"
style="fill:#808080;stroke:none" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3800"
d="m 249,216 0,6 -2,0 0,-6 z"
style="fill:#808080;stroke:none" />
<rect
ry="0.5"
rx="0.5"
y="219"
x="248"
height="1"
width="3"
id="rect3802"
style="fill:#ffd5d5;stroke:none" />
<rect
style="fill:#ffd5d5;stroke:none"
id="rect3804"
width="3"
height="1"
x="245"
y="220"
rx="0.5"
ry="0.5" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 276 KiB

After

Width:  |  Height:  |  Size: 278 KiB