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