from __future__ import print_function
from __future__ import absolute_import
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import sumolib
import route2poly
def readPOI(traceFile, net):
trace = []
for poi in sumolib.xml.parse(traceFile, "poi"):
if poi.lon is None:
trace.append((poi.x, poi.y))
else:
trace.append(net.convertLonLat2XY(poi.lon, poi.lat))
yield "blub", trace
def readFCD(traceFile, net, geo):
"""Reads traces from a file in SUMO's fcd-output format.
The file needs to be sorted by vehicle id rather than by time!"""
trace = []
last = None
for v in sumolib.xml.parse_fast(traceFile, "vehicle", ("id", "x", "y")):
if last is None:
last = v.id
if last != v.id:
yield last, trace
trace = []
last = v.id
if geo:
trace.append(net.convertLonLat2XY(float(v.x), float(v.y)))
else:
trace.append((float(v.x), float(v.y)))
if trace:
yield last, trace
def readLines(traceFile, net, geo):
with open(traceFile) as traces:
for line in traces:
tid, traceString = line.split(":")
trace = [tuple(map(float, pos.split(","))) for pos in traceString.split()]
if geo:
trace = [net.convertLonLat2XY(*pos) for pos in trace]
yield tid.strip(), trace
if __name__ == "__main__":
ap = sumolib.options.ArgumentParser()
ap.add_argument("-v", "--verbose", action="store_true",
default=False, help="tell me what you are doing")
ap.add_argument("-n", "--net", help="SUMO network to use", category="input",
type=ap.net_file, metavar="FILE", required=True)
ap.add_argument("-t", "--trace", category="input", type=ap.file,
help="trace files to use, separated by comma", metavar="FILE", required=True)
ap.add_argument("-d", "--delta", default=1., type=float,
help="maximum distance between edge and trace points")
ap.add_argument("-a", "--air-dist-factor", default=2., type=float,
help="maximum factor between airline and route distance between successive trace points")
ap.add_argument("-o", "--output", help="route output", metavar="FILE", required=True)
ap.add_argument("-p", "--poi-output", category="output", type=ap.file,
help="generate POI output for the trace", metavar="FILE")
ap.add_argument("-y", "--polygon-output", category="output", type=ap.file,
help="generate polygon output for the mapped edges", metavar="FILE")
ap.add_argument("--geo", action="store_true",
default=False, help="read trace with geo-coordinates")
ap.add_argument("--direction", action="store_true",
default=False, help="try to use direction of consecutive points when mapping")
ap.add_argument("--vehicle-class", default=None,
help="filters the edges by the vehicle class the route is meant for")
ap.add_argument("--fill-gaps", default=0., type=float,
help="repair disconnected routes bridging gaps of up to x meters")
ap.add_argument("-g", "--gap-penalty", default=-1, type=float,
help="penalty to add for disconnected routes " +
"(default of -1 adds the distance between the two endpoints as penalty)")
ap.add_argument("--internal", action="store_true",
default=False, help="include internal edges in generated shapes")
ap.add_argument("--spread", type=float, help="spread polygons laterally to avoid overlap")
ap.add_argument("--blur", type=float,
default=0, help="maximum random disturbance to route geometry")
ap.add_argument("-l", "--layer", default=100, help="layer for generated polygons")
ap.add_argument("-b", "--debug", action="store_true",
default=False, help="print out the debugging messages")
options = ap.parse_args()
if options.verbose:
print("Reading net ...")
net = sumolib.net.readNet(options.net, withInternal=True)
if options.verbose:
print("Reading traces ...")
tracefiles = options.trace.split(',')
for t in tracefiles:
if len(tracefiles) == 1:
outfile = options.output
else:
outfile = os.path.basename(t).split('.')[0] + '.tc.xml'
with open(outfile, "w") as outf:
sumolib.xml.writeHeader(outf, root='routes')
poiOut = None
if options.poi_output is not None:
if len(tracefiles) == 1:
poi_output = options.poi_output
else:
poi_output = os.path.basename(t).split('.')[0] + '.poi.xml'
poiOut = open(poi_output, "w")
sumolib.xml.writeHeader(poiOut, root='additional')
polyOut = None
if options.polygon_output is not None:
if len(tracefiles) == 1:
polygon_output = options.polygon_output
else:
polygon_output = os.path.basename(t).split('.')[0] + '.poly.xml'
polyOut = open(polygon_output, "w")
sumolib.xml.writeHeader(polyOut, root='additional')
colorgen = sumolib.miscutils.Colorgen(('random', 1, 1))
with open(t) as peek:
head = peek.read(10000)
if "<poi" in head:
traces = readPOI(t, net)
elif "<fcd" in head:
traces = readFCD(t, net, options.geo)
else:
traces = readLines(t, net, options.geo)
mapOpts = (options.delta, options.verbose, options.air_dist_factor,
options.fill_gaps, options.gap_penalty, options.debug, options.direction, options.vehicle_class)
for tid, trace in traces:
if poiOut is not None:
for idx, pos in enumerate(trace):
poiOut.write(' <poi id="%s:%s" x="%s" y="%s"/>\n' % (tid, idx, pos[0], pos[1]))
edges = [e.getID() for e in sumolib.route.mapTrace(
trace, net, *mapOpts) if e.getFunction() != "internal"]
edges = [edge for i, edge in enumerate(edges) if i == 0 or edge != edges[i-1]]
if polyOut is not None and edges:
route2poly.generate_poly(options, net, tid, colorgen(), edges, polyOut)
if edges:
outf.write(' <route id="%s" edges="%s"/>\n' % (tid, " ".join(edges)))
elif options.verbose:
print("No edges are found for %s." % (tid))
outf.write('</routes>\n')
if poiOut is not None:
poiOut.write('</additional>\n')
poiOut.close()
if polyOut is not None:
polyOut.write('</additional>\n')
polyOut.close()