| | 1 | | using System; |
| | 2 | | using Itinero.Network; |
| | 3 | | using Itinero.Routes.Paths; |
| | 4 | | using Itinero.Routing.Costs; |
| | 5 | | using Itinero.Routing.Flavours.Dijkstra.Bidirectional; |
| | 6 | | using Itinero.Snapping; |
| | 7 | |
|
| | 8 | | namespace Itinero.Routing.Flavours.Dijkstra; |
| | 9 | |
|
| | 10 | | /// <summary> |
| | 11 | | /// Extensions related to snap points. |
| | 12 | | /// </summary> |
| | 13 | | public static class SnapPointExtensions |
| | 14 | | { |
| | 15 | | /// <summary> |
| | 16 | | /// Returns a factor in the range [0, 1] representing the position on the edge. |
| | 17 | | /// </summary> |
| | 18 | | /// <param name="snapPoint">The snap point.</param> |
| | 19 | | /// <returns>The factor.</returns> |
| | 20 | | public static double OffsetFactor(this SnapPoint snapPoint) |
| 147 | 21 | | { |
| 147 | 22 | | return snapPoint.Offset / (double)ushort.MaxValue; |
| 147 | 23 | | } |
| | 24 | |
|
| | 25 | | /// <summary> |
| | 26 | | /// Calculates a single edge path using the given cost function if the two snap points are on the same edge. |
| | 27 | | /// </summary> |
| | 28 | | /// <param name="routingNetwork"></param> |
| | 29 | | /// <param name="origin"></param> |
| | 30 | | /// <param name="destination"></param> |
| | 31 | | /// <param name="costFunction"></param> |
| | 32 | | /// <param name="path"></param> |
| | 33 | | /// <param name="cost"></param> |
| | 34 | | /// <returns></returns> |
| | 35 | | /// <exception cref="Exception"></exception> |
| | 36 | | public static bool TrySingleHop(this RoutingNetwork routingNetwork, |
| | 37 | | SnapPoint origin, SnapPoint destination, ICostFunction costFunction, |
| | 38 | | out Path path, out double cost) |
| 15 | 39 | | { |
| 15 | 40 | | path = null; |
| 15 | 41 | | cost = double.MaxValue; |
| 18 | 42 | | if (origin.EdgeId != destination.EdgeId) return false; |
| | 43 | |
|
| 12 | 44 | | var enumerator = new CostEdgeEnumerator(routingNetwork.GetEdgeEnumerator(), costFunction); |
| 12 | 45 | | if (!enumerator.MoveTo(origin.EdgeId, true)) throw new Exception(); |
| 12 | 46 | | var tailToHeadCost = enumerator.GetCost(true); |
| 12 | 47 | | var headToTailCost = enumerator.GetCost(false); |
| 12 | 48 | | if (headToTailCost.cost <= 0 && tailToHeadCost.cost <= 0) return false; |
| | 49 | |
|
| 12 | 50 | | if (origin.Offset == destination.Offset) |
| 1 | 51 | | { |
| 1 | 52 | | var tailToHead = tailToHeadCost.cost > 0; |
| 1 | 53 | | path = new Path(routingNetwork); |
| 1 | 54 | | path.Append(origin.EdgeId, tailToHead); |
| 1 | 55 | | path.Offset1 = origin.Offset; |
| 1 | 56 | | path.Offset2 = destination.Offset; |
| 1 | 57 | | cost = 0; |
| 1 | 58 | | } |
| 11 | 59 | | else if (origin.Offset < destination.Offset) |
| 6 | 60 | | { |
| 6 | 61 | | var tailToHead = tailToHeadCost.cost > 0; |
| 7 | 62 | | if (!tailToHead) return false; |
| | 63 | |
|
| 5 | 64 | | path = new Path(routingNetwork); |
| 5 | 65 | | path.Append(origin.EdgeId, true); |
| 5 | 66 | | path.Offset1 = origin.Offset; |
| 5 | 67 | | path.Offset2 = destination.Offset; |
| | 68 | |
|
| 5 | 69 | | cost = (destination.OffsetFactor() - origin.OffsetFactor()) * tailToHeadCost.cost; |
| 5 | 70 | | } |
| | 71 | | else |
| 5 | 72 | | { |
| 5 | 73 | | var headToTail = headToTailCost.cost > 0; |
| 6 | 74 | | if (!headToTail) return false; |
| | 75 | |
|
| 4 | 76 | | path = new Path(routingNetwork); |
| 4 | 77 | | path.Append(origin.EdgeId, false); |
| 4 | 78 | | path.Offset1 = (ushort)(ushort.MaxValue - origin.Offset); |
| 4 | 79 | | path.Offset2 = (ushort)(ushort.MaxValue - destination.Offset); |
| | 80 | |
|
| 4 | 81 | | cost = (origin.OffsetFactor() - destination.OffsetFactor()) * headToTailCost.cost; |
| 4 | 82 | | } |
| | 83 | |
|
| 10 | 84 | | return true; |
| 15 | 85 | | } |
| | 86 | | } |