/// <summary> /// Calculates all routes between all sources and all targets. /// </summary> /// <returns></returns> public sealed override Result <EdgePath <T>[][]> TryCalculateRaw <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets, RoutingSettings <T> settings) { try { if (!_db.Supports(profileInstance.Profile)) { return(new Result <EdgePath <T>[][]>("Routing profile is not supported.", (message) => { return new Exception(message); })); } var maxSearch = weightHandler.Infinite; if (settings != null) { if (!settings.TryGetMaxSearch(profileInstance.Profile.FullName, out maxSearch)) { maxSearch = weightHandler.Infinite; } } ContractedDb contracted; EdgePath <T>[][] paths = null; bool useContracted = false; if (_db.TryGetContracted(profileInstance.Profile, out contracted)) { // contracted calculation. useContracted = true; if (_db.HasComplexRestrictions(profileInstance.Profile) && !contracted.HasEdgeBasedGraph) { // there is no edge-based graph for this profile but the db has complex restrictions, don't use the contracted graph. Logging.Logger.Log("Router", Logging.TraceEventType.Warning, "There is a vertex-based contracted graph but also complex restrictions. Not using the contracted graph, add an edge-based contracted graph."); useContracted = false; } if (!weightHandler.CanUse(contracted)) { // there is a contracted graph but it is not equipped to handle this weight-type. Logging.Logger.Log("Router", Logging.TraceEventType.Warning, "There is a contracted graph but it's not built for the given weight calculations, using the default but slow implementation."); useContracted = false; } } if (useContracted) { if (!contracted.HasEdgeBasedGraph) { // use node-based routing. var algorithm = new Itinero.Algorithms.Contracted.ManyToManyBidirectionalDykstra <T>(_db, profileInstance.Profile, weightHandler, sources, targets, maxSearch); algorithm.Run(); if (!algorithm.HasSucceeded) { return(new Result <EdgePath <T>[][]>(algorithm.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } // build all routes. paths = new EdgePath <T> [sources.Length][]; for (var s = 0; s < sources.Length; s++) { paths[s] = new EdgePath <T> [targets.Length]; for (var t = 0; t < targets.Length; t++) { paths[s][t] = algorithm.GetPath(s, t); } } } else { // use edge-based routing. var algorithm = new Itinero.Algorithms.Contracted.EdgeBased.ManyToManyBidirectionalDykstra <T>(_db, profileInstance.Profile, weightHandler, sources, targets, maxSearch); algorithm.Run(); if (!algorithm.HasSucceeded) { return(new Result <EdgePath <T>[][]>(algorithm.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } // build all routes. paths = new EdgePath <T> [sources.Length][]; for (var s = 0; s < sources.Length; s++) { paths[s] = new EdgePath <T> [targets.Length]; for (var t = 0; t < targets.Length; t++) { paths[s][t] = algorithm.GetPath(s, t); } } } } if (paths == null) { // use non-contracted calculation. var algorithm = new Itinero.Algorithms.Default.ManyToMany <T>(_db, weightHandler, sources, targets, maxSearch); algorithm.Run(); if (!algorithm.HasSucceeded) { return(new Result <EdgePath <T>[][]>(algorithm.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } // build all routes. paths = new EdgePath <T> [sources.Length][]; for (var s = 0; s < sources.Length; s++) { paths[s] = new EdgePath <T> [targets.Length]; for (var t = 0; t < targets.Length; t++) { paths[s][t] = algorithm.GetPath(s, t); } } } return(new Result <EdgePath <T>[][]>(paths)); } catch (Exception ex) { return(new Result <EdgePath <T>[][]>(ex.Message, (m) => ex)); } }
/// <summary> /// Calculates all routes between all sources and all targets. /// </summary> /// <returns></returns> public sealed override Result <T[][]> TryCalculateWeight <T>(Profile profile, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets, ISet <int> invalidSources, ISet <int> invalidTargets, RoutingSettings <T> settings) { if (!_db.Supports(profile)) { return(new Result <T[][]>("Routing profile is not supported.", (message) => { return new Exception(message); })); } var maxSearch = weightHandler.Infinite; if (settings != null) { if (!settings.TryGetMaxSearch(profile.Name, out maxSearch)) { maxSearch = weightHandler.Infinite; } } ContractedDb contracted; T[][] weights = null; bool useContracted = false; if (_db.TryGetContracted(profile, out contracted)) { // contracted calculation. useContracted = true; if (_db.HasComplexRestrictions(profile) && !contracted.HasEdgeBasedGraph) { // there is no edge-based graph for this profile but the db has complex restrictions, don't use the contracted graph. Logging.Logger.Log("Router", Logging.TraceEventType.Warning, "There is a vertex-based contracted graph but also complex restrictions. Not using the contracted graph, add an edge-based contracted graph."); useContracted = false; } if (!weightHandler.CanUse(contracted)) { // there is a contracted graph but it is not equipped to handle this weight-type. Logging.Logger.Log("Router", Logging.TraceEventType.Warning, "There is a contracted graph but it's not built for the given weight calculations, using the default but slow implementation."); useContracted = false; } } if (useContracted) { if (!contracted.HasEdgeBasedGraph) { // use node-based routing. var algorithm = new Itinero.Algorithms.Contracted.ManyToManyBidirectionalDykstra <T>(_db, profile, weightHandler, sources, targets, maxSearch); algorithm.Run(); if (!algorithm.HasSucceeded) { return(new Result <T[][]>(algorithm.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } weights = algorithm.Weights; } else { // use edge-based routing. var algorithm = new Itinero.Algorithms.Contracted.EdgeBased.ManyToManyBidirectionalDykstra <T>(_db, profile, weightHandler, sources, targets, maxSearch); algorithm.Run(); if (!algorithm.HasSucceeded) { return(new Result <T[][]>(algorithm.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } weights = algorithm.Weights; } } else { // use regular graph. if (_db.HasComplexRestrictions(profile)) { var algorithm = new Itinero.Algorithms.Default.EdgeBased.ManyToMany <T>(this, weightHandler, _db.GetGetRestrictions(profile, true), sources, targets, maxSearch); algorithm.Run(); if (!algorithm.HasSucceeded) { return(new Result <T[][]>(algorithm.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } weights = algorithm.Weights; } else { var algorithm = new Itinero.Algorithms.Default.ManyToMany <T>(_db, weightHandler, sources, targets, maxSearch); algorithm.Run(); if (!algorithm.HasSucceeded) { return(new Result <T[][]>(algorithm.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } weights = algorithm.Weights; } } // check for invalids. var invalidTargetCounts = new int[targets.Length]; for (var s = 0; s < weights.Length; s++) { var invalids = 0; for (var t = 0; t < weights[s].Length; t++) { if (t != s) { if (weightHandler.GetMetric(weights[s][t]) == float.MaxValue) { invalids++; invalidTargetCounts[t]++; if (invalidTargetCounts[t] > (sources.Length - 1) / 2) { invalidTargets.Add(t); } } } } if (invalids > (targets.Length - 1) / 2) { invalidSources.Add(s); } } return(new Result <T[][]>(weights)); }