/usr/share/sumo/tools/district/edgesInDistricts.py is in sumo-tools 0.15.0~dfsg-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | #!/usr/bin/env python
from xml.sax import saxutils, make_parser, handler
from optparse import OptionParser
import math
def parseShape(shape):
poses = shape.split()
ret = []
for pos in poses:
xy = pos.split(",")
ret.append((float(xy[0]), float(xy[1])))
return ret
def angle2D(p1, p2):
theta1 = math.atan2(p1[1], p1[0]);
theta2 = math.atan2(p2[1], p2[0]);
dtheta = theta2 - theta1;
while dtheta > 3.1415926535897932384626433832795:
dtheta -= 2.0*3.1415926535897932384626433832795
while dtheta < -3.1415926535897932384626433832795:
dtheta += 2.0*3.1415926535897932384626433832795
return dtheta
def isWithin(pos, shape):
angle = 0.
for i in range(0, len(shape)-1):
p1 = ( (shape[i][0] - pos[0]), (shape[i][1] - pos[1]) )
p2 = ( (shape[i+1][0] - pos[0]), (shape[i+1][1] - pos[1]) )
angle = angle + angle2D(p1, p2)
i = len(shape)-1
p1 = ( (shape[i][0] - pos[0]), (shape[i][1] - pos[1]) )
p2 = ( (shape[0][0] - pos[0]), (shape[0][1] - pos[1]) )
angle = angle + angle2D(p1, p2)
return math.fabs(angle)>=3.1415926535897932384626433832795
# written into the net. All members are "private".
class NetDistrictEdgeHandler(handler.ContentHandler):
def __init__(self):
self._haveDistrict = False
self._parsingDistrictShape = False
self._parsingLaneShape = False
self._currentID = ""
self._shape = ""
self._districtShapes = {}
self._laneShapes = {}
self._districtLanes = {}
self._laneDisttricts = {}
self._invalidatedLanes = []
self._laneSpeeds = {}
self._laneLengths = {}
self._noLanes = {}
def startElement(self, name, attrs):
if name == 'district':
self._haveDistrict = True
self._currentID = attrs['id']
self._districtLanes[self._currentID] = []
elif name == 'shape' and self._haveDistrict:
self._parsingDistrictShape = True
elif name == 'lane':
self._currentID = attrs['id']
self._parsingLaneShape = True
self._laneDisttricts[self._currentID] = []
self._laneSpeeds[self._currentID] = float(attrs['maxspeed'])
self._laneLengths[self._currentID] = float(attrs['length'])
edgeid = self._currentID
edgeid = edgeid[:edgeid.rfind("_")]
if edgeid in self._noLanes:
self._noLanes[edgeid] = self._noLanes[edgeid] + 1
else:
self._noLanes[edgeid] = 1
def characters(self, content):
if self._parsingDistrictShape:
self._shape += content
if self._parsingLaneShape:
self._shape += content
def endElement(self, name):
if name == 'district':
self._haveDistrict = False
elif name == 'shape' and self._haveDistrict:
self._parsingDistrictShape = False
if self._shape!='':
self._districtShapes[self._currentID] = parseShape(self._shape)
self._shape = ""
elif name == 'lane':
self._parsingLaneShape = False
if self._shape!='':
self._laneShapes[self._currentID] = parseShape(self._shape)
self._shape = ""
def computeWithin(self, complete):
for lane in self._laneShapes:
lshape = self._laneShapes[lane]
for district in self._districtShapes:
dshape = self._districtShapes[district]
found = False
for pos in lshape:
if not found and isWithin(pos, dshape):
found = True
self._districtLanes[district].append(lane)
self._laneDisttricts[lane].append(district)
if complete:
for lane in self._laneDisttricts:
if len(self._laneDisttricts[lane])>1:
self._invalidatedLanes.append(lane)
def writeResults(self, output, maxspeed, weighted):
fd = open(output, "w")
fd.write("<districts>\n")
for district in self._districtLanes:
lanes = 0
for lane in self._districtLanes[district]:
if lane not in self._invalidatedLanes and self._laneSpeeds[lane]<maxspeed:
lanes = lanes + 1
if lanes==0:
print "District '" + district + "' has no edges!"
else:
edges = {}
fd.write(" <district id=\"" + district + "\">\n")
for lane in self._districtLanes[district]:
edgeid = lane
edgeid = edgeid[:edgeid.rfind("_")]
if edgeid not in edges and lane not in self._invalidatedLanes and self._laneSpeeds[lane]<maxspeed:
weight = 1.
if weighted:
weight = float(self._laneSpeeds[lane]) * float(self._laneLengths[lane])
fd.write(" <dsource id=\"" + edgeid + "\" weight=\"" + str(weight) + "\"/>\n")
fd.write(" <dsink id=\"" + edgeid + "\" weight=\"" + str(weight) + "\"/>\n")
edges[edgeid] = 1
fd.write(" </district>\n")
fd.write("</districts>\n")
fd.close()
optParser = OptionParser()
optParser.add_option("-v", "--verbose", action="store_true", dest="verbose",
default=False, help="tell me what you are doing")
optParser.add_option("-c", "--complete", action="store_true", dest="complete",
default=False, help="Assigns only distinct lanes")
optParser.add_option("-n", "--net-files", dest="netfiles",
help="read SUMO network(s) from FILE(s) (mandatory)", metavar="FILE")
optParser.add_option("-o", "--output", dest="output",
help="write results to FILE (mandatory)", metavar="FILE")
optParser.add_option("-m", "--max-speed", type="float", dest="maxspeed",
default=1000.0, help="used lanes which speed is not greater than this (m/s)")
optParser.add_option("-w", "--weighted", action="store_true", dest="weighted",
default=False, help="Weights sources/sinks by lane number and length")
(options, args) = optParser.parse_args()
parser = make_parser()
reader = NetDistrictEdgeHandler()
parser.setContentHandler(reader)
for netfile in options.netfiles.split(","):
if options.verbose:
print "Reading net '" + netfile + "'"
parser.parse(netfile)
if options.verbose:
print "Calculating"
reader.computeWithin(options.complete)
if options.verbose:
print "Writing results"
reader.writeResults(options.output, options.maxspeed, options.weighted)
|