forked from stefanschramm/osm_oepnv_validator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rn.py
executable file
·149 lines (126 loc) · 4.22 KB
/
rn.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# rn.py - load network of routes from OSM
#
# Copyright (C) 2012, Stefan Schramm <mail@stefanschramm.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import re
import os
import stat
import datetime
from imposm.parser import OSMParser
from mako.lookup import TemplateLookup
class RouteNetwork(object):
# dummy profile
profile = {
'name': '',
'shortname': '',
'filter_text': '',
'datasource': '',
'stopplan': False,
'maps': {}
}
pbf = ""
mtime = None
relation_filter = lambda r: True
makolookup = TemplateLookup(directories=[os.path.dirname(__file__) + '/templates'])
def __init__(self):
# the interesting objects will be stored in these 3 dicts:
# dict of relations; index: relation id
# each relation consists of (relation_id, tags, members)
# where members consists of (member_id, member_type, role)
self.relations = {}
# dict of ways; index: way id
# each way consists of (way_id, tags, node_ids)
self.ways = {}
# dict of nodes; index: node id
# each node consists of (node_id, tags, coordinates)
self.nodes = {}
# additionally information about parent-relations is collected:
# dict of parent relations; index: id of relation to get parent relations for
self.parents = {}
def load_network(self, pbf, filterfunction=lambda r: True):
# read data of public transport network
# required for validating and displaying
self.relation_filter = filterfunction
# get modification time of data source
# TODO: how to determine time when reading from multiple sources?
self.mtime = datetime.datetime.fromtimestamp(os.stat(pbf)[stat.ST_MTIME])
# first pass:
# collect all interesting relations
print "Collecting relations..."
p = OSMParser(concurrency=4, relations_callback=self.relations_cb)
p.parse(pbf)
# second pass:
# collect ways for these relations
print "Collecting %i ways..." % len(self.ways)
p = OSMParser(concurrency=4, ways_callback=self.ways_cb)
p.parse(pbf)
# collect nodes for collected relations and ways
print "Collecting %i nodes..." % len(self.nodes)
p = OSMParser(concurrency=4, nodes_callback=self.nodes_cb)
p.parse(pbf)
def relations_cb(self, relations):
# callback: collect routes to validate
for relation in relations:
rid, tags, members = relation
if self.relation_filter(relation):
self.relations[rid] = relation
for member in members:
mid, typ, role = member
if typ == "node":
self.nodes[mid] = None
if typ == "way":
self.ways[mid] = None
if (typ, mid) not in self.parents:
self.parents[(typ, mid)] = [("relation", rid)]
else:
self.parents[(typ, mid)].append(("relation", rid))
def ways_cb(self, ways):
# callback: collect interesting ways
for way in ways:
wid, tags, nodes = way
if wid in self.ways and self.ways[wid] == None:
self.ways[wid] = way
for nid in nodes:
self.nodes[nid] = None
def nodes_cb(self, nodes):
# callback: collect interesting nodes
for node in nodes:
nid, tags, coords = node
if nid in self.nodes and self.nodes[nid] == None:
self.nodes[nid] = node
def get_sortkey(self, relation):
rid, tags, members = relation
key = ""
if "route_master" in tags:
key += tags["route_master"]
elif "route" in tags:
key += tags["route"]
key += "_"
if "ref" in tags:
ref = tags["ref"]
for number in set(re.findall("[0-9]+", ref)):
# append a lot of leading zeroes to each number
ref = ref.replace(number, "%010i" % int(number))
key += ref
key += "_"
if "type" in tags and tags["type"] == "route_master":
# for same refs put route_master at top
key += "0"
else:
key += "1"
return key