Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/net/visum_mapDistricts.py
169674 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2008-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 visum_mapDistricts.py
15
# @author Daniel Krajzewicz
16
# @author Michael Behrisch
17
# @date 2007-10-25
18
19
"""
20
21
This script reads a network and a dump file and
22
draws the network, coloring it by the values
23
found within the dump-file.
24
"""
25
from __future__ import absolute_import
26
from __future__ import print_function
27
28
import os
29
import sys
30
import math
31
from optparse import OptionParser
32
33
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
34
import sumolib.net # noqa
35
36
37
def computeDistance(n1, n2):
38
xd = n1._coord[0] - n2._coord[0]
39
yd = n1._coord[1] - n2._coord[1]
40
return math.sqrt(xd * xd + yd * yd)
41
42
43
def relAngle(angle1, angle2):
44
angle2 -= angle1
45
if angle2 > 180:
46
angle2 = (360. - angle2) * -1.
47
while angle2 < -180:
48
angle2 = 360 + angle2
49
return angle2
50
51
52
# initialise
53
optParser = OptionParser()
54
optParser.add_option("-v", "--verbose", action="store_true", dest="verbose",
55
default=False, help="tell me what you are doing")
56
# i/o
57
optParser.add_option("-1", "--net1", dest="net1",
58
help="SUMO network to use (mandatory)", metavar="FILE")
59
optParser.add_option("-2", "--net2", dest="net2",
60
help="SUMO network to use (mandatory)", metavar="FILE")
61
optParser.add_option("-a", "--nodes1", dest="nodes1",
62
help="The first matching nodes", metavar="NODELIST")
63
optParser.add_option("-b", "--nodes2", dest="nodes2",
64
help="The second matching nodes", metavar="NODELIST")
65
# parse options
66
(options, args) = optParser.parse_args()
67
68
69
# read networks
70
if options.verbose:
71
print("Reading net#1...")
72
net1 = sumolib.net.readNet(options.net1)
73
74
if options.verbose:
75
print("Reading net#2...")
76
net2 = sumolib.net.readNet(options.net2)
77
78
# reproject the visum net onto the navteq net
79
adaptor = sumolib.net.netshiftadaptor.NetShiftAdaptor(
80
net1, net2, options.nodes1.split(","), options.nodes2.split(","))
81
adaptor.reproject(options.verbose)
82
83
# build a speed-up grid
84
xmin = 100000
85
xmax = -100000
86
ymin = 100000
87
ymax = -100000
88
for n in net1._nodes:
89
xmin = min(xmin, n._coord[0])
90
xmax = max(xmax, n._coord[0])
91
ymin = min(ymin, n._coord[1])
92
ymax = max(ymax, n._coord[1])
93
for n in net2._nodes:
94
xmin = min(xmin, n._coord[0])
95
xmax = max(xmax, n._coord[0])
96
ymin = min(ymin, n._coord[1])
97
ymax = max(ymax, n._coord[1])
98
xmin = xmin - .1
99
xmax = xmax + .1
100
ymin = ymin - .1
101
ymax = ymax + .1
102
103
104
CELLSIZE = 100
105
arr1 = []
106
arr2 = []
107
for y in range(0, CELLSIZE):
108
arr1.append([])
109
arr2.append([])
110
for x in range(0, CELLSIZE):
111
arr1[-1].append([])
112
arr2[-1].append([])
113
114
cw = (xmax - xmin) / float(CELLSIZE)
115
ch = (ymax - ymin) / float(CELLSIZE)
116
for n in net2._nodes:
117
cx = (n._coord[0] - xmin) / cw
118
cy = (n._coord[1] - ymin) / ch
119
arr1[int(cy)][int(cx)].append(n)
120
for n in net1._nodes:
121
cx = (n._coord[0] - xmin) / cw
122
cy = (n._coord[1] - ymin) / ch
123
arr2[int(cy)][int(cx)].append(n)
124
125
126
# map
127
nmap1to2 = {}
128
nmap2to1 = {}
129
nodes1 = net2._nodes
130
nodes2 = net1._nodes
131
highwayNodes2 = set()
132
highwaySinks2 = set()
133
highwaySources2 = set()
134
urbanNodes2 = set()
135
for n2 in nodes2:
136
noIncoming = 0
137
noOutgoing = 0
138
for e in n2._outgoing:
139
if e.getSpeed() > 80. / 3.6 and e.getSpeed() < 99:
140
highwayNodes2.add(n2)
141
if e.getSpeed() < 99:
142
noOutgoing = noOutgoing + 1
143
for e in n2._incoming:
144
if e.getSpeed() > 80. / 3.6 and e.getSpeed() < 99:
145
highwayNodes2.add(n2)
146
if e.getSpeed() < 99:
147
noIncoming = noIncoming + 1
148
if n2 in highwayNodes2:
149
if noOutgoing == 0:
150
highwaySinks2.add(n2)
151
if noIncoming == 0:
152
highwaySources2.add(n2)
153
else:
154
urbanNodes2.add(n2)
155
print("Found " + str(len(highwaySinks2)) + " highway sinks in net2")
156
cont = ""
157
for n in highwaySinks2:
158
cont = cont + n._id + ", "
159
print(cont)
160
cont = ""
161
print("Found " + str(len(highwaySources2)) + " highway sources in net2")
162
for n in highwaySources2:
163
cont = cont + n._id + ", "
164
print(cont)
165
166
167
fdd = open("dconns.con.xml", "w")
168
fdd.write("<connections>\n")
169
highwaySinks1 = set()
170
highwaySources1 = set()
171
origDistrictNodes = {}
172
nnn = {}
173
for n1 in nodes1:
174
if n1._id.find('-', 1) < 0:
175
continue
176
# if n1._id.find("38208387")<0:
177
# continue
178
un1 = None
179
for e in n1._outgoing:
180
un1 = e._to
181
for e in n1._incoming:
182
un1 = e._from
183
d = n1._id[:n1._id.find('-', 1)]
184
if d[0] == '-':
185
d = d[1:]
186
if d not in origDistrictNodes:
187
origDistrictNodes[d] = []
188
if options.verbose:
189
print("District: " + d)
190
isHighwayNode = False
191
isHighwaySink = False
192
isHighwaySource = False
193
noIncoming = 0
194
noOutgoing = 0
195
noInConns = 0
196
noOutConns = 0
197
for e in un1._outgoing:
198
if e.getSpeed() > 80. / 3.6 and e.getSpeed() < 99:
199
isHighwayNode = True
200
if e.getSpeed() < 99:
201
noOutgoing = noOutgoing + 1
202
if e.getSpeed() > 99:
203
noOutConns = noOutConns + 1
204
for e in un1._incoming:
205
if e.getSpeed() > 80. / 3.6 and e.getSpeed() < 99:
206
isHighwayNode = True
207
if e.getSpeed() < 99:
208
noIncoming = noIncoming + 1
209
if e.getSpeed() > 99:
210
noInConns = noInConns + 1
211
if options.verbose:
212
print("Check", un1._id, noOutgoing, noIncoming)
213
if isHighwayNode:
214
if noOutgoing == 0:
215
highwaySinks1.add(n1)
216
isHighwaySink = True
217
if noIncoming == 0:
218
highwaySources1.add(n1)
219
isHighwaySource = True
220
# the next is a hack for bad visum-networks
221
if noIncoming == 1 and noOutgoing == 1 and noInConns == 1 and noOutConns == 1:
222
highwaySinks1.add(n1)
223
isHighwaySink = True
224
highwaySources1.add(n1)
225
isHighwaySource = True
226
227
best = None
228
bestDist = -1
229
check = urbanNodes2
230
if n1 in highwaySinks1:
231
check = highwaySinks2
232
elif n1 in highwaySources1:
233
check = highwaySources2
234
elif isHighwayNode:
235
check = highwayNodes2
236
for n2 in check:
237
dist = computeDistance(un1, n2)
238
if bestDist == -1 or bestDist > dist:
239
best = n2
240
bestDist = dist
241
if best:
242
nnn[best] = n1
243
if d not in nmap1to2:
244
nmap1to2[d] = []
245
if best not in nmap1to2[d]:
246
nmap1to2[d].append(best)
247
if best not in nmap2to1:
248
nmap2to1[best] = []
249
if n1 not in nmap2to1[best]:
250
nmap2to1[best].append(n1)
251
if options.verbose:
252
print("a: " + d + "<->" + best._id)
253
if best not in origDistrictNodes[d]:
254
origDistrictNodes[d].append(best)
255
256
preBest = best
257
best = None
258
bestDist = -1
259
check = []
260
if n1 in highwaySinks1 or preBest in highwaySinks2:
261
check = highwaySources2
262
elif n1 in highwaySources1 or preBest in highwaySources2:
263
check = highwaySinks2
264
elif isHighwayNode:
265
check = highwayNodes2
266
for n2 in check:
267
dist = computeDistance(un1, n2)
268
if (bestDist == -1 or bestDist > dist) and n2 != preBest:
269
best = n2
270
bestDist = dist
271
if best:
272
nnn[best] = n1
273
if d not in nmap1to2:
274
nmap1to2[d] = []
275
if best not in nmap1to2[d]:
276
nmap1to2[d].append(best)
277
if best not in nmap2to1:
278
nmap2to1[best] = []
279
if n1 not in nmap2to1[best]:
280
nmap2to1[best].append(n1)
281
print("b: " + d + "<->" + best._id)
282
if best not in origDistrictNodes[d]:
283
origDistrictNodes[d].append(best)
284
285
286
if options.verbose:
287
print("Found " + str(len(highwaySinks1)) + " highway sinks in net1")
288
for n in highwaySinks1:
289
print(n._id)
290
print("Found " + str(len(highwaySources1)) + " highway sources in net1")
291
for n in highwaySources1:
292
print(n._id)
293
294
295
connectedNodesConnections = {}
296
for d in nmap1to2:
297
for n2 in nmap1to2[d]:
298
if n2 in connectedNodesConnections:
299
continue
300
n1i = net1.addNode("i" + n2._id, nnn[n2]._coord)
301
n1o = net1.addNode("o" + n2._id, nnn[n2]._coord)
302
haveIncoming = False
303
incomingLaneNo = 0
304
for e in n2._incoming:
305
if e._id[0] != "i" and e._id[0] != "o":
306
haveIncoming = True
307
incomingLaneNo = incomingLaneNo + e.getLaneNumber()
308
haveOutgoing = False
309
outgoingLaneNo = 0
310
for e in n2._outgoing:
311
if e._id[0] != "i" and e._id[0] != "o":
312
haveOutgoing = True
313
outgoingLaneNo = outgoingLaneNo + e.getLaneNumber()
314
if haveIncoming:
315
e1 = net1.addEdge("o" + n2._id, n2._id, n1o._id, -2)
316
if haveOutgoing:
317
net1.addLane(e1, 20, 100.)
318
else:
319
for i in range(0, incomingLaneNo):
320
net1.addLane(e1, 20, 100.)
321
if len(n2._incoming) == 1:
322
fdd.write(' <connection from="' + n2._incoming[
323
0]._id + '" to="' + e1._id + '" lane="' + str(i) + ':' + str(i) + '"/>\n')
324
if haveOutgoing:
325
if options.verbose:
326
print("has outgoing")
327
e2 = net1.addEdge("i" + n2._id, n1i._id, n2._id, -2)
328
if haveIncoming:
329
net1.addLane(e2, 20, 100.)
330
else:
331
for i in range(0, outgoingLaneNo):
332
net1.addLane(e2, 20, 100.)
333
if len(n2._outgoing) == 1:
334
fdd.write(' <connection from="' + e2._id + '" to="' +
335
n2._outgoing[0]._id + '" lane="' + str(i) + ':' + str(i) + '"/>\n')
336
connectedNodesConnections[n2] = [n1i, n1o]
337
338
339
newDistricts = {}
340
districtSources = {}
341
districtSinks = {}
342
mappedDistrictNodes = {}
343
connNodes = {}
344
dRemap = {}
345
for d in nmap1to2:
346
newDistricts[d] = []
347
if len(nmap1to2[d]) == 1:
348
n = nmap1to2[d][0]
349
if n in dRemap:
350
districtSources[d] = districtSources[dRemap[n]]
351
districtSinks[d] = districtSinks[dRemap[n]]
352
newDistricts[d] = []
353
newDistricts[d].append(n._id)
354
continue
355
else:
356
dRemap[n] = d
357
[ni, no] = connectedNodesConnections[n]
358
if len(ni._outgoing) > 0:
359
districtSources[d] = ni._outgoing[0]._id
360
if len(no._incoming) > 0:
361
districtSinks[d] = no._incoming[0]._id
362
fdd.write(' <connection from="' + no._incoming[0]._id + '"/>\n')
363
else:
364
incomingLaneNoG = 0
365
outgoingLaneNoG = 0
366
for n in nmap1to2[d]:
367
for e in n._incoming:
368
if e._id[0] != "i" and e._id[0] != "o":
369
incomingLaneNoG = incomingLaneNoG + e.getLaneNumber()
370
for e in n._outgoing:
371
if e._id[0] != "i" and e._id[0] != "o":
372
outgoingLaneNoG = outgoingLaneNoG + e.getLaneNumber()
373
p1 = [0, 0]
374
p11 = [0, 0]
375
p12 = [0, 0]
376
p2 = [0, 0]
377
for n in nmap1to2[d]:
378
p1[0] = p1[0] + n._coord[0]
379
p1[1] = p1[1] + n._coord[1]
380
p2[0] = p2[0] + nnn[n]._coord[0]
381
p2[1] = p2[1] + nnn[n]._coord[1]
382
p2[0] = (p1[0] + p2[0]) / float(len(origDistrictNodes[d]) * 2)
383
p2[1] = (p1[1] + p2[1]) / float(len(origDistrictNodes[d]) * 2)
384
dn2i = net1.addNode("cci" + d, p2)
385
dn2o = net1.addNode("cci" + d, p2)
386
p11[0] = p1[0] / float(len(origDistrictNodes[d]))
387
p11[1] = p1[1] / float(len(origDistrictNodes[d]))
388
dn1o = net1.addNode("co" + d, p11)
389
e1 = net1.addEdge("co" + d, dn1o._id, dn2o._id, -2)
390
for i in range(0, incomingLaneNoG):
391
net1.addLane(e1, 22, 100.)
392
districtSinks[d] = e1._id
393
p12[0] = p1[0] / float(len(origDistrictNodes[d]))
394
p12[1] = p1[1] / float(len(origDistrictNodes[d]))
395
dn1i = net1.addNode("ci" + d, p12)
396
e2 = net1.addEdge("ci" + d, dn2i._id, dn1i._id, -2)
397
for i in range(0, outgoingLaneNoG):
398
net1.addLane(e2, 21, 100.)
399
districtSources[d] = e2._id
400
runningOutLaneNumber = 0
401
runningInLaneNumber = 0
402
for n2 in nmap1to2[d]:
403
[ni, no] = connectedNodesConnections[n2]
404
print("In: " + ni._id + " " + str(len(ni._incoming)) +
405
" " + str(len(ni._outgoing)))
406
print("Out: " + no._id + " " + str(len(no._incoming)) +
407
" " + str(len(no._outgoing)))
408
if len(no._incoming) > 0:
409
incomingLaneNo = 0
410
for e in n2._incoming:
411
if e._id[0] != "i" and e._id[0] != "o":
412
incomingLaneNo = incomingLaneNo + e.getLaneNumber()
413
e1 = net1.addEdge("o" + d + "#" + n2._id, no._id, dn1o._id, -2)
414
for i in range(0, incomingLaneNo):
415
net1.addLane(e1, 19, 100.)
416
fdd.write(' <connection from="' + "o" + d + "#" + n2._id + '" to="' + dn1o._outgoing[
417
0]._id + '" lane="' + str(i) + ':' + str(runningOutLaneNumber) + '"/>\n')
418
runningOutLaneNumber = runningOutLaneNumber + 1
419
fdd.write(
420
' <connection from="' + dn1o._outgoing[0]._id + '"/>\n')
421
if incomingLaneNo == 0:
422
net1.addLane(e1, 19, 100.)
423
runningOutLaneNumber = runningOutLaneNumber + 1
424
if len(ni._outgoing) > 0:
425
outgoingLaneNo = 0
426
for e in n2._outgoing:
427
if e._id[0] != "i" and e._id[0] != "o":
428
outgoingLaneNo = outgoingLaneNo + e.getLaneNumber()
429
e2 = net1.addEdge("i" + d + "#" + n2._id, dn1i._id, ni._id, -2)
430
for i in range(0, outgoingLaneNo):
431
net1.addLane(e2, 18, 100.)
432
fdd.write(' <connection from="' + dn1i._incoming[
433
0]._id + '" to="' + "i" + d + "#" + n2._id + '" lane="' + str(runningInLaneNumber) +
434
':' + str(i) + '"/>\n')
435
runningInLaneNumber = runningInLaneNumber + 1
436
if outgoingLaneNo == 0:
437
net1.addLane(e2, 18, 100.)
438
runningInLaneNumber = runningInLaneNumber + 1
439
440
fd = open("districts.xml", "w")
441
fd.write("<tazs>\n")
442
for d in newDistricts:
443
fd.write(' <taz id="' + d + '">\n')
444
if d in districtSources:
445
fd.write(
446
' <tazSource id="' + districtSources[d] + '" weight="1"/>\n')
447
if d in districtSinks:
448
fd.write(
449
' <tazSink id="' + districtSinks[d] + '" weight="1"/>\n')
450
fd.write(' </taz>\n')
451
fd.write("</tazs>\n")
452
fd.close()
453
454
455
def writeNode(fd, node):
456
fd.write(" <node id=\"" + node._id + "\" x=\"" +
457
str(node._coord[0]) + "\" y=\"" + str(node._coord[1]) + "\"/>\n")
458
459
460
def writeEdge(fd, edge, withGeom=True):
461
fd.write(" <edge id=\"" + edge._id + "\" fromNode=\"" +
462
edge._from._id + "\" toNode=\"" + edge._to._id)
463
fd.write("\" speed=\"" + str(edge._speed))
464
fd.write("\" priority=\"" + str(edge._priority))
465
if withGeom:
466
fd.write("\" spreadType=\"center")
467
fd.write("\" numLanes=\"" + str(len(edge._lanes)) + "\"")
468
shape = edge.getShape()
469
if withGeom:
470
fd.write(" shape=\"")
471
for i, c in enumerate(shape):
472
if i != 0:
473
fd.write(" ")
474
fd.write(str(c[0]) + "," + str(c[1]))
475
fd.write("\"")
476
fd.write("/>\n")
477
478
479
def writeNodes(net):
480
fd = open("nodes.xml", "w")
481
fd.write("<nodes>\n")
482
for node in net._nodes:
483
writeNode(fd, node)
484
fd.write("</nodes>\n")
485
fd.close()
486
487
488
def writeEdges(net):
489
fd = open("edges.xml", "w")
490
fd.write("<edges>\n")
491
for edge in net._edges:
492
if edge._id.find("#") > 0 or edge._id.find("c") >= 0 or edge._id.find("i") >= 0:
493
writeEdge(fd, edge, False)
494
else:
495
writeEdge(fd, edge)
496
fd.write("</edges>\n")
497
fd.close()
498
499
500
fdd.write("</connections>\n")
501
writeNodes(net1)
502
writeEdges(net1)
503
504