/// <summary> /// Expands an island starting the given vertex. /// </summary> private uint Expand(uint vertex, ushort island) { var min = uint.MaxValue; _enumerator.MoveTo(vertex); while (_enumerator.MoveNext()) { var neighbour = _enumerator.To; if (_vertexFlags.Contains(neighbour)) { continue; } float distance; ushort edgeProfile; EdgeDataSerializer.Deserialize(_enumerator.Data0, out distance, out edgeProfile); if (!_canTraverse.Contains(edgeProfile)) { continue; } _islands[neighbour] = island; // set the island. if (neighbour < min) { min = neighbour; } } return(min); }
public void TestOneHop() { var graph = new Graph(1); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); var edge1 = graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(100, 1)); var edge2 = graph.AddEdge(1, 2, EdgeDataSerializer.Serialize(100, 1)); var dykstra = new DirectedDykstra <float>(graph, new DefaultWeightHandler((profile) => new Itinero.Profiles.Factor() { Direction = 0, Value = 1 }), new Itinero.Algorithms.Restrictions.RestrictionCollection((c, v) => false), new DirectedEdgeId(edge1, true), float.MaxValue, false); dykstra.WasFound = (p, e, w) => { if (e.EdgeId == edge1) { Assert.AreEqual(true, e.Forward); Assert.AreEqual(0, w); } else if (e.EdgeId == edge2) { Assert.AreEqual(true, e.Forward); Assert.AreEqual(100, w); } return(false); }; dykstra.Run(); Assert.IsTrue(dykstra.HasRun); Assert.IsTrue(dykstra.HasSucceeded); }
/// <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(); } } } } return(bestEdge); }
public Func <GeometricEdge, bool> GetIsAcceptable(bool verifyCanStopOn, params Profile[] profiles) { if (!this.ContainsAll(profiles)) { throw new ArgumentException("Not all given profiles are supported."); } ProfileFactorCache.CachedFactor[][] cachedFactors = new ProfileFactorCache.CachedFactor[profiles.Length][]; for (int index = 0; index < profiles.Length; ++index) { cachedFactors[index] = this._edgeProfileFactors[profiles[index].Name]; } return((Func <GeometricEdge, bool>)(edge => { float distance; ushort profile; EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out profile); for (int index = 0; index < profiles.Length; ++index) { ProfileFactorCache.CachedFactor cachedFactor = cachedFactors[index][(int)profile]; if (verifyCanStopOn && (int)cachedFactor.Type > 4 || (double)cachedFactor.Value <= 0.0) { return false; } } return true; })); }
public void TestSerialize() { var edgeData = new EdgeData() { Distance = 100.1f, Profile = 12 }; var data = EdgeDataSerializer.Serialize(edgeData); Assert.IsNotNull(data); Assert.AreEqual(1, data.Length); Assert.AreEqual((uint)16384 * (uint)(edgeData.Distance * 10) + (uint)edgeData.Profile, data[0]); edgeData = new EdgeData() { Distance = 0f, Profile = 12 }; data = EdgeDataSerializer.Serialize(edgeData); Assert.IsNotNull(data); Assert.AreEqual(1, data.Length); Assert.AreEqual((uint)16384 * (uint)(edgeData.Distance * 10) + (uint)edgeData.Profile, data[0]); edgeData = new EdgeData() { Distance = EdgeDataSerializer.MAX_DISTANCE, Profile = EdgeDataSerializer.MAX_PROFILE_COUNT - 1 }; data = EdgeDataSerializer.Serialize(edgeData); Assert.IsNotNull(data); Assert.AreEqual(1, data.Length); Assert.AreEqual((uint)16384 * (uint)(edgeData.Distance * 10) + (uint)edgeData.Profile, data[0]); edgeData = new EdgeData() { Distance = EdgeDataSerializer.MAX_DISTANCE + 0.1f, Profile = EdgeDataSerializer.MAX_PROFILE_COUNT - 1 }; Assert.Catch <ArgumentOutOfRangeException>(() => { EdgeDataSerializer.Serialize(edgeData); }); edgeData = new EdgeData() { Distance = EdgeDataSerializer.MAX_DISTANCE, Profile = EdgeDataSerializer.MAX_PROFILE_COUNT }; Assert.Catch <ArgumentOutOfRangeException>(() => { EdgeDataSerializer.Serialize(edgeData); }); }
public void TestOneEdgeAugmented() { // build graph. var graph = new Itinero.Graphs.Graph(EdgeDataSerializer.Size); graph.AddVertex(0); graph.AddVertex(1); graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })); // build speed profile function. var speed = 100f / 3.6f; Func <ushort, FactorAndSpeed> getFactor = (x) => { return(new FactorAndSpeed() { Direction = 0, SpeedFactor = 1.0f / speed, Value = 1.0f / speed }); }; // convert graph. var directedGraph = new DirectedDynamicGraph(ContractedEdgeDataSerializer.DynamicAugmentedFixedSize); var algorithm = new DirectedGraphBuilder <Weight>(graph, directedGraph, new WeightHandler(getFactor)); algorithm.Run(); // check result. Assert.IsTrue(algorithm.HasRun); Assert.IsTrue(algorithm.HasSucceeded); directedGraph.Compress(); Assert.AreEqual(2, directedGraph.VertexCount); Assert.AreEqual(2, directedGraph.EdgeCount); // verify all edges. var edges = directedGraph.GetEdgeEnumerator(0); Assert.AreEqual(1, edges.Count()); var data = ContractedEdgeDataSerializer.SerializeDynamicAugmented(100 * getFactor(1).Value, null, 100, 100 * getFactor(1).Value); Assert.AreEqual(data[0], edges.First().Data[0]); Assert.AreEqual(data[1], edges.First().Data[1]); Assert.AreEqual(data[2], edges.First().Data[2]); Assert.AreEqual(1, edges.First().Neighbour); edges = directedGraph.GetEdgeEnumerator(1); Assert.AreEqual(1, edges.Count()); data = ContractedEdgeDataSerializer.SerializeDynamicAugmented(100 * getFactor(1).Value, null, 100, 100 * getFactor(1).Value); Assert.AreEqual(data[0], edges.First().Data[0]); Assert.AreEqual(data[1], edges.First().Data[1]); Assert.AreEqual(data[2], edges.First().Data[2]); Assert.AreEqual(0, edges.First().Neighbour); }
public void TestOneEdge() { // build graph. var graph = new Itinero.Graphs.Graph(EdgeDataSerializer.Size); graph.AddVertex(0); graph.AddVertex(1); graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })); // build speed profile function. var speed = 100f / 3.6f; Func <ushort, Factor> getFactor = (x) => { return(new Factor() { Direction = 0, Value = 1.0f / speed }); }; // convert graph. var directedGraph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size, ContractedEdgeDataSerializer.MetaSize); var algorithm = new DirectedGraphBuilder(graph, directedGraph, getFactor); algorithm.Run(); // check result. Assert.IsTrue(algorithm.HasRun); Assert.IsTrue(algorithm.HasSucceeded); directedGraph.Compress(); Assert.AreEqual(2, directedGraph.VertexCount); Assert.AreEqual(2, directedGraph.EdgeCount); // verify all edges. var edges = directedGraph.GetEdgeEnumerator(0); Assert.AreEqual(1, edges.Count); var data = ContractedEdgeDataSerializer.Serialize(100 * getFactor(1).Value, null); Assert.AreEqual(data, edges.First().Data[0]); Assert.AreEqual(Constants.NO_VERTEX, edges.First().MetaData[0]); Assert.AreEqual(1, edges.First().Neighbour); edges = directedGraph.GetEdgeEnumerator(1); Assert.AreEqual(1, edges.Count); data = ContractedEdgeDataSerializer.Serialize(100 * getFactor(1).Value, null); Assert.AreEqual(data, edges.First().Data[0]); Assert.AreEqual(Constants.NO_VERTEX, edges.First().MetaData[0]); Assert.AreEqual(0, edges.First().Neighbour); }
public RoutingEdge GetEdge(uint edgeId) { GeometricEdge edge = this._graph.GetEdge(edgeId); OsmSharp.Routing.Data.EdgeData edgeData = EdgeDataSerializer.Deserialize(edge.Data); OsmSharp.Routing.Network.Data.EdgeData data = new OsmSharp.Routing.Network.Data.EdgeData() { MetaId = this._edgeData[(long)edgeId], Distance = edgeData.Distance, Profile = edgeData.Profile }; return(new RoutingEdge(edge.Id, edge.From, edge.To, data, edge.DataInverted, edge.Shape)); }
public void TestLoopRestricted() { var graph = new Graph(1); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); graph.AddVertex(3); graph.AddVertex(4); graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(100, 1)); graph.AddEdge(1, 4, EdgeDataSerializer.Serialize(100, 1)); graph.AddEdge(1, 2, EdgeDataSerializer.Serialize(100, 1)); graph.AddEdge(2, 3, EdgeDataSerializer.Serialize(100, 1)); graph.AddEdge(3, 1, EdgeDataSerializer.Serialize(100, 1)); var dykstra = new Dykstra(graph, (profile) => new Itinero.Profiles.Factor() { Direction = 0, Value = 1 }, (vertex) => { if (vertex == 0) { return(new uint[][] { new uint[] { 0, 1, 4 } }); } return(null); }, new EdgePath <float>[] { new EdgePath <float>(1, 50, 1, new EdgePath <float>()), new EdgePath <float>(0, 50, -1, new EdgePath <float>()) }, float.MaxValue, false); dykstra.Run(); Assert.IsTrue(dykstra.HasRun); Assert.IsTrue(dykstra.HasSucceeded); EdgePath <float> visit; Assert.IsTrue(dykstra.TryGetVisit(-1, out visit) && visit.Weight == 50); Assert.IsTrue(dykstra.TryGetVisit(1, out visit) && visit.Weight == 50); Assert.IsFalse(dykstra.TryGetVisit(-2, out visit)); Assert.IsTrue(dykstra.TryGetVisit(2, out visit) && visit.Weight == 450); Assert.IsTrue(dykstra.TryGetVisit(-3, out visit) && visit.Weight == 350); Assert.IsTrue(dykstra.TryGetVisit(3, out visit) && visit.Weight == 150); Assert.IsTrue(dykstra.TryGetVisit(-4, out visit) && visit.Weight == 250); Assert.IsTrue(dykstra.TryGetVisit(4, out visit) && visit.Weight == 250); Assert.IsTrue(dykstra.TryGetVisit(-5, out visit) && visit.Weight == 150); Assert.IsTrue(dykstra.TryGetVisit(4, out visit) && visit.Weight == 250); }
public void TestTwoHopRestricted() { var graph = new Graph(1); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); graph.AddVertex(3); graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(100, 1)); graph.AddEdge(1, 2, EdgeDataSerializer.Serialize(100, 1)); graph.AddEdge(2, 3, EdgeDataSerializer.Serialize(100, 1)); var dykstra = new Dykstra(graph, (profile) => new Itinero.Profiles.Factor() { Direction = 0, Value = 1 }, (vertex) => { if (vertex == 1) { return(new uint[][] { new uint[] { 1, 2, 3 } }); } return(null); }, new EdgePath <float>[] { new EdgePath <float>(0, 50, 1, new EdgePath <float>()), new EdgePath <float>(1, 50, -1, new EdgePath <float>()) }, float.MaxValue, new List <uint>(), false); dykstra.Run(); Assert.IsTrue(dykstra.HasRun); Assert.IsTrue(dykstra.HasSucceeded); EdgePath <float> visit; Assert.IsTrue(dykstra.TryGetVisit(-1, out visit)); Assert.AreEqual(-1, visit.Edge); Assert.AreEqual(50, visit.Weight); Assert.IsTrue(dykstra.TryGetVisit(1, out visit)); Assert.AreEqual(1, visit.Edge); Assert.AreEqual(50, visit.Weight); Assert.IsTrue(dykstra.TryGetVisit(2, out visit)); Assert.AreEqual(2, visit.Edge); Assert.AreEqual(150, visit.Weight); Assert.IsFalse(dykstra.TryGetVisit(-2, out visit)); Assert.IsFalse(dykstra.TryGetVisit(3, out visit)); Assert.IsFalse(dykstra.TryGetVisit(-2, out visit)); }
public uint AddEdge(uint vertex1, uint vertex2, OsmSharp.Routing.Network.Data.EdgeData data, ShapeBase shape) { if ((double)data.Distance > (double)this._maxEdgeDistance) { throw new ArgumentException("data.Distance too big for this network."); } uint edgeId = this._graph.AddEdge(vertex1, vertex2, EdgeDataSerializer.Serialize(data.Distance, data.Profile), shape); if ((long)edgeId >= this._edgeData.Length) { this.IncreaseSizeEdgeData(edgeId); } this._edgeData[(long)edgeId] = data.MetaId; return(edgeId); }
protected override void DoRun() { bool?nullable = new bool?(); Dictionary <ushort, Factor> dictionary = new Dictionary <ushort, Factor>(); Graph.EdgeEnumerator edgeEnumerator = this._source.GetEdgeEnumerator(); for (uint vertex = 0; vertex < this._source.VertexCount; ++vertex) { edgeEnumerator.MoveTo(vertex); edgeEnumerator.Reset(); while (edgeEnumerator.MoveNext()) { float distance; ushort profile; EdgeDataSerializer.Deserialize(edgeEnumerator.Data0, out distance, out profile); Factor factor = Factor.NoFactor; if (!dictionary.TryGetValue(profile, out factor)) { factor = this._getFactor(profile); dictionary[profile] = factor; } if ((double)factor.Value != 0.0) { bool?direction = new bool?(); if ((int)factor.Direction == 1) { direction = new bool?(true); if (edgeEnumerator.DataInverted) { direction = new bool?(false); } } else if ((int)factor.Direction == 2) { direction = new bool?(false); if (edgeEnumerator.DataInverted) { direction = new bool?(true); } } uint data = ContractedEdgeDataSerializer.Serialize(distance * factor.Value, direction); int num = (int)this._target.AddEdge(edgeEnumerator.From, edgeEnumerator.To, data, 4294967294U); } } } this.HasSucceeded = true; }
/// <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; }
public void TestTriangle() { var graph = new Graph(1); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(100, 1)); graph.AddEdge(1, 2, EdgeDataSerializer.Serialize(100, 1)); graph.AddEdge(2, 0, EdgeDataSerializer.Serialize(100, 1)); var dykstra = new Dykstra(graph, (profile) => new Itinero.Profiles.Factor() { Direction = 0, Value = 1 }, null, new EdgePath <float>[] { new EdgePath <float>(0, 50, 1, new EdgePath <float>()), new EdgePath <float>(1, 50, -1, new EdgePath <float>()) }, float.MaxValue, false); dykstra.Run(); Assert.IsTrue(dykstra.HasRun); Assert.IsTrue(dykstra.HasSucceeded); EdgePath <float> visit; Assert.IsTrue(dykstra.TryGetVisit(-1, out visit)); Assert.AreEqual(-1, visit.Edge); Assert.AreEqual(50, visit.Weight); Assert.IsTrue(dykstra.TryGetVisit(1, out visit)); Assert.AreEqual(1, visit.Edge); Assert.AreEqual(50, visit.Weight); Assert.IsTrue(dykstra.TryGetVisit(2, out visit)); Assert.AreEqual(2, visit.Edge); Assert.AreEqual(150, visit.Weight); Assert.IsTrue(dykstra.TryGetVisit(-2, out visit)); Assert.AreEqual(-2, visit.Edge); Assert.AreEqual(250, visit.Weight); Assert.IsTrue(dykstra.TryGetVisit(3, out visit)); Assert.AreEqual(3, visit.Edge); Assert.AreEqual(250, visit.Weight); Assert.IsTrue(dykstra.TryGetVisit(-3, out visit)); Assert.AreEqual(-3, visit.Edge); Assert.AreEqual(150, visit.Weight); }
public void TestTwoEdges() { // build graph. var graph = new Graph(EdgeDataSerializer.Size); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })); graph.AddEdge(1, 2, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })); // build speed profile function. var speed = 100f / 3.6f; Func <ushort, Factor> getFactor = (x) => { return(new Factor() { Direction = 0, Value = 1.0f / speed }); }; // run algorithm. var sourceSearch = new Dykstra(graph, getFactor, null, new EdgePath <float>[] { new EdgePath <float>(0) }, 150 * 1 / speed, false); var targetSearch = new Dykstra(graph, getFactor, null, new EdgePath <float>[] { new EdgePath <float>(2) }, 150 * 1 / speed, true); var algorithm = new BidirectionalDykstra(sourceSearch, targetSearch, getFactor); algorithm.Run(); Assert.IsTrue(algorithm.HasRun); Assert.IsTrue(algorithm.HasSucceeded); Assert.AreEqual(1, algorithm.BestVertex); Assert.AreEqual(new uint[] { 0, 1, 2 }, algorithm.GetPath().ToListAsVertices().ToArray()); }
public void TestOneEdge() { // build graph. var graph = new Graph(EdgeDataSerializer.Size); graph.AddVertex(0); graph.AddVertex(1); graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })); // build speed profile function. var speed = 100f / 3.6f; Func <ushort, Itinero.Profiles.Factor> getFactor = (x) => { return(new Itinero.Profiles.Factor() { Direction = 0, Value = 1.0f / speed }); }; // run algorithm. var algorithm = new Dykstra(graph, getFactor, null, new EdgePath <float>[] { new EdgePath <float>(0) }, float.MaxValue, false); algorithm.Run(); Assert.IsTrue(algorithm.HasRun); Assert.IsTrue(algorithm.HasSucceeded); EdgePath <float> visit; Assert.IsTrue(algorithm.TryGetVisit(0, out visit)); Assert.AreEqual(null, visit.From); Assert.AreEqual(0, visit.Vertex); Assert.AreEqual(0, visit.Weight); Assert.IsTrue(algorithm.TryGetVisit(1, out visit)); Assert.AreEqual(0, visit.From.Vertex); Assert.AreEqual(1, visit.Vertex); Assert.AreEqual(100 / speed, visit.Weight); }
/// <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>()) }); } }
public void TestDeserialize() { var edge = EdgeDataSerializer.Deserialize(new uint[] { 0 }); Assert.AreEqual(0, edge.Distance); Assert.AreEqual(0, edge.Profile); edge = EdgeDataSerializer.Deserialize(new uint[] { 10 }); Assert.AreEqual(0, edge.Distance); Assert.AreEqual(10, edge.Profile); edge = EdgeDataSerializer.Deserialize(new uint[] { EdgeDataSerializer.MAX_PROFILE_COUNT - 1 }); Assert.AreEqual(0, edge.Distance); Assert.AreEqual(EdgeDataSerializer.MAX_PROFILE_COUNT - 1, edge.Profile); edge = EdgeDataSerializer.Deserialize(new uint[] { (uint)16384 * (uint)(EdgeDataSerializer.MAX_DISTANCE * 10) + (uint)(EdgeDataSerializer.MAX_PROFILE_COUNT - 1) }); Assert.AreEqual(EdgeDataSerializer.MAX_DISTANCE, edge.Distance, .1f); Assert.AreEqual(EdgeDataSerializer.MAX_PROFILE_COUNT - 1, edge.Profile); }
protected Func <GeometricEdge, bool> GetIsAcceptable(Profile[] profiles) { if (this.ProfileFactorCache != null && this.ProfileFactorCache.ContainsAll(profiles)) { return(this.ProfileFactorCache.GetIsAcceptable(this.VerifyAllStoppable, profiles)); } return((Func <GeometricEdge, bool>)(edge => { float distance; ushort profile; EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out profile); TagsCollectionBase attributes = this._db.EdgeProfiles.Get((uint)profile); for (int index = 0; index < profiles.Length; ++index) { if ((double)profiles[index].Factor(attributes).Value <= 0.0 || this.VerifyAllStoppable && !profiles[index].CanStopOn(attributes)) { return false; } } return true; })); }
/// <summary> /// Returns the IsAcceptable function to use in the default resolver algorithm. /// </summary> public static Func <GeometricEdge, bool> GetIsAcceptable(this RouterBase router, params Profile[] profiles) { if (router.ProfileFactorAndSpeedCache != null && router.ProfileFactorAndSpeedCache.ContainsAll(profiles)) { // use cached version and don't consult profiles anymore. return(router.ProfileFactorAndSpeedCache.GetIsAcceptable(router.VerifyAllStoppable, profiles)); } else { // use the regular function, and consult profiles continuously. return((edge) => { // check all profiles, they all need to be traversible. // get profile. float distance; ushort edgeProfileId; EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out edgeProfileId); var edgeProfile = router.Db.EdgeProfiles.Get(edgeProfileId); for (var i = 0; i < profiles.Length; i++) { // get factor from profile. if (profiles[i].Factor(edgeProfile).Value <= 0) { // cannot be traversed by this profile. return false; } if (router.VerifyAllStoppable) { // verify stoppable. if (!profiles[i].CanStopOn(edgeProfile)) { // this profile cannot stop on this edge. return false; } } } return true; }); } }
/// <summary> /// Executes one step in the search. /// </summary> public bool Step() { // while the visit list is not empty. _current = null; if (_heap.Count > 0) { // choose the next vertex. _current = _heap.Pop(); while (_current != null && _visits.ContainsKey(_current.Vertex)) { // keep dequeuing. if (_heap.Count == 0) { // nothing more to pop. break; } if (this.Visit != null && this.Visit(_current)) { // edge was found and true was returned, this search should stop. return(false); } _current = _heap.Pop(); } } if (_current != null && !_visits.ContainsKey(_current.Vertex)) { // we visit this one, set visit. _visits[_current.Vertex] = _current; } else { // route is not found, there are no vertices left // or the search went outside of the max bounds. return(false); } if (this.WasFound != null && this.WasFound(_current.Vertex, _current.Weight)) { // vertex was found and true was returned, this search should stop. return(false); } // check for restrictions. var restriction = Constants.NO_VERTEX; if (_getRestriction != null) { restriction = _getRestriction(_current.Vertex); } if (restriction != Constants.NO_VERTEX) { // this vertex is restricted, step is a success but just move // to the next one because this vertex's neighbours are not allowed. return(true); } if (this.Visit != null && this.Visit(_current)) { // edge was found and true was returned, this search should stop. return(false); } // get neighbours and queue them. _edgeEnumerator.MoveTo(_current.Vertex); while (_edgeEnumerator.MoveNext()) { var edge = _edgeEnumerator; var neighbour = edge.To; if (_current.From != null && _current.From.Vertex == neighbour) { // don't go back continue; } if (this.Visit == null) { if (_visits.ContainsKey(neighbour)) { // has already been choosen continue; } } // get the speed from cache or calculate. float distance; ushort edgeProfile; EdgeDataSerializer.Deserialize(edge.Data0, out distance, out edgeProfile); var factor = Factor.NoFactor; var totalWeight = _weightHandler.Add(_current.Weight, edgeProfile, distance, out factor); // check the tags against the interpreter. if (factor.Value > 0 && (factor.Direction == 0 || (!_backward && (factor.Direction == 1) != edge.DataInverted) || (_backward && (factor.Direction == 1) == edge.DataInverted))) { // it's ok; the edge can be traversed by the given vehicle. // calculate neighbors weight. var edgeWeight = (distance * factor.Value); if (_weightHandler.IsSmallerThan(totalWeight, _sourceMax)) { // update the visit list. _heap.Push(new EdgePath <T>(neighbour, totalWeight, edge.IdDirected(), _current), _weightHandler.GetMetric(totalWeight)); } else { // the maxium was reached. this.MaxReached = true; } } } return(true); }
/// <summary> /// Executes the actual algorithm. /// </summary> protected override void DoRun() { float distance; ushort edgeProfile; var enumerator1 = _source.GetEdgeEnumerator(); var enumerator2 = _source.GetEdgeEnumerator(); for (uint v = 0; v < _source.VertexCount; v++) { enumerator1.MoveTo(v); while (enumerator1.MoveNext()) { EdgeDataSerializer.Deserialize(enumerator1.Data0, out distance, out edgeProfile); var accessible1 = false; var weight1 = _weightHandler.CalculateWeightAndDir(edgeProfile, distance, out accessible1); if (enumerator1.DataInverted) { var dir = weight1.Direction; dir.Reverse(); weight1.Direction = dir; } if (!accessible1) { // not accessible. continue; } var direction1 = weight1.Direction; var edge1 = enumerator1.DirectedEdgeId(); // look at the neighbours of this edge. enumerator2.MoveTo(enumerator1.To); _restrictions.Update(enumerator1.To); while (enumerator2.MoveNext()) { var turn = new Turn(new OriginalEdge(v, enumerator1.To), Constants.NO_VERTEX); EdgeDataSerializer.Deserialize(enumerator2.Data0, out distance, out edgeProfile); var accessible2 = false; var weight2 = _weightHandler.CalculateWeightAndDir(edgeProfile, distance, out accessible2); if (enumerator2.DataInverted) { var dir = weight2.Direction; dir.Reverse(); weight2.Direction = dir; } if (!accessible2) { // not accessible. continue; } var direction2 = weight2.Direction; turn.Vertex3 = enumerator2.To; if (turn.IsUTurn) { // is a u-turn, leave this out! continue; } var direction = Dir.Combine(direction1, direction2); if (direction.F && turn.IsRestrictedBy(_restrictions)) { // turn is restricted. direction.F = false; } if (!direction.F) { // there is no possible combination for these two edges. continue; } // ok, we need to add this edge, it's a non-restricted turn, not a u-turn and edges are in correct direction. var edge2 = enumerator2.DirectedEdgeId(); _weightHandler.AddOrUpdateEdge(_target, edge1.Raw, edge2.Raw, Constants.NO_VERTEX, true, weight1.Weight); //direction.Reverse(); _weightHandler.AddOrUpdateEdge(_target, edge2.Raw, edge1.Raw, Constants.NO_VERTEX, false, weight1.Weight); } } } }
public void TestSourceBetween() { // build graph. var graph = new Graph(EdgeDataSerializer.Size); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })); graph.AddEdge(1, 2, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })); graph.AddEdge(0, 2, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })); // build speed profile function. var speed = 100f / 3.6f; Func <ushort, Factor> getFactor = (x) => { return(new Factor() { Direction = 1, Value = 1.0f / speed }); }; // run algorithm. var algorithm = new Dykstra(graph, getFactor, null, new EdgePath <float>[] { new EdgePath <float>(0, 10 / speed, new EdgePath <float>(uint.MaxValue)), new EdgePath <float>(1, 90 / speed, new EdgePath <float>(uint.MaxValue)) }, float.MaxValue, new List <uint>(), false); algorithm.Run(); Assert.IsTrue(algorithm.HasRun); Assert.IsTrue(algorithm.HasSucceeded); EdgePath <float> visit; Assert.IsTrue(algorithm.TryGetVisit(0, out visit)); Assert.IsNotNull(visit.From); Assert.AreEqual(uint.MaxValue, visit.From.Vertex); Assert.AreEqual(0, visit.Vertex); Assert.AreEqual(10 / speed, visit.Weight); Assert.IsTrue(algorithm.TryGetVisit(1, out visit)); Assert.IsNotNull(visit.From); Assert.AreEqual(uint.MaxValue, visit.From.Vertex); Assert.AreEqual(1, visit.Vertex); Assert.AreEqual(90 / speed, visit.Weight); Assert.IsTrue(algorithm.TryGetVisit(2, out visit)); Assert.IsNotNull(visit.From); Assert.AreEqual(0, visit.From.Vertex); Assert.AreEqual(2, visit.Vertex); Assert.AreEqual(110 / speed, visit.Weight); }
/// <summary> /// Returns the IsAcceptable function to use in the default resolver algorithm. /// </summary> public static Func <GeometricEdge, bool> GetIsAcceptable(this RouterBase router, params IProfileInstance[] profiles) { if (router.ProfileFactorAndSpeedCache != null && router.ProfileFactorAndSpeedCache.ContainsAll(profiles)) { // use cached version and don't consult profiles anymore. return(router.ProfileFactorAndSpeedCache.GetIsAcceptable(router.VerifyAllStoppable, profiles)); } else { // use the regular function, and consult profiles continuously. if (router.ProfileFactorAndSpeedCache != null) { // when there is a cache, built it on demand. var profileNames = new StringBuilder(); var profileArray = new Profile[profiles.Length]; for (var i = 0; i < profiles.Length; i++) { if (i > 0) { profileNames.Append(','); } profileNames.Append(profiles[i].Profile.FullName); profileArray[i] = profiles[i].Profile; } Itinero.Logging.Logger.Log("RouterBaseExtensions", TraceEventType.Information, "Profile(s) {0} not cached, building cache.", profileNames.ToInvariantString()); router.ProfileFactorAndSpeedCache.CalculateFor(profileArray); return(router.ProfileFactorAndSpeedCache.GetIsAcceptable(router.VerifyAllStoppable, profiles)); } else { Itinero.Logging.Logger.Log("RouterBaseExtensions", TraceEventType.Warning, "Not all profiles are cached, this could slow down routing significantly, consider building a profile cache."); return((edge) => { // check all profiles, they all need to be traversible. // get profile. float distance; ushort edgeProfileId; EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out edgeProfileId); var edgeProfile = router.Db.EdgeProfiles.Get(edgeProfileId); for (var i = 0; i < profiles.Length; i++) { var factorAndSpeed = profiles[i].Profile.FactorAndSpeed(edgeProfile); // get factor from profile. if (factorAndSpeed.Value <= 0) { // cannot be traversed by this profile. return false; } if (router.VerifyAllStoppable) { // verify stoppable. if (!factorAndSpeed.CanStopOn()) { // this profile cannot stop on this edge. return false; } } if (profiles[i].IsConstrained(factorAndSpeed.Constraints)) { // this edge is constrained, this vehicle cannot travel here. return false; } } return true; }); } } }
public void TestEdgeVisits() { // build graph. var graph = new Graph(EdgeDataSerializer.Size); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); var e01 = graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })) + 1; var e12 = graph.AddEdge(1, 2, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })) + 1; var e02 = graph.AddEdge(0, 2, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })) + 1; // build speed profile function. var speed = 100f / 3.6f; Func <ushort, Factor> getFactor = (x) => { return(new Factor() { Direction = 0, Value = 1.0f / speed }); }; // run algorithm. var reportedEdges = new HashSet <long>(); var algorithm = new Dykstra(graph, getFactor, null, new EdgePath <float>[] { new EdgePath <float>(0) }, float.MaxValue, false); algorithm.Visit += (path) => { if (path.From == null) { return(false); } var v1 = path.From.Vertex; var v2 = path.Vertex; var w1 = path.From.Weight; var w2 = path.Weight; var e = path.Edge; var edge = graph.GetEdge(e); float l; ushort p; Itinero.Data.Edges.EdgeDataSerializer.Deserialize(edge.Data[0], out l, out p); if (v1 == 0 && v2 == 1) { Assert.AreEqual(100, l); Assert.AreEqual(e01, e); Assert.AreEqual(0, w1); Assert.AreEqual(100 / speed, w2); reportedEdges.Add(e01); } else if (v1 == 1 && v2 == 0) { Assert.AreEqual(100, l); Assert.AreEqual(-e01, e); Assert.AreEqual(100 / speed, w1); Assert.AreEqual(200 / speed, w2); reportedEdges.Add(-e01); } else if (v1 == 0 && v2 == 2) { Assert.AreEqual(100, l); Assert.AreEqual(e02, e); Assert.AreEqual(0, w1); Assert.AreEqual(100 / speed, w2); reportedEdges.Add(e02); } else if (v1 == 2 && v2 == 0) { Assert.AreEqual(100, l); Assert.AreEqual(-e02, e); Assert.AreEqual(100 / speed, w1); Assert.AreEqual(200 / speed, w2); reportedEdges.Add(-e02); } else if (v1 == 1 && v2 == 2) { Assert.AreEqual(100, l); Assert.AreEqual(e12, e); Assert.AreEqual(100 / speed, w1); Assert.AreEqual(200 / speed, w2); reportedEdges.Add(e12); } else if (v1 == 2 && v2 == 1) { Assert.AreEqual(100, l); Assert.AreEqual(-e12, e); Assert.AreEqual(100 / speed, w1); Assert.AreEqual(200 / speed, w2); reportedEdges.Add(-e12); } return(false); }; algorithm.Run(); Assert.IsTrue(algorithm.HasRun); Assert.IsTrue(algorithm.HasSucceeded); Assert.IsTrue(reportedEdges.Contains(e01)); Assert.IsTrue(reportedEdges.Contains(e02)); }
/// <summary> /// Executes one step in the search. /// </summary> public bool Step() { // while the visit list is not empty. _current = null; if (_heap.Count > 0) { // choose the next vertex. _current = _heap.Pop(); while (_current != null && _visits.ContainsKey(_current.Edge)) { // keep dequeuing. if (_heap.Count == 0) { // nothing more to pop. break; } _current = _heap.Pop(); } } if (_current != null) { // we visit this one, set visit. if (_current.Edge != Constants.NO_EDGE) { _visits[_current.Edge] = _current; // report on visit. if (this.Visit != null) { if (this.Visit(_current)) { return(true); } } } } else { // route is not found, there are no vertices left // or the search went outside of the max bounds. return(false); } // move to the current edge's target vertex. _edgeEnumerator.MoveTo(_current.Vertex); // get new restrictions at the current vertex. LinkedRestriction restrictions = null; if (_edgeRestrictions.TryGetValue(_current, out restrictions)) { _edgeRestrictions.Remove(_current); } if (_getRestriction != null) { var targetVertexRestriction = _getRestriction(_current.Vertex); if (targetVertexRestriction != null) { foreach (var restriction in targetVertexRestriction) { if (restriction != null && restriction.Length > 0) { if (restriction.Length == 1) { // a simple restriction, restricted vertex, no need to check outgoing edges. return(true); } else { // a complex restriction. restrictions = new LinkedRestriction() { Restriction = restriction, Next = restrictions }; } } } } } while (_edgeEnumerator.MoveNext()) { var edge = _edgeEnumerator; var directedEdgeId = _edgeEnumerator.IdDirected(); var neighbour = edge.To; if (directedEdgeId == -_current.Edge) { // don't go back. continue; } if (_visits.ContainsKey(directedEdgeId)) { // has already been choosen. continue; } // get the speed from cache or calculate. float distance; ushort edgeProfile; EdgeDataSerializer.Deserialize(edge.Data0, out distance, out edgeProfile); var factor = Factor.NoFactor; var edgeWeight = _weightHandler.Calculate(edgeProfile, distance, out factor); // check the tags against the interpreter. if (factor.Value > 0 && (factor.Direction == 0 || (!_backward && (factor.Direction == 1) != edge.DataInverted) || (_backward && (factor.Direction == 1) == edge.DataInverted))) { // it's ok; the edge can be traversed by the given vehicle. // verify restriction(s). var currentRestriction = restrictions; var forbidden = false; LinkedRestriction newRestrictions = null; while (currentRestriction != null) { // check if some restriction prohibits this move or if we need add a new restriction // for the current edge. if (currentRestriction.Restriction[1] == _edgeEnumerator.To) { // ok restrictions applies to this edge and the previous one. if (currentRestriction.Restriction.Length == 2) { // ok this is the last edge in this restriction, prohibit this move. forbidden = true; break; } else { // append this restriction to the restrictions in for the current edge. newRestrictions = new LinkedRestriction() { Restriction = currentRestriction.Restriction.SubArray(1, currentRestriction.Restriction.Length - 1), Next = newRestrictions }; } } currentRestriction = currentRestriction.Next; } if (forbidden) { // move to next neighbour. continue; } // calculate neighbors weight. var totalWeight = _weightHandler.Add(_current.Weight, edgeWeight); if (_weightHandler.IsSmallerThan(totalWeight, _sourceMax)) { // update the visit list. var path = new EdgePath <T>(neighbour, totalWeight, directedEdgeId, _current); if (newRestrictions != null) { _edgeRestrictions[path] = newRestrictions; } _heap.Push(path, _weightHandler.GetMetric(totalWeight)); } else { // the maxium was reached. this.MaxReached = true; } } } return(true); }
public void TestEdgeVisits() { // build graph. var graph = new Graph(EdgeDataSerializer.Size); graph.AddVertex(0); graph.AddVertex(1); graph.AddVertex(2); var e01 = graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })) + 1; var e12 = graph.AddEdge(1, 2, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })) + 1; var e02 = graph.AddEdge(0, 2, EdgeDataSerializer.Serialize(new EdgeData() { Distance = 100, Profile = 1 })) + 1; // build speed profile function. var speed = 100f / 3.6f; Func <ushort, Factor> getFactor = (x) => { return(new Factor() { Direction = 0, Value = 1.0f / speed }); }; // run algorithm. var reportedEdges = new HashSet <long>(); var algorithm = new Dykstra(graph, getFactor, null, new EdgePath <float>[] { new EdgePath <float>(0) }, float.MaxValue, false); algorithm.WasEdgeFound += (v1, v2, w1, w2, e, l) => { if (v1 == 0 && v2 == 1) { Assert.AreEqual(100, l); Assert.AreEqual(e01, e); Assert.AreEqual(0, w1); Assert.AreEqual(100 / speed, w2); reportedEdges.Add(e01); } else if (v1 == 1 && v2 == 0) { Assert.AreEqual(100, l); Assert.AreEqual(-e01, e); Assert.AreEqual(100 / speed, w1); Assert.AreEqual(200 / speed, w2); reportedEdges.Add(-e01); } else if (v1 == 0 && v2 == 2) { Assert.AreEqual(100, l); Assert.AreEqual(e02, e); Assert.AreEqual(0, w1); Assert.AreEqual(100 / speed, w2); reportedEdges.Add(e02); } else if (v1 == 2 && v2 == 0) { Assert.AreEqual(100, l); Assert.AreEqual(-e02, e); Assert.AreEqual(100 / speed, w1); Assert.AreEqual(200 / speed, w2); reportedEdges.Add(-e02); } else if (v1 == 1 && v2 == 2) { Assert.AreEqual(100, l); Assert.AreEqual(e12, e); Assert.AreEqual(100 / speed, w1); Assert.AreEqual(200 / speed, w2); reportedEdges.Add(e12); } else if (v1 == 2 && v2 == 1) { Assert.AreEqual(100, l); Assert.AreEqual(-e12, e); Assert.AreEqual(100 / speed, w1); Assert.AreEqual(200 / speed, w2); reportedEdges.Add(-e12); } return(false); }; algorithm.Run(); Assert.IsTrue(algorithm.HasRun); Assert.IsTrue(algorithm.HasSucceeded); Assert.IsTrue(reportedEdges.Contains(e01)); Assert.IsTrue(reportedEdges.Contains(-e01)); Assert.IsTrue(reportedEdges.Contains(e02)); Assert.IsTrue(reportedEdges.Contains(-e02)); Assert.IsTrue(reportedEdges.Contains(e12)); Assert.IsTrue(reportedEdges.Contains(-e12)); }
/// <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>()) }); } }
/// <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>()) }); } }