/// <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> /// 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)); } }