Exemplo n.º 1
0
        /// <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;
        }
Exemplo n.º 2
0
        /// <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));
            }
        }