/// <summary> /// Executes the actual run of the algorithm. /// </summary> protected override void DoRun() { _best = new EdgePath <T> [_targets.Count]; // register the targets and determine one-edge-paths. var sourcePaths = _source.ToEdgePaths(_routerDb, _weightHandler, true); var targetIndexesPerEdge = new Dictionary <uint, LinkedTarget>(); var targetPaths = new IEnumerable <EdgePath <T> > [_targets.Count]; for (var i = 0; i < _targets.Count; i++) { var targets = _targets[i].ToEdgePaths(_routerDb, _weightHandler, false); targetPaths[i] = targets; // determine one-edge-paths. if (_source.EdgeId == _targets[i].EdgeId) { // on same edge. _best[i] = _source.EdgePathTo(_routerDb, _weightHandler, _targets[i]); } // register targets. for (var t = 0; t < targets.Length; t++) { var target = targetIndexesPerEdge.TryGetValueOrDefault(targets[t].Vertex); targetIndexesPerEdge[targets[t].Vertex] = new LinkedTarget() { Target = i, Next = target }; } } // determine the best max search radius. var max = _weightHandler.Zero; for (var s = 0; s < _best.Length; s++) { if (_best[s] == null) { max = _maxSearch; } else { if (_weightHandler.IsLargerThan(_best[s].Weight, max)) { max = _best[s].Weight; } } } // run the search. var dykstra = new Dykstra <T>(_routerDb.Network.GeometricGraph.Graph, _weightHandler, _getRestrictions, sourcePaths, max, false); dykstra.Visit += (path) => { LinkedTarget target; if (targetIndexesPerEdge.TryGetValue(path.Vertex, out target)) { // there is a target for this vertex. while (target != null) { var best = _best[target.Target]; foreach (var targetPath in targetPaths[target.Target]) { if (targetPath.Vertex == path.Vertex) { // there is a path here. var fullPath = path.Append(targetPath, _weightHandler); if (best == null || _weightHandler.IsSmallerThan(fullPath.Weight, best.Weight)) { // not a best path yet, just add this one. best = fullPath; } break; } } // set again. _best[target.Target] = best; // move to next target. target = target.Next; } } return(false); }; dykstra.Run(); this.HasSucceeded = true; }
/// <summary> /// Creates a new instance of search algorithm. /// </summary> public BidirectionalDykstra(Dykstra <T> sourceSearch, Dykstra <T> targetSearch, WeightHandler <T> weightHandler) { _sourceSearch = sourceSearch; _targetSearch = targetSearch; _weightHandler = weightHandler; }
/// <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 (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) { // 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(profileInstance.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(profileInstance.Profile)) { 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(); } 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)); } 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; } } 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) { // 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(profileInstance.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(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) { 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)); } 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)); } }
/// <summary> /// Checks if the given point is connected to the rest of the network. Use this to detect points on routing islands. /// </summary> /// <param name="radiusInMeter">The radius metric, that's always a distance in meters.</param> /// <returns></returns> public sealed override Result <bool> TryCheckConnectivity(IProfileInstance profileInstance, RouterPoint point, float radiusInMeter, bool?forward = null) { try { if (!_db.Supports(profileInstance.Profile)) { return(new Result <bool>("Routing profile is not supported.", (message) => { return new Exception(message); })); } // get the weight handler. var getGetFactor = this.GetDefaultGetFactor(profileInstance); Func <ushort, Factor> getShortestFactor = (p) => { // only keep directional information, get factor to 1 for distance metrics only. var factor = getGetFactor(p); if (factor.Value == 0) { return(new Factor() { Direction = factor.Direction, Value = 0 }); } return(new Factor() { Direction = factor.Direction, Value = 1 }); }; var weightHandler = new DefaultWeightHandler(getShortestFactor); var checkForward = forward == null || forward.Value; var checkBackward = forward == null || !forward.Value; if (checkForward) { // build and run forward dykstra search. var dykstra = new Algorithms.Default.EdgeBased.Dykstra(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profileInstance.Profile, true), point.ToEdgePaths(_db, weightHandler, true), radiusInMeter, false); dykstra.Run(); if (!dykstra.HasSucceeded || !dykstra.MaxReached) { // something went wrong or max not reached. return(new Result <bool>(false)); } } if (checkBackward) { // build and run backward dykstra search. var dykstra = new Algorithms.Default.EdgeBased.Dykstra(_db.Network.GeometricGraph.Graph, weightHandler, _db.GetGetRestrictions(profileInstance.Profile, false), point.ToEdgePaths(_db, weightHandler, false), radiusInMeter, true); dykstra.Run(); if (!dykstra.HasSucceeded || !dykstra.MaxReached) { // something went wrong or max not reached. return(new Result <bool>(false)); } } return(new Result <bool>(true)); } catch (Exception ex) { return(new Result <bool>(ex.Message, (m) => ex)); } }