from __future__ import print_function
from __future__ import absolute_import
import os
import sys
import random
if 'SUMO_HOME' in os.environ:
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
import sumolib
def get_options(args=None):
optParser = sumolib.options.ArgumentParser(description="Generate parking areas along the edges")
optParser.add_argument("-n", "--net-file", category="input", dest="netfile",
help="define the net file (mandatory)")
optParser.add_argument("--selection-file", category="input", dest="selectionfile",
help="optionally restrict the parking area to the selected net part")
optParser.add_argument("-o", "--output-file", category="output", dest="outfile",
default="parkingareas.add.xml", help="define the output filename")
optParser.add_argument("-p", "--probability", category="processing", type=float, default=1,
help="Probability for an edge to receive a parkingArea")
optParser.add_argument("-L", "--length", category="processing", type=float, default=6,
help="Length required per parking space")
optParser.add_argument("-l", "--space-length", category="processing", type=float, default=5, dest="spaceLength",
help="visual length of each parking space")
optParser.add_argument("-w", "--width", category="processing", type=float,
help="visual width of each parking space")
optParser.add_argument("-r", "--random-capacity", category="processing", action="store_true", dest="randCapacity",
default=False, help="Randomize roadsideCapacity")
optParser.add_argument("--min", category="processing", type=int, default=0,
help="Minimum capacity for parkingAreas")
optParser.add_argument("--max", category="processing", type=int, default=int(1e9),
help="Maximum capacity for parkingAreas")
optParser.add_argument("--edge-type.keep", category="processing", dest="edgeTypeKeep",
help="Optional list of edge types to keep exclusively")
optParser.add_argument("--edge-type.remove", category="processing", dest="edgeTypeRemove",
help="Optional list of edge types to exclude")
optParser.add_argument("--keep-all", category="processing", action="store_true", default=False, dest="keepAll",
help="whether to keep parkingAreas with 0 capacity")
optParser.add_argument("--lefthand", category="processing", action="store_true", default=False, dest="lefthand",
help="whether to place parkingareas on the left of the road")
optParser.add_argument("-a", "--angle", category="processing", type=float,
help="parking area angle")
optParser.add_argument("--on-road", category="processing", action="store_true", default=False, dest="onRoad",
help="whether to place parkingareas directly on the road")
optParser.add_argument("--on-road.lane-offset", category="processing", type=int, default=0, dest="onRoadLaneOffset",
help="lane index to place on-road parking spaces on (use negative value to use all lanes)")
optParser.add_argument("--prefix", category="processing", default="pa", help="prefix for the parkingArea ids")
optParser.add_argument("-s", "--seed", category="processing", type=int, default=42, help="random seed")
optParser.add_argument("--random", category="processing", action="store_true", default=False,
help="use a random seed to initialize the random number generator")
optParser.add_argument("--vclass", category="processing", default="passenger",
help="only use edges which permit the given vehicle class")
optParser.add_argument("-v", "--verbose", category="processing", action="store_true",
default=False, help="tell me what you are doing")
options = optParser.parse_args(args=args)
if not options.netfile:
optParser.print_help()
sys.exit(1)
if options.edgeTypeKeep:
options.edgeTypeKeep = options.edgeTypeKeep.split(',')
if options.edgeTypeRemove:
options.edgeTypeRemove = options.edgeTypeRemove.split(',')
return options
def hasOppositeEdge(edge):
toNode = edge.getToNode()
fromNode = edge.getFromNode()
return fromNode in [e.getToNode() for e in toNode.getOutgoing()]
def main(options):
if not options.random:
random.seed(options.seed)
net = sumolib.net.readNet(options.netfile)
checkSelection = False
if options.selectionfile is not None:
net.loadSelection(options.selectionfile)
checkSelection = True
with open(options.outfile, 'w') as outf:
sumolib.writeXMLHeader(outf, "$Id$", "additional", options=options)
for edge in net.getEdges():
if options.edgeTypeKeep and not edge.getType() in options.edgeTypeKeep:
continue
if options.edgeTypeRemove and edge.getType() in options.edgeTypeRemove:
continue
if checkSelection and not edge.isSelected():
continue
lanes = edge.getLanes()
if options.lefthand:
lanes = reversed(lanes)
for lane in lanes:
if options.lefthand and lane.getNeigh() is not None:
break
laneIndex = lane.getIndex()
if options.onRoad and options.onRoadLaneOffset > -1:
if options.onRoadLaneOffset > laneIndex:
continue
elif options.onRoadLaneOffset < laneIndex:
break
if lane.allows(options.vclass):
if random.random() < options.probability:
capacity = lane.getLength() / options.length
if options.randCapacity:
capacity *= random.random()
if options.verbose and options.min > capacity:
print("ParkingArea on edge '%s' exceeds the available space by %.2f spaces "
"due to minimum capacity %d." % (edge.getID(), options.min - capacity, options.min))
capacity = min(options.max, max(options.min, int(capacity)))
if capacity > 0 or capacity == options.max or options.keepAll:
angle = '' if options.angle is None else ' angle="%s"' % options.angle
length = '' if options.spaceLength <= 0 else ' length="%s"' % options.spaceLength
width = '' if options.width is None else ' width="%s"' % options.width
onRoad = '' if not options.onRoad else ' onRoad="true"'
lefthand = '' if not options.lefthand else ' lefthand="true"'
idSuffix = '' if not options.onRoad else '_%s' % laneIndex
outf.write(' <parkingArea id="%s%s%s" lane="%s" roadsideCapacity="%s"%s%s%s%s%s/>\n' % (
options.prefix, edge.getID(), idSuffix, lane.getID(),
capacity, length, width, angle, lefthand, onRoad))
if not options.onRoad:
break
outf.write("</additional>\n")
if __name__ == "__main__":
if not main(get_options()):
sys.exit(1)