diff --git a/README.md b/README.md
index c26b3e6..c4df0a5 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
-Röntgen project focuses on displaying every [OpenStreetMap](http://openstreetmap.org) data tag on the map.
+
+
+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)
**Requirements**: Python 2.7.
@@ -28,13 +31,13 @@ There are simple Python renderer that generates SVG map from OpenStreetMap data.
-s , --size
-<width>,<height> (pixels)
+, (pixels)
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)
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.
+
+
diff --git a/data/tags.yml b/data/tags.yml
index c398b91..898bd89 100644
--- a/data/tags.yml
+++ b/data/tags.yml
@@ -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
diff --git a/doc/grid.png b/doc/grid.png
index 4df3688..ed9327c 100644
Binary files a/doc/grid.png and b/doc/grid.png differ
diff --git a/doc/map.png b/doc/map.png
index 5610a67..8859df8 100644
Binary files a/doc/map.png and b/doc/map.png differ
diff --git a/doc/readme.moi b/doc/readme.moi
index 0d0b21b..80338ee 100644
--- a/doc/readme.moi
+++ b/doc/readme.moi
@@ -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 -o }
-\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.
+
diff --git a/engine/mapper.py b/engine/mapper.py
index 22e696d..108ba3a 100644
--- a/engine/mapper.py
+++ b/engine/mapper.py
@@ -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(' \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('"', '"')
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
diff --git a/engine/osm_reader.py b/engine/osm_reader.py
index 07ebf09..d8f6456 100644
--- a/engine/osm_reader.py
+++ b/engine/osm_reader.py
@@ -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 [' \n', '\t\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 [' \n', '\t\n']:
diff --git a/engine/ui.py b/engine/ui.py
index 1249cee..1d51cad 100644
--- a/engine/ui.py
+++ b/engine/ui.py
@@ -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):
diff --git a/icons/icons.svg b/icons/icons.svg
index 8a42e94..8e2dc6f 100644
--- a/icons/icons.svg
+++ b/icons/icons.svg
@@ -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">
+
+
+
+
+
+
+