regions.py

Wed, 29 Jul 2020 23:45:53 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 29 Jul 2020 23:45:53 +0300
changeset 1
f9788970fa46
child 2
7378b802ddf8
permissions
-rw-r--r--

begin work on bus compiler

1
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
1 #!/usr/bin/env python3
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
2 from xml.etree import ElementTree
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
3 from geometry import *
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
4
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
5 REGION_TYPES = ['major', 'minor']
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
6 REGION_KEY_VALUES = [x + '_region' for x in REGION_TYPES]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
7 SHAPE_KEYS = [x + '_shapes' for x in REGION_TYPES]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
8
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
9 def parse_nodes(root):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
10 nodes = {}
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
11 for child in root:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
12 if child.tag == 'node':
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
13 lat, lon = float(child.attrib['lat']), float(child.attrib['lon'])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
14 nodes[child.attrib['id']] = Location(lat, lon)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
15 return nodes
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
16
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
17 def parse_way(way, nodes):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
18 def choose_shapes(way, boundary):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
19 return (way['major_shapes']
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
20 if boundary == 'major_region'
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
21 else way['minor_shapes'])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
22 result = {'minor_shapes': [], 'major_shapes': []}
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
23 shape = []
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
24 for child in way:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
25 if child.tag == 'nd':
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
26 shape.append(child.attrib['ref'])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
27 elif child.tag == 'tag':
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
28 key = child.attrib['k']
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
29 if key in SHAPE_KEYS:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
30 raise ValueError(str.format('tag "{}" is not allowed', key))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
31 result[key] = child.attrib['v']
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
32 if key == 'boundary' and result['boundary'] not in REGION_KEY_VALUES:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
33 return None # we're not interested in it!
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
34 if shape[-1] != shape[0]:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
35 raise ValueError('polygon is not closed: %r' % result)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
36 if 'boundary' not in result:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
37 raise ValueError('polygon not tagged as a boundary: %r' % result)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
38 shape = [nodes[ref] for ref in shape[:-1]]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
39 choose_shapes(result, result['boundary']).append(Polygon(*shape))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
40 return result
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
41
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
42 def parse_boundaries(root, *, nodes):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
43 for child in root:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
44 if child.tag == 'way':
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
45 way = parse_way(child, nodes = nodes)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
46 if way:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
47 yield way
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
48
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
49 def parse_regions(filename):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
50 from katakana import transliterate as transliterate_katakana
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
51 tree = ElementTree.parse(filename)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
52 root = tree.getroot()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
53 nodes = parse_nodes(root)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
54 regions = dict()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
55 extra_shapes = list()
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
56 for way in parse_boundaries(root, nodes = nodes):
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
57 if 'boundary' in way and way['boundary'] != 'subregion' and 'name' in way:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
58 # defines a region
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
59 way['via_factor'] = int(way.get('via_factor', 1))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
60 if way['name'] in regions:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
61 raise ValueError(str.format(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
62 'Region {name} defined twice',
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
63 name = repr(way['name']),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
64 ))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
65 regions[way['name']] = way
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
66 del way['boundary']
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
67 if 'external' in way:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
68 way['boundary'] = 'minor_region'
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
69 for prefix in ['', 'short_', 'internal_']:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
70 name_key = prefix + 'name'
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
71 if name_key in way and way[name_key] and name_key + ':ja' not in way:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
72 way[name_key + ':ja'] = transliterate_katakana(way[name_key])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
73 elif 'boundary' in way and 'is_in' in way:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
74 # adds an extra shape to an existing region
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
75 extra_shapes.append(way)
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
76 for extra_shape in extra_shapes:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
77 name = extra_shape['is_in']
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
78 try:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
79 region = regions[name]
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
80 except KeyError:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
81 raise ValueError(str.format(
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
82 'Extra shape refers to {name} which was not found: {extra_shape}',
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
83 name = repr(name),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
84 extra_shape = repr(extra_shape),
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
85 ))
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
86 for key in SHAPE_KEYS:
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
87 region[key].extend(extra_shape[key])
f9788970fa46 begin work on bus compiler
Teemu Piippo <teemu@hecknology.net>
parents:
diff changeset
88 return regions

mercurial