Beispiel #1
0
        /// <summary>
        /// Calculates the edge path between this router point and one of it's neighbours.
        /// </summary>
        public static EdgePath <T> EdgePathTo <T>(this RouterPoint point, RouterDb db, WeightHandler <T> weightHandler, uint neighbour, bool backward = false)
            where T : struct
        {
            Factor factor;

            var edge = db.Network.GetEdge(point.EdgeId);

            if (edge.From == neighbour)
            {
                var distance = ((float)System.Math.Abs((int)point.Offset) / (float)ushort.MaxValue) * edge.Data.Distance;
                var weight   = weightHandler.Calculate(edge.Data.Profile, distance, out factor);
                if (backward)
                {
                    return(new EdgePath <T>(Constants.NO_VERTEX, weight, edge.IdDirected(), new EdgePath <T>(neighbour)));
                }
                return(new EdgePath <T>(neighbour, weight, edge.IdDirected(), new EdgePath <T>()));
            }
            else if (edge.To == neighbour)
            {
                var distance = (1 - ((float)System.Math.Abs((int)point.Offset) / (float)ushort.MaxValue)) * edge.Data.Distance;
                var weight   = weightHandler.Calculate(edge.Data.Profile, distance, out factor);
                if (backward)
                {
                    return(new EdgePath <T>(Constants.NO_VERTEX, weight, edge.IdDirected(), new EdgePath <T>(neighbour)));
                }
                return(new EdgePath <T>(neighbour, weight, edge.IdDirected(), new EdgePath <T>()));
            }
            else
            {
                throw new ArgumentException(string.Format("Cannot route to neighbour: {0} is not an edge {1}.", neighbour, point.EdgeId));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Finds the best edge between the two given vertices.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="graph"></param>
        /// <param name="weightHandler"></param>
        /// <param name="vertex1"></param>
        /// <param name="vertex2"></param>
        /// <returns></returns>
        public static long FindBestEdge <T>(this Graph.EdgeEnumerator edgeEnumerator, WeightHandler <T> weightHandler, uint vertex1, uint vertex2, out T bestWeight)
            where T : struct
        {
            edgeEnumerator.MoveTo(vertex1);
            bestWeight = weightHandler.Infinite;
            long   bestEdge = Constants.NO_EDGE;
            Factor factor;

            while (edgeEnumerator.MoveNext())
            {
                if (edgeEnumerator.To == vertex2)
                {
                    float  distance;
                    ushort edgeProfile;
                    EdgeDataSerializer.Deserialize(edgeEnumerator.Data0, out distance, out edgeProfile);
                    var weight = weightHandler.Calculate(edgeProfile, distance, out factor);

                    if (factor.Value > 0 && (factor.Direction == 0 ||
                                             ((factor.Direction == 1) && !edgeEnumerator.DataInverted) ||
                                             ((factor.Direction == 2) && edgeEnumerator.DataInverted)))
                    { // it's ok; the edge can be traversed by the given vehicle.
                        if (weightHandler.IsSmallerThan(weight, bestWeight))
                        {
                            bestWeight = weight;
                            bestEdge   = edgeEnumerator.IdDirected();
                        }
                    }
                }
            }
            if (bestEdge == Constants.NO_EDGE)
            {
                edgeEnumerator.Reset();
                while (edgeEnumerator.MoveNext())
                {
                    if (edgeEnumerator.To == vertex2)
                    {
                        float  distance;
                        ushort edgeProfile;
                        EdgeDataSerializer.Deserialize(edgeEnumerator.Data0, out distance, out edgeProfile);
                        var weight = weightHandler.Calculate(edgeProfile, distance, out factor);

                        //if (factor.Value > 0 && (factor.Direction == 0 ||
                        //    ((factor.Direction == 1) && !edgeEnumerator.DataInverted) ||
                        //    ((factor.Direction == 2) && edgeEnumerator.DataInverted)))
                        //{ // it's ok; the edge can be traversed by the given vehicle.
                        if (weightHandler.IsSmallerThan(weight, bestWeight))
                        {
                            bestWeight = weight;
                            bestEdge   = edgeEnumerator.IdDirected();
                        }
                        //}
                    }
                }
            }
            return(bestEdge);
        }
Beispiel #3
0
        /// <summary>
        /// Calculates the edge path between this router point and the given router point.
        /// </summary>
        public static EdgePath <T> EdgePathTo <T>(this RouterPoint point, RouterDb db, WeightHandler <T> weightHandler, RouterPoint target)
            where T : struct
        {
            if (point.EdgeId != target.EdgeId)
            {
                throw new ArgumentException("Target point must be part of the same edge.");
            }
            if (point.Offset == target.Offset)
            { // path is possible but it has a weight of 0.
                return(new EdgePath <T>(point.VertexId(db)));
            }
            var forward  = point.Offset < target.Offset;
            var edge     = db.Network.GetEdge(point.EdgeId);
            var distance = ((float)System.Math.Abs((int)point.Offset - (int)target.Offset) / (float)ushort.MaxValue) *
                           edge.Data.Distance;
            Factor factor;
            var    weight = weightHandler.Calculate(edge.Data.Profile, distance, out factor);

            if (factor.Value <= 0)
            { // not possible to travel here.
                return(null);
            }
            if (factor.Direction == 0 ||
                (forward && factor.Direction == 1) ||
                (!forward && factor.Direction == 2))
            { // ok, directions match.
                if (forward)
                {
                    return(new EdgePath <T>(target.VertexId(db), weight, point.EdgeId, new EdgePath <T>(point.VertexId(db))));
                }
                return(new EdgePath <T>(target.VertexId(db), weight, -point.EdgeId, new EdgePath <T>(point.VertexId(db))));
            }
            return(null);
        }
Beispiel #4
0
        /// <summary>
        /// Executes the actual run.
        /// </summary>
        protected override void DoRun()
        {
            float  distance;
            ushort edgeProfile;
            bool?  direction = null;

            var factors        = new Dictionary <ushort, Factor>();
            var edgeEnumerator = _source.GetEdgeEnumerator();

            for (uint vertex = 0; vertex < _source.VertexCount; vertex++)
            {
                edgeEnumerator.MoveTo(vertex);
                edgeEnumerator.Reset();
                while (edgeEnumerator.MoveNext())
                {
                    EdgeDataSerializer.Deserialize(edgeEnumerator.Data0,
                                                   out distance, out edgeProfile);
                    Factor factor;
                    var    weight = _weightHandler.Calculate(edgeProfile, distance, out factor);

                    if (factor.Value != 0)
                    {
                        direction = null;
                        if (factor.Direction == 1)
                        {
                            direction = true;
                            if (edgeEnumerator.DataInverted)
                            {
                                direction = false;
                            }
                        }
                        else if (factor.Direction == 2)
                        {
                            direction = false;
                            if (edgeEnumerator.DataInverted)
                            {
                                direction = true;
                            }
                        }

                        _weightHandler.AddEdge(_target, edgeEnumerator.From, edgeEnumerator.To, direction, weight);
                    }
                }
            }

            this.HasSucceeded = true;
        }
        /// <summary>
        /// Converts the router point to paths leading to the closest 2 vertices, always returning paths, event if length zero.
        /// </summary>
        internal static EdgePath <T>[] ToEdgePathsComplete <T>(this RouterPoint point, RouterDb routerDb, WeightHandler <T> weightHandler, bool asSource)
            where T : struct
        {
            var graph = routerDb.Network.GeometricGraph;
            var edge  = graph.GetEdge(point.EdgeId);

            EdgeDataSerializer.Deserialize(edge.Data[0], out var distance, out var profileId);
            var edgeWeight = weightHandler.Calculate(profileId, distance, out var factor);

            var offset = point.Offset / (float)ushort.MaxValue;

            if (factor.Direction == 0)
            { // bidirectional.
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>()),
                    new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                });
            }
            else if (factor.Direction == 1)
            { // edge is forward oneway.
                if (asSource)
                {
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
            else
            { // edge is backward oneway.
                if (!asSource)
                {
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
        }
Beispiel #6
0
        /// <summary>
        /// Generates an edge path for the given edge.
        /// </summary>
        public static EdgePath <T> GetPathForEdge <T>(this RouterDb routerDb, WeightHandler <T> weightHandler, RoutingEdge edge, bool edgeForward, bool asSource)
            where T : struct
        {
            var weight = weightHandler.Calculate(edge.Data.Profile, edge.Data.Distance);

            if (asSource)
            {
                if (edgeForward)
                {
                    return(new EdgePath <T>(edge.To, weight, edge.IdDirected(), new EdgePath <T>(edge.From)));
                }
                return(new EdgePath <T>(edge.From, weight, -edge.IdDirected(), new EdgePath <T>(edge.To)));
            }
            else
            {
                if (edgeForward)
                {
                    return(new EdgePath <T>(edge.From, weight, -edge.IdDirected(), new EdgePath <T>(edge.To)));
                }
                return(new EdgePath <T>(edge.To, weight, edge.IdDirected(), new EdgePath <T>(edge.From)));
            }
        }
Beispiel #7
0
        public override Result <T[][]> TryCalculateWeight <T>(IProfileInstance profile, WeightHandler <T> weightHandler,
                                                              RouterPoint[] sources, RouterPoint[] targets, ISet <int> invalidSources, ISet <int> invalidTargets, RoutingSettings <T> settings)
        {
            var weights = new T[sources.Length][];

            for (var s = 0; s < sources.Length; s++)
            {
                weights[s] = new T[targets.Length];
                for (var t = 0; t < sources.Length; t++)
                {
                    weights[s][t] = weightHandler.Calculate(0, Coordinate.DistanceEstimateInMeter(
                                                                new Coordinate(sources[s].Latitude, sources[s].Longitude),
                                                                new Coordinate(targets[t].Latitude, targets[t].Longitude)));
                }
            }

            foreach (var invalid in _invalidSet)
            {
                invalidSources.Add(invalid);
                invalidTargets.Add(invalid);
            }

            return(new Result <T[][]>(weights));
        }
Beispiel #8
0
        /// <summary>
        /// Converts the router point to vertex and weights with vertex id being the directed edge id. This results in one dykstra source of this routerpoint.
        /// </summary>
        public static DykstraSource <T> ToDualDykstraSource <T>(this RouterPoint point, RouterDb routerDb, WeightHandler <T> weightHandler, bool asSource)
            where T : struct
        {
            var graph = routerDb.Network.GeometricGraph;
            var edge  = graph.GetEdge(point.EdgeId);

            float  distance;
            ushort profileId;

            EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out profileId);
            Factor factor;
            var    edgeWeight = weightHandler.Calculate(profileId, distance, out factor);

            var offset = point.Offset / (float)ushort.MaxValue;

            if (factor.Direction == 0)
            { // bidirectional.
                return(new DykstraSource <T>
                {
                    Vertex1 = (new DirectedEdgeId(point.EdgeId, true)).Raw,
                    Weight1 = weightHandler.Calculate(profileId, distance * offset),
                    Vertex2 = (new DirectedEdgeId(point.EdgeId, false)).Raw,
                    Weight2 = weightHandler.Calculate(profileId, distance * (1 - offset))
                });
            }
            else if (factor.Direction == 1)
            { // edge is forward oneway
                if (asSource)
                {
                    return(new DykstraSource <T>
                    {
                        Vertex1 = (new DirectedEdgeId(point.EdgeId, true)).Raw,
                        Weight1 = weightHandler.Calculate(profileId, distance * offset),
                        Vertex2 = Constants.NO_VERTEX,
                        Weight2 = weightHandler.Infinite
                    });
                }
                return(new DykstraSource <T>
                {
                    Vertex1 = Constants.NO_VERTEX,
                    Weight1 = weightHandler.Infinite,
                    Vertex2 = (new DirectedEdgeId(point.EdgeId, false)).Raw,
                    Weight2 = weightHandler.Calculate(profileId, distance * (1 - offset))
                });
            }
            else
            { // edge is backward oneway.
                if (asSource)
                {
                    return(new DykstraSource <T>
                    {
                        Vertex1 = Constants.NO_VERTEX,
                        Weight1 = weightHandler.Infinite,
                        Vertex2 = (new DirectedEdgeId(point.EdgeId, false)).Raw,
                        Weight2 = weightHandler.Calculate(profileId, distance * (1 - offset))
                    });
                }
                return(new DykstraSource <T>
                {
                    Vertex1 = (new DirectedEdgeId(point.EdgeId, true)).Raw,
                    Weight1 = weightHandler.Calculate(profileId, distance * offset),
                    Vertex2 = Constants.NO_VERTEX,
                    Weight2 = weightHandler.Infinite
                });
            }
        }
Beispiel #9
0
        /// <summary>
        /// Converts the router point to paths leading to the closest 2 vertices.
        /// </summary>
        public static EdgePath <T>[] ToEdgePaths <T>(this RouterPoint point, RouterDb routerDb, WeightHandler <T> weightHandler, bool asSource)
            where T : struct
        {
            var graph = routerDb.Network.GeometricGraph;
            var edge  = graph.GetEdge(point.EdgeId);

            float  distance;
            ushort profileId;

            EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out profileId);
            Factor factor;
            var    edgeWeight = weightHandler.Calculate(profileId, distance, out factor);

            var offset = point.Offset / (float)ushort.MaxValue;

            if (factor.Direction == 0)
            {     // bidirectional.
                if (offset == 0)
                { // the first part is just the first vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.From),
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>(edge.From))
                    });
                }
                else if (offset == 1)
                { // the second path it just the second vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>(edge.To)),
                        new EdgePath <T>(edge.To)
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>()),
                    new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                });
            }
            else if (factor.Direction == 1)
            { // edge is forward oneway.
                if (asSource)
                {
                    if (offset == 1)
                    { // just return the to-vertex.
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.To)
                        });
                    }
                    if (offset == 0)
                    { // return both, we are at the from-vertex.
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.From),
                            new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>(edge.From))
                        });
                    }
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                    });
                }
                if (offset == 0)
                { // just return the from vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.From)
                    });
                }
                if (offset == 1)
                { // return both, we are at the to-vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To),
                        new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>(edge.To))
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
            else
            { // edge is backward oneway.
                if (!asSource)
                {
                    if (offset == 1)
                    { // just return the to-vertex.
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.To)
                        });
                    }
                    if (offset == 0)
                    { // return both, we are at the from-vertex.
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.From),
                            new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>(edge.From))
                        });
                    }
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                    });
                }
                if (offset == 0)
                { // just return the from-vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.From)
                    });
                }
                if (offset == 1)
                { // return both, we are at the to-vertex.
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To),
                        new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>(edge.To))
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
        }
Beispiel #10
0
        /// <summary>
        /// Converts the router point to paths leading to the closest 2 vertices.
        /// </summary>
        public static EdgePath <T>[] ToEdgePaths <T>(this RouterPoint point, RouterDb routerDb, WeightHandler <T> weightHandler, bool asSource, bool?forward)
            where T : struct
        {
            if (forward == null)
            { // don't-care direction, use default implementation.
                return(point.ToEdgePaths(routerDb, weightHandler, asSource));
            }

            var graph = routerDb.Network.GeometricGraph;
            var edge  = graph.GetEdge(point.EdgeId);

            float  distance;
            ushort profileId;

            EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out profileId);
            Factor factor;
            var    edgeWeight = weightHandler.Calculate(profileId, distance, out factor);

            var offset = point.Offset / (float)ushort.MaxValue;

            if (factor.Direction == 0)
            { // bidirectional.
                if (forward.Value)
                {
                    return(new EdgePath <T>[] {
                        new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                    });
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
            else if (factor.Direction == 1)
            { // edge is forward oneway.
                if (asSource)
                {
                    if (forward.Value)
                    {
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                        });
                    }
                    return(new EdgePath <T> [0]);
                }
                if (forward.Value)
                {
                    return(new EdgePath <T> [0]);
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
            else
            { // edge is backward oneway.
                if (!asSource)
                {
                    if (forward.Value)
                    {
                        return(new EdgePath <T>[] {
                            new EdgePath <T>(edge.To, weightHandler.Calculate(profileId, distance * (1 - offset)), edge.IdDirected(), new EdgePath <T>())
                        });
                    }
                    return(new EdgePath <T> [0]);
                }
                if (forward.Value)
                {
                    return(new EdgePath <T> [0]);
                }
                return(new EdgePath <T>[] {
                    new EdgePath <T>(edge.From, weightHandler.Calculate(profileId, distance * offset), -edge.IdDirected(), new EdgePath <T>())
                });
            }
        }