/* * Copyright (c) 2005-2006 Erik Tigerholm * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ namespace OpenTraffic.Model.Importer.Mezzo { using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; using OpenTraffic.Model.Route; using OpenTraffic.Model.SpeedFunctions; public class MezzoImporter : IImporterModel { private delegate void PropertyCommand(Dictionary value); private string basename; private TrafficModel model; private DemandCommand demandCommand; private TrafficGenerator.NonProbOD trafficGen; private Dictionary classes; private Result.ResultData result; private Dictionary serverRate; private float stdVehicleLength = 7.0f; public string GetName() { return "Mezzo"; } public string GetExtensions() { return "Mezzo|*.mezzo;"; } public static string GetString(int col, ArrayList values) { if (values != null) { return (string)values[col]; } return string.Empty; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "float")] public static float GetFloat(int col, ArrayList values) { NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat; float val = 0; if (values != null) { val = float.Parse((string)values[col], nfi); } return val; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int")] public static int GetInt(int col, ArrayList values) { NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat; int val = 0; if (values != null) { val = int.Parse((string)values[col], nfi); } return val; } private static string GetNextToken(StreamReader sr) { // Skip white space; string str = ""; while ((char)sr.Peek() == ' ' || sr.Peek() == '\t' || sr.Peek() == '\n') sr.Read(); while (sr.Peek() != ' ' && sr.Peek() != '\t' && sr.Peek() != '\n' && (sr.Peek() != '{' || string.IsNullOrEmpty(str)) && (sr.Peek() != '}' || string.IsNullOrEmpty(str))) { str += (char)sr.Read(); } //System.Console.WriteLine("Token " + str); return str.Trim(); } private ArrayList FetchList(StreamReader sr, Command cmd, int number) { return FetchList(sr, cmd, number, false); } private ArrayList FetchList(StreamReader sr, Command cmd, int number, bool init) { ArrayList values = new ArrayList(); Dictionary properties = new Dictionary(); int n = 0; bool prop = true; while (n < number) { string value = GetNextToken(sr); if (!init) { if (value == "{") { init = true; // Call on first init if (prop) cmd.BeforeList(properties); prop = false; } if (value[value.Length - 1] == ':') { properties.Add(value.Substring(0, value.Length - 1), GetNextToken(sr)); } } else { switch (value) { case "}": if (cmd == null) return values; cmd.LoadItem(values); init = false; values.Clear(); n++; break; case "{": values.Add(FetchList(sr, null, 1, true)); break; default: values.Add(value); break; } } } return values; } private void FetchFile(StreamReader sr, PropertyCommand command, Dictionary commands) { Dictionary values = new Dictionary(); while (!sr.EndOfStream) { string str = sr.ReadLine(); if (str.Length > 0 && str[0] != '#') { String[] cols = str.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); string cmd = cols[0]; Char type = cmd[cmd.Length - 1]; cmd = cmd.Substring(0, cmd.Length - 1); switch (type) { case ':': if (commands != null && commands.ContainsKey(cmd)) { FetchList(sr, commands[cmd], int.Parse(cols[1])); } break; case '=': if (cols.Length == 1) { values.Add(cmd, "0"); } else { values.Add(cmd, cols[1]); } break; default: if (commands != null && commands.ContainsKey("")) { String[] tCols = str.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); ArrayList ar = new ArrayList(tCols); commands[""].LoadItem(ar); } break; } } } if (command != null) { command(values); } } public void LoadNodes(ArrayList values) { int id = GetInt(0, values); int type = GetInt(1, values); float x = GetInt(2, values); float y = GetInt(3, values); IntersectionNode n = null; float dx = 0; switch (type) { case 1: dx = 10.0f; goto case 2; case 2: TrafficZone z = new TrafficZone(id, "Zone #" + id, x + dx, y + dx); n = z; model.TrafficZones.Add(z); break; case 3: n = new IntersectionNode(id, "Node #" + id, x, y); model.IntersectionNodes.Add(n); break; } if (n != null) { Lookup.Get().Add(id, n); } } public void LoadLinks(ArrayList values) { int id = GetInt(0, values); int startId = GetInt(1, values); int stopId = GetInt(2, values); float length = GetFloat(3, values); float nLanes = GetInt(4, values); int spfId = GetInt(5, values); IntersectionNode start = Lookup.Get().GetObject(startId); IntersectionNode stop = Lookup.Get().GetObject(stopId); SpeedFlow sf = Lookup.Get().GetObject(spfId); // SpeedFunctions.GeneralisedBurghout gb = (SpeedFunctions.GeneralisedBurghout)sf; TrafficModelLink link = null; if (start.GetType() == typeof(TrafficZone) || stop.GetType() == typeof(TrafficZone)) { TrafficModelConnector conn = new TrafficModelConnector(id, start, stop, "Connector #" + id, "", 0, 0, length, nLanes, 10 * length * nLanes / stdVehicleLength, null, null, sf); link = conn; model.TrafficModelConnectors.Add(conn); } else { // float cap = gb.kMax * length * nLanes; float cap = length * nLanes / stdVehicleLength; link = new TrafficModelLink(id, start, stop, "Link #" + id, "", 0, 0, length, nLanes, cap, null, null, sf); model.TrafficModelLinks.Add(link); } if (link != null) { Lookup.Get().Add(id, link); } } public void LoadSpeedFlows(ArrayList values) { if (GetInt(1, values) != 2) { throw new NotImplementedException(); } int id = GetInt(0, values); float vMax = GetInt(2, values); float vMin = GetInt(3, values); float kMax = GetInt(4, values) / 1000.0f; float kMin = GetInt(5, values) / 1000.0f; float a = GetFloat(6, values); float b = GetFloat(7, values); SpeedFlow sf = new SpeedFunctions.GeneralisedBurghout(id.ToString(), "SpeedDensity Burghout " + id, vMax, vMin, kMax, kMin, a, b); this.model.SpeedFlows.Add(sf); Lookup.Get().Add(id, sf); } public void LoadRoutes(ArrayList values) { if (values != null) { int id = GetInt(0, values); int nLinks = GetInt(3, values); ArrayList linkIds = (ArrayList)values[4]; TrafficModelLink[] links = new TrafficModelLink[nLinks - 2]; TrafficModelLink start = Lookup.Get().GetObject(GetInt(0, linkIds)); TrafficModelLink stop = Lookup.Get().GetObject(GetInt(nLinks - 1, linkIds)); int k = 0; for (int i = 1; i < nLinks - 1; i++) { links[k++] = Lookup.Get().GetObject(GetInt(i, linkIds)); } model.Routes.Add(new RouteContainer(id, start, stop, links)); } } public void LoadClasses(ArrayList values) { int id = GetInt(0, values); string name = GetString(1, values); float percentage = GetFloat(2, values); float length = GetFloat(3, values); //@todo Cost per distance not beatiful. VehicleClass c = new VehicleClass(id, length / stdVehicleLength, 1, 1, name, 1.0f / 900.0f, 0.5f / 1000.0f); // Hard code from contram model.VehicleClasses.Add(c); classes.Add(c, percentage); } public void LoadTurning(ArrayList values) { int id = GetInt(0, values); int orgId = GetInt(3, values); int destId = GetInt(4, values); int serverId = GetInt(2, values); float rate = serverRate[serverId]; TrafficModelLink org = Lookup.Get().GetObject(orgId); TrafficModelLink dest = Lookup.Get().GetObject(destId); Turning turn = new Turning(id, org, dest, rate); org.Turnings.Add(turn); Lookup.Get().Add(id, turn); } public void LoadSignalControl(ArrayList values) { if (values != null) { int nPlanes = GetInt(1, values); for (int i = 0; i < nPlanes; i++) { ArrayList planValues = (ArrayList)values[i + 2]; int idPlan = GetInt(0, planValues); float start = GetFloat(1, planValues); float stop = GetFloat(2, planValues); float offset = GetFloat(3, planValues); float cycleTime = GetFloat(4, planValues); int nStages = GetInt(5, planValues); TimeSlice active = new TimeSlice(start, stop); float checkStart = offset; //stem.Console.WriteLine("SignalControl: " + idPlan); SignalPlans.Fixed plan = new SignalPlans.Fixed(idPlan.ToString(), "Mezzo " + idPlan, cycleTime, offset, active); for (int j = 0; j < nStages; j++) { ArrayList stageValues = (ArrayList)planValues[j + 6]; float stageStart = GetFloat(1, stageValues); // BE CAREFUL HERE. WE ARE COMPARING FLOAT WITH FLOAT. SHOULD WORK BECAUSE START AND DURATION IS // ALWAYS SMALL RELATIVE) INTEGERS. BUT IF YOU HAVE PROBLEM HERE AND YOU DO NOT HAVE OVERLAPPING // STAGES YOU SHOULD LOOK INTO THIS. if (stageStart != checkStart) throw new NotImplementedException("Does not work with overlapping stages"); float duration = GetFloat(2, stageValues); int nTurns = GetInt(3, stageValues); checkStart += duration; // System.Console.WriteLine("\tStage: " + j); // Dictionary alreadyAdded = new Dictionary(); List turns = new List(nTurns); for (int k = 0; k < nTurns; k++) { int turnId = GetInt(k, (ArrayList)stageValues[4]); Turning turn = Lookup.Get().GetObject(turnId); // System.Console.WriteLine("\t\tGreen " + turn.Origin.Id + " -> " + turn.Destination.Id); turns.Add(turn); } plan.Stages.Add(new SignalPlans.SignalStage(duration, turns)); } model.SignalPlans.Add(plan); } } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "OutFlow")] public void LoadOutFlow(ArrayList values) { if (values != null) { int id = GetInt(0, values); TrafficModelLink l = Lookup.Get().GetObject(id); for (int i = 1; i < values.Count; i++) { Result.ResultLink rl = result.GetLinkResultFromBin(i - 1, l); rl.FlowOut = GetFloat(i, values) / (900); } } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "InFlow")] public void LoadInFlow(ArrayList values) { if (values != null) { int id = GetInt(0, values); TrafficModelLink l = Lookup.Get().GetObject(id); for (int i = 1; i < values.Count; i++) { Result.ResultLink rl = result.GetLinkResultFromBin(i - 1, l); rl.FlowIn = GetFloat(i, values) / (900); } } } public void LoadTravelTime(ArrayList values) { if (values != null) { int id = GetInt(0, values); TrafficModelLink l = Lookup.Get().GetObject(id); for (int i = 1; i < values.Count; i++) { float speed = GetFloat(i, values); float traveltime = speed == 0.0f ? 0.0f : 3.6f * l.Length / speed; Result.ResultLink rl = result.GetLinkResultFromBin(i - 1, l); rl.TravelTime = traveltime; } } } public void LoadServers(ArrayList values) { int id = GetInt(0, values); float rate = GetFloat(2, values); serverRate.Add(id, rate); } public void LoadParameters(Dictionary dict) { if (dict != null) { NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat; float outflow = float.Parse(dict["moe_outflow_update"], nfi); float inflow = float.Parse(dict["moe_inflow_update"], nfi); float speed = float.Parse(dict["moe_speed_update"], nfi); stdVehicleLength = float.Parse(dict["standard_veh_length"], nfi); if (speed != outflow || speed != inflow) { throw new NotImplementedException("Output update frequence should be same for all variables."); } model.ResultFactory = new Result.FixedFactory(model.StartTime, model.StopTime, speed); result = model.ResultFactory.CreateResult(); result.Name = "Mezzo"; model.ResultStore.AddResult(result); } } public void Property(Dictionary dict) { if (dict != null) { model.StartTime = int.Parse(dict["starttime"]); model.StopTime = int.Parse(dict["stoptime"]); if (dict.ContainsKey("parameters")) { string filename = dict["parameters"]; StreamReader sr = null; try { sr = new StreamReader(basename + filename); FetchFile(sr, LoadParameters, null); } finally { if (sr != null) { sr.Close(); } } } Dictionary> commands = getCommands(); foreach (KeyValuePair> kv in commands) { if (dict.ContainsKey(kv.Key)) { string filename = dict[kv.Key]; StreamReader sr = null; try { sr = new StreamReader(basename + filename); FetchFile(sr, null, kv.Value); } finally { if (sr != null) { sr.Close(); } } foreach (KeyValuePair kvCmd in kv.Value) { kvCmd.Value.Close(); } } } } } private Dictionary> getCommands() { Dictionary> commands; commands = new Dictionary>(); commands.Add("network", new Dictionary()); commands.Add("routes", new Dictionary()); commands.Add("vehicletypes", new Dictionary()); commands.Add("demand", new Dictionary()); commands.Add("turnings", new Dictionary()); commands.Add("signals", new Dictionary()); commands.Add("outflows", new Dictionary()); commands.Add("inflows", new Dictionary()); commands.Add("speeds", new Dictionary()); commands["network"].Add("nodes", new SimpleCommand(LoadNodes)); commands["network"].Add("links", new SimpleCommand(LoadLinks)); commands["network"].Add("sdfuncs", new SimpleCommand(LoadSpeedFlows)); commands["network"].Add("servers", new SimpleCommand(LoadServers)); commands["routes"].Add("routes", new SimpleCommand(LoadRoutes)); commands["vehicletypes"].Add("vtypes", new SimpleCommand(LoadClasses)); commands["demand"].Add("od_pairs", demandCommand); commands["turnings"].Add("turnings", new SimpleCommand(LoadTurning)); commands["signals"].Add("controls", new SimpleCommand(LoadSignalControl)); commands["outflows"].Add("", new SimpleCommand(LoadOutFlow)); commands["inflows"].Add("", new SimpleCommand(LoadInFlow)); commands["speeds"].Add("", new SimpleCommand(LoadTravelTime)); return commands; } public void LoadFile(FileInfo file, OpenTraffic.Model.TrafficModel m) { if (file != null && m != null) { serverRate = new Dictionary(); model = m; model.Reset(); Lookup.Get().Clear(); trafficGen = new TrafficGenerator.NonProbOD(); classes = new Dictionary(); demandCommand = new DemandCommand(classes, trafficGen); basename = file.DirectoryName + "\\"; StreamReader sr = null; try { sr = new StreamReader(file.FullName, Encoding.GetEncoding(28591)); //WESTER EUROPE FetchFile(sr, Property, null); model.TrafficGenerator = trafficGen; // resFact.Step = Math.Max(1800 * 2, resFact.Step); model.StopCriterias.Add(new StopCriteria.AverageAbsoluteDifference(1.0f, 3)); model.PostLoad(); foreach (TrafficModelConnector c in model.TrafficModelConnectors) c.GenerateShape(4); foreach (TrafficModelLink c in model.TrafficModelLinks) c.GenerateShape(4); } finally { if (sr != null) { sr.Close(); } } } } } }