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

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