Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/purgatory/routes_Join.py
169674 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2009-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file routes_Join.py
15
# @author Daniel Krajzewicz
16
# @author Michael Behrisch
17
# @date 11.09.2009
18
19
"""
20
Joins routes belonging to two networks.
21
A map file with the following syntax is read first:
22
<EDGE_ID>-><EDGE_ID>
23
It describes at which edges the networks overlapped and which edge
24
was kept in the resulting one.
25
Vehicles from both given route files starting at the first of those
26
edges will be at first not regarded, but their routes are kept in memory.
27
All other vehicles are kept, but if they pass one of the mapped edges, the
28
route is continued by choosing a random route from the list of previously
29
discarded ones which start at the corresponding edge.
30
31
Attention! The routes are not sorted in time!
32
"""
33
from __future__ import absolute_import
34
from __future__ import print_function
35
import sys
36
from xml.sax import make_parser, handler
37
38
39
class Route:
40
41
def __init__(self, vPars, edges):
42
self._vPars = vPars
43
self._edges = edges
44
45
def encodeVehicle(self):
46
ret = "<vehicle"
47
for a in self._vPars:
48
ret = ret + " " + a + "=\"" + self._vPars[a] + "\""
49
ret = ret + ">"
50
return ret
51
52
def firstEdge(self):
53
return self._edges[0]
54
55
56
class RoutesReader(handler.ContentHandler):
57
58
def __init__(self, prefix, replacements):
59
self._prefix = prefix
60
self._replacements = {}
61
for r in replacements:
62
rs = replacements[r].split(",")
63
for r2 in rs:
64
self._replacements[r2] = 1
65
self._routes = []
66
self._continuations = {}
67
self._continuationsSum = {}
68
69
def endDocument(self):
70
self._continuationsBackup = {}
71
self._continuationsSumBackup = {}
72
for e in self._continuations:
73
self._continuationsBackup[e] = []
74
self._continuationsBackup[e].extend(self._continuations[e])
75
self._continuationsSumBackup[e] = self._continuationsSum[e]
76
77
def startElement(self, name, attrs):
78
if name == "vehicle":
79
self._vPars = {}
80
for a in attrs.keys():
81
self._vPars[a] = attrs[a]
82
if name == "route":
83
edges = attrs["edges"].split(" ")
84
for i in range(0, len(edges)):
85
edges[i] = self._prefix + edges[i]
86
self._routes.append(Route(self._vPars, edges))
87
for i in range(0, len(edges)):
88
if edges[i] in self._replacements:
89
if edges[i] not in self._continuations:
90
self._continuations[edges[i]] = []
91
self._continuationsSum[edges[i]] = 0
92
self._continuations[edges[i]].append(edges[i:])
93
self._continuationsSum[
94
edges[i]] = self._continuationsSum[edges[i]] + 1
95
96
def getContinuation(self, beginEdge, replacements):
97
assert beginEdge in replacements
98
rEdge = replacements[beginEdge]
99
if rEdge.find(",") >= 0:
100
rEdge = rEdge.split(",")[0]
101
edges = self._continuations[rEdge][-1]
102
self._continuations[rEdge].pop()
103
self._continuationsSum[rEdge] = self._continuationsSum[rEdge] - 1
104
if self._continuationsSum[rEdge] == 0:
105
self._continuations[rEdge] = []
106
self._continuations[rEdge].extend(self._continuationsBackup[rEdge])
107
self._continuationsSum[rEdge] = self._continuationsSumBackup[rEdge]
108
return edges
109
110
111
def writeRoute(fdo, edges, conts1, conts2, replacements):
112
replaceFrom = None
113
for e in edges:
114
if e in replacements:
115
if not replaceFrom:
116
replaceFrom = e
117
continue
118
fdo.write(e + " ")
119
if replaceFrom:
120
if replaceFrom[0] == conts2._prefix:
121
cont = conts1.getContinuation(replaceFrom, replacements)
122
writeRoute(fdo, cont, conts1, conts2, replacements)
123
else:
124
cont = conts2.getContinuation(replaceFrom, replacements)
125
writeRoute(fdo, cont, conts1, conts2, replacements)
126
127
128
def writeVehicle(fdo, route, conts1, conts2, replacements):
129
fdo.write(" " + route.encodeVehicle() + "<route edges=\"")
130
writeRoute(fdo, route._edges, conts1, conts2, replacements)
131
fdo.write("\"></route></vehicle>\n")
132
133
134
if len(sys.argv) < 6:
135
print("Usage: " +
136
sys.argv[0] + " <prefix#1> <routes#1> <prefix#2> <routes#2> <mapfile>")
137
sys.exit()
138
# read mapping
139
mmap = {}
140
fd = open(sys.argv[5])
141
for line in fd:
142
if line.find("->") < 0:
143
continue
144
(orig, dest) = line.strip().split("->")
145
mmap[orig] = dest
146
fd.close()
147
# read routes
148
parser = make_parser()
149
print("Reading routes#1")
150
routes1 = RoutesReader(sys.argv[1], mmap)
151
parser.setContentHandler(routes1)
152
parser.parse(sys.argv[2])
153
print("Reading routes#2")
154
routes2 = RoutesReader(sys.argv[3], mmap)
155
parser.setContentHandler(routes2)
156
parser.parse(sys.argv[4])
157
158
print("Processing routes#1")
159
fdo = open("joined.rou.xml", "w")
160
fdo.write("<routes>\n")
161
for r in routes1._routes:
162
if r.firstEdge() in mmap:
163
continue
164
# skip, starts at a replaced edge
165
writeVehicle(fdo, r, routes1, routes2, mmap)
166
print("Processing routes#2")
167
for r in routes2._routes:
168
if r.firstEdge() in mmap:
169
continue
170
# skip, starts at a replaced edge
171
writeVehicle(fdo, r, routes1, routes2, mmap)
172
fdo.write("</routes>\n")
173
fdo.close()
174
175