/* * 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.Route { using System; using System.Collections.Generic; using System.Xml.Serialization; [Serializable] public delegate bool RouteFunction(TrafficRoute r); [Serializable] public class RouteContainer { public static int NextId { get { return NextIdValue; } set { NextIdValue = value; } } private static int NextIdValue = 0; #region XmlExport [XmlAttribute(AttributeName = "Id")] public int Id { get; set; } [XmlAttribute(AttributeName = "RouteGeneratorId")] public int RouteGeneratorId { get; set; } [XmlAttributeAttribute(AttributeName = "Source")] public int XmlExportSource { get { return Source.Id; } set { Source = (TrafficModelLink)Importer.Lookup.Get().GetObject(value); } } [XmlAttributeAttribute(AttributeName = "Target")] public int XmlExportTarget { get { return Target.Id; } set { Target = (TrafficModelLink)Importer.Lookup.Get().GetObject(value); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] [XmlArray(ElementName = "Links")] [XmlArrayItem(ElementName = "l")] public int[] XmlExportLinks { get { int[] fs = new int[Links.Length]; for (int i = 0; i < Links.Length; i++) fs[i] = Links[i].Id; return fs; } set { Links = new TrafficModelLink[value.Length]; for (int i = 0; i < value.Length; i++) Links[i] = Importer.Lookup.Get().GetObject(value[i]); } } #endregion /* =========== Ignored XML Elements =========== */ #region XmlIgnore [XmlIgnore] public TrafficModelLink Source { get; private set; } [XmlIgnore] public TrafficModelLink Target { get; private set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] [XmlIgnore] public TrafficModelLink[] Links { get; private set; } [XmlIgnore] public int Count { get { int c = 1; if (parrallellLinks == null) return 1; foreach (KeyValuePair kv in parrallellLinks) { c = c * kv.Value.Length; } return c; } } [XmlIgnore] private KeyValuePair[] parrallellLinks; [XmlIgnore] private bool filledInParallelLinks = false; #endregion public RouteContainer() { RouteGeneratorId = 1; } public TrafficRoute GetShortestRoute(float t, VehicleClass c, Result.ResultData res) { if (c != null && res != null) { if (parrallellLinks == null) { return new TrafficRoute(this, Links, 0); } TrafficModelLink[] links = (TrafficModelLink[])Links.Clone(); int id = 0; int pos = 0; int baseId = 1; foreach (KeyValuePair kv in parrallellLinks) { float cost = float.PositiveInfinity; for (; pos < kv.Key; pos++) { t += links[pos].GetObservedTotalTravelTime(t, c, res); } int p = 0; for (int i = 0; i < kv.Value.Length; i++) { TrafficModelLink l = kv.Value[p]; float tCost = c.CalculateCost(l, res, t); if (tCost < cost) { cost = tCost; p = i; } } TrafficModelLink link = kv.Value[p]; id += baseId * p; baseId = baseId * kv.Value.Length; t += link.GetObservedTotalTravelTime(t, c, res); links[kv.Key] = link; pos++; } return new TrafficRoute(this, links, id); } return null; } public TrafficRoute GetRoute(int routeId) { if (routeId == 0) { return new TrafficRoute(this, Links, 0); } TrafficModelLink[] links = (TrafficModelLink[])Links.Clone(); int id = routeId; foreach (KeyValuePair kv in parrallellLinks) { int b = kv.Value.Length; links[kv.Key] = kv.Value[id % b]; id = id % b; } return new TrafficRoute(this, Links, routeId); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "id+1")] public RouteContainer(int id, TrafficModelLink source, TrafficModelLink target, TrafficModelLink[] links) { RouteContainer.NextId = Math.Max(RouteContainer.NextId, id + 1); Id = id; RouteGeneratorId = 1; Source = source; Target = target; Links = links; } public TrafficModelLink GetLink(int i) { if (i == 0) { return Source; } if (i <= Links.Length) { return Links[i - 1]; } if (i == Links.Length + 1) { return Target; } return null; } public System.Collections.IEnumerable Routes { get { foreach (TrafficRoute r in EachInternal(0, Links, 1, 0)) { yield return r; } } } public void FillInId() { if (Id == -1) { Id = RouteContainer.NextId; RouteContainer.NextId = RouteContainer.NextId + 1; } } public bool IsWithinPartion(IDictionary part, int idPart) { if (part != null) { if (part[Source.Source.Id] == idPart || part[Target.Source.Id] == idPart || part[Target.Target.Id] == idPart) { return true; } foreach (TrafficModelLink l in this.Links) { if (part[l.Source.Id] == idPart) { return true; } } } return false; } public bool IsValid() { foreach (TrafficRoute r in Routes) { if (!r.IsValid()) return false; } return true; } public bool Compare(RouteContainer rc) { this.FillInParallellRoutes(); if (rc == null || Links.Length != rc.Links.Length || rc.Source != Source || rc.Target != Target) { return false; } int paraPos = 0; for (int i = 0; i < Links.Length; i++) { if (parrallellLinks != null && paraPos < parrallellLinks.Length && parrallellLinks[paraPos].Key == i) { bool found = false; foreach (TrafficModelLink l in parrallellLinks[paraPos].Value) { if (l == rc.Links[i]) { found = true; break; } } if (!found) return false; paraPos++; } else { if (Links[i] != rc.Links[i]) return false; } } return true; } public void FillInParallellRoutes() { // Start to find valid parrell links if (filledInParallelLinks) return; filledInParallelLinks = true; List>> parrLinks = new List>>(); for (int i = 0; i < Links.Length; i++) { TrafficModelLink original = Links[i]; bool first = true; foreach (TrafficModelLink par in original.Source.LinksOut) { if (par != original && par.Target == original.Target) { bool add = true; if (parrLinks.Count > 0 && parrLinks[parrLinks.Count - 1].Key == i - 1) { foreach (TrafficModelLink l in parrLinks[parrLinks.Count - 1].Value) { if (!l.Turnings.Exists(delegate(Turning t) { return t.Destination == par; })) { add = false; }; } } else { TrafficModelLink before = i - 1 > 0 ? Links[i - 1] : Source; add = before.Turnings.Exists(delegate(Turning t) { return t.Destination == par; }); } if (add) { if (i < Links.Length - 1) { add = false; foreach (Turning t in par.Turnings) { if (t.Destination == Links[i + 1]) { add = true; break; } } } } if (add) { if (first) { first = false; parrLinks.Add(new KeyValuePair>(i, new List())); parrLinks[parrLinks.Count - 1].Value.Add(original); } parrLinks[parrLinks.Count - 1].Value.Add(par); } } } } if (parrLinks.Count == 0) return; parrallellLinks = new KeyValuePair[parrLinks.Count]; int pos = 0; foreach (KeyValuePair> posKV in parrLinks) { parrallellLinks[pos] = new KeyValuePair(posKV.Key, posKV.Value.ToArray()); pos++; } if (!IsValid()) { Console.WriteLine("OOOOPS"); } } private IEnumerable EachInternal(int i, TrafficModelLink[] routeLinks, int baseId, int id) { if (parrallellLinks == null) { yield return new TrafficRoute(this, routeLinks, 0); yield break; } int pos = parrallellLinks[i].Key; TrafficModelLink[] linksArray = parrallellLinks[i].Value; List links = new List(linksArray); bool next = i + 1 < parrallellLinks.Length; int childId = 0; foreach (TrafficModelLink l in links) { int nId = id + childId * baseId; routeLinks[pos] = l; if (next) { foreach (TrafficRoute r in EachInternal(i + 1, routeLinks, baseId * links.Count, nId)) { yield return r; } } else { yield return new TrafficRoute(this, (TrafficModelLink[])routeLinks.Clone(), nId); } childId++; } } } }