/// <summary> /// Called when a vertex was reached during a forward search. /// </summary> /// <returns></returns> private bool ReachedVertexForward(uint vertex, T weight) { // check backward search for the same vertex. EdgePath <T> backwardVisit; if (_targetSearch.TryGetVisit(vertex, out backwardVisit)) { // there is a status for this vertex in the source search. weight = _weightHandler.Add(weight, backwardVisit.Weight); if (_weightHandler.IsSmallerThan(weight, _bestWeight)) { // this vertex is a better match. _bestWeight = weight; _bestVertex = vertex; this.HasSucceeded = true; } } return(false); }
/// <summary> /// Executes the actual run of the algorithm. /// </summary> protected override void DoRun(CancellationToken cancellationToken) { _best = new EdgePath <T> [_targets.Count]; // register the targets and determine one-edge-paths. var sourcePaths = _source.ToEdgePaths(_routerDb, _weightHandler, true); var targetIndexesPerVertex = 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 = targetIndexesPerVertex.TryGetValueOrDefault(targets[t].Vertex); targetIndexesPerVertex[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, null, _weightHandler, sourcePaths, max, false); dykstra.WasFound += (vertex, weight) => { LinkedTarget target; if (targetIndexesPerVertex.TryGetValue(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]) { EdgePath <T> path; dykstra.TryGetVisit(vertex, out path); if (targetPath.Vertex == vertex) { // there is a path here. var total = _weightHandler.Add(targetPath.Weight, weight); if (best == null || _weightHandler.IsSmallerThan(total, best.Weight)) { // not a best path yet, just add this one. if (_targets[target.Target].IsVertex(_routerDb, path.Vertex)) { // target is the exact vertex. best = path; } else { // target is not the exact vertex. best = new EdgePath <T>(_targets[target.Target].VertexId(_routerDb), total, path); } } break; } } // set again. _best[target.Target] = best; // move to next target. target = target.Next; } } return(false); }; dykstra.Run(cancellationToken); this.HasSucceeded = true; }