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