示例#1
0
 /// <summary>
 /// Calculates all weights between all sources and all targets.
 /// </summary>
 /// <returns></returns>
 public abstract Result <T[][]> TryCalculateWeight <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets,
                                                       ISet <int> invalidSources, ISet <int> invalidTargets, RoutingSettings <T> settings = null) where T : struct;
示例#2
0
 /// <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 abstract Result <EdgePath <T> > TryCalculateRaw <T>(IProfileInstance profile, WeightHandler <T> weightHandler, long sourceDirectedEdge, long targetDirectedEdge,
                                                            RoutingSettings <T> settings = null) where T : struct;
示例#3
0
 /// <summary>
 /// Calculates all routes between all sources and all targets.
 /// </summary>
 /// <returns></returns>
 public abstract Result <EdgePath <T>[][]> TryCalculateRaw <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets,
                                                               RoutingSettings <T> settings = null) where T : struct;
示例#4
0
        /// <summary>
        /// Calculates all routes between all sources and all targets.
        /// </summary>
        /// <returns></returns>
        public sealed override Result <EdgePath <T>[][]> TryCalculateRaw <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 <EdgePath <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;

            if (_db.TryGetContracted(profile, out contracted))
            {
                Logging.Logger.Log("Router", Logging.TraceEventType.Warning,
                                   "Many to many route calculations are not possible yet using contracted algorithms.");
            }

            // 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.
            var 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));
        }
示例#5
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));
        }
示例#6
0
        /// <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>(Profile profile, WeightHandler <T> weightHandler, long sourceDirectedEdge, long targetDirectedEdge,
                                                                          RoutingSettings <T> settings)
        {
            if (!_db.Supports(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(profile.Name, 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(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 (!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(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(profile))
                {
                    var sourceSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler,
                                                                                    _db.GetGetRestrictions(profile, true), new EdgePath <T>[] { sourcePath }, maxSearch, false);
                    var targetSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler,
                                                                                    _db.GetGetRestrictions(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));
        }
示例#7
0
        /// <summary>
        /// Calculates a route between the two locations.
        /// </summary>
        /// <returns></returns>
        public sealed override Result <EdgePath <T> > TryCalculateRaw <T>(Profile profile, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target,
                                                                          RoutingSettings <T> settings)
        {
            if (!_db.Supports(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(profile.Name, out maxSearch))
                {
                    maxSearch = weightHandler.Infinite;
                }
            }

            EdgePath <T> path;
            ContractedDb contracted;

            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 (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(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(profile))
                {
                    var sourceSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler,
                                                                                    _db.GetGetRestrictions(profile, true), source.ToEdgePaths(_db, weightHandler, true), maxSearch, false);
                    var targetSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler,
                                                                                    _db.GetGetRestrictions(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));
        }
示例#8
0
文件: Router.cs 项目: zyhong/routing
        /// <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 && !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 (!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 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);
                            }
                        }
                    }
                    else if (contracted.HasNodeBasedGraph &&
                             contracted.NodeBasedIsEdgedBased)
                    { // use vertex-based graph for edge-based routing.
                        var algorithm = new Itinero.Algorithms.Contracted.Dual.ManyToMany.VertexToVertexAlgorithm <T>(contracted.NodeBasedGraph, weightHandler,
                                                                                                                      Itinero.Algorithms.Contracted.Dual.RouterPointExtensions.ToDualDykstraSources(sources, _db, weightHandler, true),
                                                                                                                      Itinero.Algorithms.Contracted.Dual.RouterPointExtensions.ToDualDykstraSources(targets, _db, weightHandler, false), 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++)
                            {
                                var path = algorithm.GetPath(s, t);
                                if (path != null)
                                {
                                    path = _db.BuildDualEdgePath(weightHandler, sources[s], targets[t], path);
                                }
                                paths[s][t] = path;
                            }
                        }
                    }
                    else
                    { // 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);
                            }
                        }
                    }
                }

                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));
            }
        }
示例#9
0
文件: Router.cs 项目: zyhong/routing
        /// <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));
            }
        }
示例#10
0
文件: Router.cs 项目: zyhong/routing
        /// <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));
            }
        }