/// <summary> /// Calculates all weights between all sources and all targets. /// </summary> /// <returns></returns> public abstract Result <T[][]> TryCalculateWeight <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets, ISet <int> invalidSources, ISet <int> invalidTargets, RoutingSettings <T> settings = null) where T : struct;
/// <summary> /// Calculates a route between the two directed edges. The route starts in the direction of the edge and ends with an arrive in the direction of the target edge. /// </summary> /// <returns></returns> public abstract Result <EdgePath <T> > TryCalculateRaw <T>(IProfileInstance profile, WeightHandler <T> weightHandler, long sourceDirectedEdge, long targetDirectedEdge, RoutingSettings <T> settings = null) where T : struct;
/// <summary> /// Calculates all routes between all sources and all targets. /// </summary> /// <returns></returns> public abstract Result <EdgePath <T>[][]> TryCalculateRaw <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets, RoutingSettings <T> settings = null) where T : struct;
/// <summary> /// Calculates all routes between all sources and all targets. /// </summary> /// <returns></returns> public sealed override Result <EdgePath <T>[][]> TryCalculateRaw <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 <EdgePath <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; if (_db.TryGetContracted(profile, out contracted)) { Logging.Logger.Log("Router", Logging.TraceEventType.Warning, "Many to many route calculations are not possible yet using contracted algorithms."); } // 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. var 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)); }
/// <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)); }
/// <summary> /// Calculates a route between the two directed edges. The route starts in the direction of the edge and ends with an arrive in the direction of the target edge. /// </summary> /// <returns></returns> public sealed override Result <EdgePath <T> > TryCalculateRaw <T>(Profile profile, WeightHandler <T> weightHandler, long sourceDirectedEdge, long targetDirectedEdge, RoutingSettings <T> settings) { if (!_db.Supports(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(profile.Name, out maxSearch)) { maxSearch = weightHandler.Infinite; } } var sourcePath = _db.GetPathForEdge(weightHandler, sourceDirectedEdge, true); var targetPath = _db.GetPathForEdge(weightHandler, targetDirectedEdge, false); if (sourceDirectedEdge == targetDirectedEdge) { // when edges match, path is always the edge itself. var edgePath = sourcePath; if (edgePath != null) { return(new Result <EdgePath <T> >(edgePath)); } } EdgePath <T> path; ContractedDb contracted; 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 (!contracted.HasEdgeBasedGraph) { Logging.Logger.Log("Router", Logging.TraceEventType.Warning, "There is a vertex-based contracted graph but it cannot be used to calculate routes with a start and end edge in a specific direction."); useContracted = false; } } if (useContracted) { // use the contracted graph. path = null; List <uint> vertexPath = null; if (!contracted.HasEdgeBasedGraph) { // use node-based routing. throw new Exception("Cannot use vertex-based contracted graph for edge-based calculations."); } else { // use edge-based routing. var bidirectionalSearch = new Algorithms.Contracted.EdgeBased.BidirectionalDykstra <T>(contracted.EdgeBasedGraph, weightHandler, new EdgePath <T>[] { sourcePath }, new EdgePath <T>[] { targetPath }, _db.GetGetRestrictions(profile, null)); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } vertexPath = bidirectionalSearch.GetPath(); } // expand vertex path using the regular graph. var source = _db.CreateRouterPointForEdge(sourceDirectedEdge, true); var target = _db.CreateRouterPointForEdge(targetDirectedEdge, false); path = _db.BuildEdgePath(weightHandler, source, target, vertexPath); } else { // use the regular graph. if (_db.HasComplexRestrictions(profile)) { var sourceSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profile, true), new EdgePath <T>[] { sourcePath }, maxSearch, false); var targetSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profile, false), new EdgePath <T>[] { targetPath }, maxSearch, true); var bidirectionalSearch = new Algorithms.Default.EdgeBased.BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } path = bidirectionalSearch.GetPath(); } else { var sourceSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, null, weightHandler, new EdgePath <T>[] { sourcePath }, maxSearch, false); var targetSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, null, weightHandler, new EdgePath <T>[] { targetPath }, maxSearch, true); var bidirectionalSearch = new BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } path = bidirectionalSearch.GetPath(); } } return(new Result <EdgePath <T> >(path)); }
/// <summary> /// Calculates a route between the two locations. /// </summary> /// <returns></returns> public sealed override Result <EdgePath <T> > TryCalculateRaw <T>(Profile profile, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, RoutingSettings <T> settings) { if (!_db.Supports(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(profile.Name, out maxSearch)) { maxSearch = weightHandler.Infinite; } } EdgePath <T> path; ContractedDb contracted; 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 (useContracted) { // use the contracted graph. path = null; List <uint> vertexPath = null; if (!contracted.HasEdgeBasedGraph) { // use node-based routing. var bidirectionalSearch = new Itinero.Algorithms.Contracted.BidirectionalDykstra <T>(contracted.NodeBasedGraph, weightHandler, source.ToEdgePaths(_db, weightHandler, true), target.ToEdgePaths(_db, weightHandler, false)); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } vertexPath = bidirectionalSearch.GetPath(); } else { // use edge-based routing. var bidirectionalSearch = new Itinero.Algorithms.Contracted.EdgeBased.BidirectionalDykstra <T>(contracted.EdgeBasedGraph, weightHandler, source.ToEdgePaths(_db, weightHandler, true), target.ToEdgePaths(_db, weightHandler, false), _db.GetGetRestrictions(profile, null)); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } vertexPath = bidirectionalSearch.GetPath(); } // expand vertex path using the regular graph. path = _db.BuildEdgePath(weightHandler, source, target, vertexPath); } else { // use the regular graph. if (_db.HasComplexRestrictions(profile)) { var sourceSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profile, true), source.ToEdgePaths(_db, weightHandler, true), maxSearch, false); var targetSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profile, false), target.ToEdgePaths(_db, weightHandler, false), maxSearch, true); var bidirectionalSearch = new Algorithms.Default.EdgeBased.BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } path = bidirectionalSearch.GetPath(); } else { var sourceSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, null, weightHandler, source.ToEdgePaths(_db, weightHandler, true), maxSearch, false); var targetSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, null, weightHandler, target.ToEdgePaths(_db, weightHandler, false), maxSearch, true); var bidirectionalSearch = new BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } path = bidirectionalSearch.GetPath(); } } if (source.EdgeId == target.EdgeId) { // check for a shorter path on the same edge. var edgePath = source.EdgePathTo(_db, weightHandler, target); if (edgePath != null && weightHandler.IsSmallerThan(edgePath.Weight, path.Weight)) { path = edgePath; } } return(new Result <EdgePath <T> >(path)); }
/// <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 && !contracted.NodeBasedIsEdgedBased)) { // 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 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); } } } else if (contracted.HasNodeBasedGraph && contracted.NodeBasedIsEdgedBased) { // use vertex-based graph for edge-based routing. var algorithm = new Itinero.Algorithms.Contracted.Dual.ManyToMany.VertexToVertexAlgorithm <T>(contracted.NodeBasedGraph, weightHandler, Itinero.Algorithms.Contracted.Dual.RouterPointExtensions.ToDualDykstraSources(sources, _db, weightHandler, true), Itinero.Algorithms.Contracted.Dual.RouterPointExtensions.ToDualDykstraSources(targets, _db, weightHandler, false), 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++) { var path = algorithm.GetPath(s, t); if (path != null) { path = _db.BuildDualEdgePath(weightHandler, sources[s], targets[t], path); } paths[s][t] = path; } } } else { // 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); } } } } 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 a route between the two directed edges. The route starts in the direction of the edge and ends with an arrive in the direction of the target edge. /// </summary> /// <returns></returns> public sealed override Result <EdgePath <T> > TryCalculateRaw <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, long sourceDirectedEdge, long targetDirectedEdge, 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; } } var sourcePath = _db.GetPathForEdge(weightHandler, sourceDirectedEdge, true); var targetPath = _db.GetPathForEdge(weightHandler, targetDirectedEdge, false); if (sourcePath == null) { return(new Result <EdgePath <T> >("Source edge cannot be routed along in the requested direction.")); } if (targetPath == null) { return(new Result <EdgePath <T> >("Target edge cannot be routed along in the requested direction.")); } if (sourceDirectedEdge == targetDirectedEdge) { // when edges match, path is always the edge itself. var edgePath = sourcePath; if (edgePath != null) { return(new Result <EdgePath <T> >(edgePath)); } } EdgePath <T> path; ContractedDb contracted; bool useContracted = false; if (_db.TryGetContracted(profileInstance.Profile, out contracted)) { // contracted calculation. useContracted = true; if (_db.HasComplexRestrictions(profileInstance.Profile) && (!contracted.HasEdgeBasedGraph && !contracted.NodeBasedIsEdgedBased)) { // 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 (!contracted.HasEdgeBasedGraph && !contracted.NodeBasedIsEdgedBased) { Logging.Logger.Log("Router", Logging.TraceEventType.Warning, "There is a vertex-based contracted graph but it cannot be used to calculate routes with a start and end edge in a specific direction."); useContracted = false; } } if (useContracted) { // use the contracted graph. path = null; List <uint> vertexPath = null; if (contracted.HasEdgeBasedGraph) { // use edge-based routing. var bidirectionalSearch = new Algorithms.Contracted.EdgeBased.BidirectionalDykstra <T>(contracted.EdgeBasedGraph, weightHandler, new EdgePath <T>[] { sourcePath }, new EdgePath <T>[] { targetPath }, _db.GetGetRestrictions(profileInstance.Profile, null)); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } vertexPath = bidirectionalSearch.GetPath(); } else if (contracted.HasNodeBasedGraph && contracted.NodeBasedIsEdgedBased) { // use vertex-based graph for edge-based routing. var sourceDirectedId = new DirectedEdgeId(sourceDirectedEdge); var targetDirectedId = new DirectedEdgeId(targetDirectedEdge); var bidirectionalSearch = new Itinero.Algorithms.Contracted.BidirectionalDykstra <T>(contracted.NodeBasedGraph, null, weightHandler, new EdgePath <T>[] { new EdgePath <T>(sourceDirectedId.Raw) }, new EdgePath <T>[] { new EdgePath <T>(targetDirectedId.Raw) }); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } var directedEdgePath = Algorithms.Dual.BidirectionalDykstraExtensions.GetDualPath(bidirectionalSearch); // convert directed edge-path to an original vertex path. var enumerator = _db.Network.GetEdgeEnumerator(); vertexPath = new List <uint>(); for (var i = 0; i < directedEdgePath.Count; i++) { var e = new DirectedEdgeId() { Raw = directedEdgePath[i] }; enumerator.MoveToEdge(e.EdgeId); var original = new OriginalEdge(enumerator.From, enumerator.To); if (!e.Forward) { original = original.Reverse(); } if (vertexPath.Count == 0) { vertexPath.Add(original.Vertex1); } vertexPath.Add(original.Vertex2); } } else { throw new Exception("Cannot use vertex-based contracted graph for edge-based calculations."); } // expand vertex path using the regular graph. var source = _db.CreateRouterPointForEdge(sourceDirectedEdge, true); var target = _db.CreateRouterPointForEdge(targetDirectedEdge, false); path = _db.BuildEdgePath(weightHandler, source, target, vertexPath); } else { // use the regular graph. var sourceSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profileInstance.Profile, true), new EdgePath <T>[] { sourcePath }, maxSearch, false); var targetSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profileInstance.Profile, false), new EdgePath <T>[] { targetPath }, maxSearch, true); var bidirectionalSearch = new Algorithms.Default.EdgeBased.BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } path = bidirectionalSearch.GetPath(); } return(new Result <EdgePath <T> >(path)); } catch (Exception ex) { return(new Result <EdgePath <T> >(ex.Message, (m) => ex)); } }
/// <summary> /// Calculates a route between the two locations. /// </summary> /// <returns></returns> public sealed override Result <EdgePath <T> > TryCalculateRaw <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, 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; bool useContracted = false; if (_db.TryGetContracted(profileInstance.Profile, out contracted)) { // contracted calculation. useContracted = true; if (_db.HasComplexRestrictions(profileInstance.Profile) && (!contracted.HasEdgeBasedGraph && !contracted.NodeBasedIsEdgedBased)) { // 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; } } EdgePath <T> path = null; if (source.EdgeId == target.EdgeId) { // check for a path on the same edge. var edgePath = source.EdgePathTo(_db, weightHandler, target); if (edgePath != null) { path = edgePath; } } if (useContracted) { // use the contracted graph. List <uint> vertexPath = null; if (contracted.HasEdgeBasedGraph) { // use edge-based routing. var bidirectionalSearch = new Itinero.Algorithms.Contracted.EdgeBased.BidirectionalDykstra <T>(contracted.EdgeBasedGraph, weightHandler, source.ToEdgePaths(_db, weightHandler, true), target.ToEdgePaths(_db, weightHandler, false), _db.GetGetRestrictions(profileInstance.Profile, null)); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { if (path == null) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } } else { vertexPath = bidirectionalSearch.GetPath(); } } else if (contracted.NodeBasedIsEdgedBased) {// use vertex-based graph for edge-based routing. var sourceDirectedId1 = new DirectedEdgeId(source.EdgeId, true); var sourceDirectedId2 = new DirectedEdgeId(source.EdgeId, false); var targetDirectedId1 = new DirectedEdgeId(target.EdgeId, true); var targetDirectedId2 = new DirectedEdgeId(target.EdgeId, false); var bidirectionalSearch = new Itinero.Algorithms.Contracted.BidirectionalDykstra <T>(contracted.NodeBasedGraph, null, weightHandler, new EdgePath <T>[] { new EdgePath <T>(sourceDirectedId1.Raw), new EdgePath <T>(sourceDirectedId2.Raw) }, new EdgePath <T>[] { new EdgePath <T>(targetDirectedId1.Raw), new EdgePath <T>(targetDirectedId2.Raw) }); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } var directedEdgePath = Algorithms.Dual.BidirectionalDykstraExtensions.GetDualPath(bidirectionalSearch); // convert directed edge-path to an original vertex path. var enumerator = _db.Network.GetEdgeEnumerator(); vertexPath = new List <uint>(); var edge = new List <OriginalEdge>(); for (var i = 0; i < directedEdgePath.Count; i++) { var e = new DirectedEdgeId() { Raw = directedEdgePath[i] }; enumerator.MoveToEdge(e.EdgeId); var original = new OriginalEdge(enumerator.From, enumerator.To); if (!e.Forward) { original = original.Reverse(); } edge.Add(original); if (vertexPath.Count == 0) { vertexPath.Add(original.Vertex1); } vertexPath.Add(original.Vertex2); } vertexPath[0] = Constants.NO_VERTEX; vertexPath[vertexPath.Count - 1] = Constants.NO_VERTEX; } else { // use node-based routing. var bidirectionalSearch = new Itinero.Algorithms.Contracted.BidirectionalDykstra <T>(contracted.NodeBasedGraph, _db.GetRestrictions(profileInstance.Profile), weightHandler, source.ToEdgePaths(_db, weightHandler, true), target.ToEdgePaths(_db, weightHandler, false)); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { if (path == null) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } } else { vertexPath = Algorithms.Contracted.BidirectionalDykstraExtensions.GetPath(bidirectionalSearch); } } // expand vertex path using the regular graph. if (vertexPath != null) { var localPath = _db.BuildEdgePath(weightHandler, source, target, vertexPath); if (path == null || weightHandler.IsSmallerThan(localPath.Weight, path.Weight)) { path = localPath; } } } else { // use the regular graph. EdgePath <T> localPath = null; if (_db.HasComplexRestrictions(profileInstance.Profile)) { var sourceSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profileInstance.Profile, true), source.ToEdgePaths(_db, weightHandler, true), maxSearch, false); var targetSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profileInstance.Profile, false), target.ToEdgePaths(_db, weightHandler, false), maxSearch, true); var bidirectionalSearch = new Algorithms.Default.EdgeBased.BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { if (path == null) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } } else { localPath = bidirectionalSearch.GetPath(); } } else { var sourceSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, _db.GetGetSimpleRestrictions(profileInstance.Profile), weightHandler, source.ToEdgePaths(_db, weightHandler, true), maxSearch, false); var targetSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, _db.GetGetSimpleRestrictions(profileInstance.Profile), weightHandler, target.ToEdgePaths(_db, weightHandler, false), maxSearch, true); var bidirectionalSearch = new BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler); bidirectionalSearch.Run(); if (!bidirectionalSearch.HasSucceeded) { if (path == null) { return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) => { return new RouteNotFoundException(message); })); } } else { localPath = bidirectionalSearch.GetPath(); } } // choose best path. if (localPath != null) { if (path == null || weightHandler.IsSmallerThan(localPath.Weight, path.Weight)) { path = localPath; } } } return(new Result <EdgePath <T> >(path)); } catch (Exception ex) { return(new Result <EdgePath <T> >(ex.Message, (m) => ex)); } }