/// <summary> /// Compares all routes against the reference router. /// </summary> public void TestCompareAll(string embeddedName) { // build the routing settings. IRoutingInterpreter interpreter = new OsmSharp.Routing.Osm.Interpreter.OsmRoutingInterpreter(); // get the osm data source. IBasicRouterDataSource <LiveEdge> data = this.BuildDykstraDataSource(interpreter, embeddedName); // build the reference router.; Router referenceRouter = this.BuildDykstraRouter( this.BuildDykstraDataSource(interpreter, embeddedName), interpreter, new DykstraRoutingLive(data.TagsIndex)); // build the router to be tested. Router router = this.BuildRouter(interpreter, embeddedName); // loop over all nodes and resolve their locations. var resolvedReference = new RouterPoint[data.VertexCount - 1]; var resolved = new RouterPoint[data.VertexCount - 1]; for (uint idx = 1; idx < data.VertexCount; idx++) { // resolve each vertex. float latitude, longitude; if (data.GetVertex(idx, out latitude, out longitude)) { resolvedReference[idx - 1] = referenceRouter.Resolve(Vehicle.Car, new GeoCoordinate(latitude, longitude)); resolved[idx - 1] = router.Resolve(Vehicle.Car, new GeoCoordinate(latitude, longitude)); } Assert.IsNotNull(resolvedReference[idx - 1]); Assert.IsNotNull(resolved[idx - 1]); Assert.AreEqual(resolvedReference[idx - 1].Location.Latitude, resolved[idx - 1].Location.Latitude, 0.0001); Assert.AreEqual(resolvedReference[idx - 1].Location.Longitude, resolved[idx - 1].Location.Longitude, 0.0001); } // check all the routes having the same weight(s). for (int fromIdx = 0; fromIdx < resolved.Length; fromIdx++) { for (int toIdx = 0; toIdx < resolved.Length; toIdx++) { OsmSharpRoute referenceRoute = referenceRouter.Calculate(Vehicle.Car, resolvedReference[fromIdx], resolvedReference[toIdx]); OsmSharpRoute route = router.Calculate(Vehicle.Car, resolved[fromIdx], resolved[toIdx]); Assert.IsNotNull(referenceRoute); Assert.IsNotNull(route); Assert.AreEqual(referenceRoute.TotalDistance, route.TotalDistance, 0.0001); // TODO: meta data is missing in some CH routing; see issue //Assert.AreEqual(reference_route.TotalTime, route.TotalTime, 0.0001); } } }
/// <summary> /// Tests that a router actually finds the shortest route. /// </summary> protected void DoTestShortestDefault() { var interpreter = new OsmRoutingInterpreter(); IBasicRouterDataSource <TEdgeData> data = this.BuildData(interpreter, "OsmSharp.Test.Unittests.test_network.osm"); IBasicRouter <TEdgeData> basicRouter = this.BuildBasicRouter(data); Router router = this.BuildRouter( data, interpreter, basicRouter); RouterPoint source = router.Resolve(Vehicle.Car, new GeoCoordinate(51.0578532, 3.7192229)); RouterPoint target = router.Resolve(Vehicle.Car, new GeoCoordinate(51.0576193, 3.7191801)); Route route = router.Calculate(Vehicle.Car, source, target); Assert.IsNotNull(route); Assert.AreEqual(5, route.Entries.Length); float latitude, longitude; data.GetVertex(20, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[0].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[0].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Start, route.Entries[0].Type); data.GetVertex(21, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[1].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[1].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Along, route.Entries[1].Type); data.GetVertex(16, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[2].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[2].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Along, route.Entries[2].Type); data.GetVertex(22, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[3].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[3].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Along, route.Entries[3].Type); data.GetVertex(23, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[4].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[4].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Stop, route.Entries[4].Type); }
/// <summary> /// Tests the the given router class by comparing calculated routes agains a given reference router. /// </summary> /// <param name="data"></param> /// <param name="referenceRouter"></param> /// <param name="router"></param> protected void TestCompareAll <TEdgeData>(IBasicRouterDataSource <TEdgeData> data, Router referenceRouter, Router router) where TEdgeData : IGraphEdgeData { // loop over all nodes and resolve their locations. var resolvedReference = new RouterPoint[data.VertexCount - 1]; var resolved = new RouterPoint[data.VertexCount - 1]; for (uint idx = 1; idx < data.VertexCount; idx++) { // resolve each vertex. float latitude, longitude; if (data.GetVertex(idx, out latitude, out longitude)) { resolvedReference[idx - 1] = referenceRouter.Resolve(Vehicle.Car, new GeoCoordinate(latitude, longitude), true); resolved[idx - 1] = router.Resolve(Vehicle.Car, new GeoCoordinate(latitude, longitude), true); } // reference and resolved have to exist. Assert.IsNotNull(resolvedReference[idx - 1]); Assert.IsNotNull(resolved[idx - 1]); // reference and resolved cannot be more than 10cm apart. Assert.AreEqual(0, resolvedReference[idx - 1].Location.DistanceReal( resolved[idx - 1].Location).Value, 0.1, "Reference and resolved are more than 10cm apart."); } // limit tests to a fixed number. int maxTestCount = 100; int testEveryOther = (resolved.Length * resolved.Length) / maxTestCount; testEveryOther = System.Math.Max(testEveryOther, 1); // check all the routes having the same weight(s). for (int fromIdx = 0; fromIdx < resolved.Length; fromIdx++) { for (int toIdx = 0; toIdx < resolved.Length; toIdx++) { int testNumber = fromIdx * resolved.Length + toIdx; if (testNumber % testEveryOther == 0) { var referenceRoute = referenceRouter.Calculate(Vehicle.Car, resolvedReference[fromIdx], resolvedReference[toIdx]); var route = router.Calculate(Vehicle.Car, resolved[fromIdx], resolved[toIdx]); if (referenceRoute != null) { Assert.IsNotNull(referenceRoute); Assert.IsNotNull(route); this.CompareRoutes(referenceRoute, route); } } } } }
/// <summary> /// Tests that a router actually finds the shortest route. /// </summary> protected void DoTestShortestWithDirection() { var interpreter = new OsmRoutingInterpreter(); IBasicRouterDataSource <EdgeData> data = this.BuildData(interpreter); IBasicRouter <EdgeData> basicRouter = this.BuildBasicRouter(data); Router router = this.BuildRouter( data, interpreter, basicRouter); RouterPoint source = router.Resolve(Vehicle.Car, new GeoCoordinate(51.0582205, 3.7192647)); // -52 RouterPoint target = router.Resolve(Vehicle.Car, new GeoCoordinate(51.0579530, 3.7196168)); // -56 OsmSharpRoute route = router.Calculate(Vehicle.Car, source, target); Assert.IsNotNull(route); Assert.AreEqual(4, route.Entries.Length); float latitude, longitude; data.GetVertex(19, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[0].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[0].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Start, route.Entries[0].Type); data.GetVertex(8, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[1].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[1].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Along, route.Entries[1].Type); data.GetVertex(9, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[2].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[2].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Along, route.Entries[2].Type); data.GetVertex(10, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[3].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[3].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Stop, route.Entries[3].Type); }
/// <summary> /// Tests that a router preserves tags given to resolved points. /// </summary> protected void DoTestResolvedTags() { var interpreter = new OsmRoutingInterpreter(); IBasicRouterDataSource <TEdgeData> data = this.BuildData(interpreter, "OsmSharp.Test.Unittests.test_network.osm"); IBasicRouter <TEdgeData> basicRouter = this.BuildBasicRouter(data); Router router = this.BuildRouter( data, interpreter, basicRouter); RouterPoint source = router.Resolve(Vehicle.Car, new GeoCoordinate(51.0578532, 3.7192229)); source.Tags.Add(new KeyValuePair <string, string>("name", "source")); RouterPoint target = router.Resolve(Vehicle.Car, new GeoCoordinate(51.0576193, 3.7191801)); target.Tags.Add(new KeyValuePair <string, string>("name", "target")); Route route = router.Calculate(Vehicle.Car, source, target); Assert.IsNotNull(route); Assert.AreEqual(5, route.Entries.Length); float latitude, longitude; data.GetVertex(20, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[0].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[0].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Start, route.Entries[0].Type); Assert.IsNotNull(route.Entries[0].Points[0].Tags); Assert.AreEqual(1, route.Entries[0].Points[0].Tags.Length); Assert.AreEqual("source", route.Entries[0].Points[0].Tags[0].Value); data.GetVertex(23, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[4].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[4].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Stop, route.Entries[4].Type); Assert.IsNotNull(route.Entries[4].Points[0].Tags); Assert.AreEqual(1, route.Entries[4].Points[0].Tags.Length); Assert.AreEqual("target", route.Entries[4].Points[0].Tags[0].Value); }
/// <summary> /// Tests that a router actually finds the shortest route. /// </summary> /// <param name="vehicle"></param> /// <param name="accessTags"></param> protected void DoTestShortestWithAccess(Vehicle vehicle, List <KeyValuePair <string, string> > accessTags) { var interpreter = new OsmRoutingInterpreter(); IBasicRouterDataSource <EdgeData> data = this.BuildData(interpreter, vehicle, accessTags); IBasicRouter <EdgeData> basicRouter = this.BuildBasicRouter(data, vehicle); Router router = this.BuildRouter( data, interpreter, basicRouter); RouterPoint source = router.Resolve(vehicle, new GeoCoordinate(51.0582205, 3.7192647)); // -52 RouterPoint target = router.Resolve(vehicle, new GeoCoordinate(51.0579530, 3.7196168)); // -56 Route route = router.Calculate(vehicle, source, target); Assert.IsNotNull(route); Assert.AreEqual(4, route.Segments.Length); float latitude, longitude; data.GetVertex(19, out latitude, out longitude); Assert.AreEqual(latitude, route.Segments[0].Latitude, 0.00001); Assert.AreEqual(longitude, route.Segments[0].Longitude, 0.00001); Assert.AreEqual(RouteSegmentType.Start, route.Segments[0].Type); data.GetVertex(8, out latitude, out longitude); Assert.AreEqual(latitude, route.Segments[1].Latitude, 0.00001); Assert.AreEqual(longitude, route.Segments[1].Longitude, 0.00001); Assert.AreEqual(RouteSegmentType.Along, route.Segments[1].Type); data.GetVertex(9, out latitude, out longitude); Assert.AreEqual(latitude, route.Segments[2].Latitude, 0.00001); Assert.AreEqual(longitude, route.Segments[2].Longitude, 0.00001); Assert.AreEqual(RouteSegmentType.Along, route.Segments[2].Type); data.GetVertex(10, out latitude, out longitude); Assert.AreEqual(latitude, route.Segments[3].Latitude, 0.00001); Assert.AreEqual(longitude, route.Segments[3].Longitude, 0.00001); Assert.AreEqual(RouteSegmentType.Stop, route.Segments[3].Type); }
/// <summary> /// Test if the resolving of nodes returns those same nodes. /// /// (does not work on a lazy loading data source!) /// </summary> protected void DoTestResolveAllNodes() { var interpreter = new OsmRoutingInterpreter(); IBasicRouterDataSource <EdgeData> data = this.BuildData(interpreter); IBasicRouter <EdgeData> basicRouter = this.BuildBasicRouter(data); Router router = this.BuildRouter( data, interpreter, basicRouter); for (int idx = 1; idx < data.VertexCount; idx++) { float latitude, longitude; if (data.GetVertex((uint)idx, out latitude, out longitude)) { RouterPoint point = router.Resolve(Vehicle.Car, new GeoCoordinate(latitude, longitude)); Assert.AreEqual(idx, (point as RouterPoint).Id); } } }
public void RoutingSerializationV2CompressedRoutingTest() { const string embeddedString = "OsmSharp.Test.Unittests.test_network.osm"; // create the tags index. var tagsIndex = new SimpleTagsIndex(); // creates a new interpreter. var interpreter = new OsmRoutingInterpreter(); // do the data processing. var original = new DynamicGraphRouterDataSource <LiveEdge>(tagsIndex); var targetData = new LiveGraphOsmStreamTarget( original, interpreter, tagsIndex); var dataProcessorSource = new XmlOsmStreamSource( Assembly.GetExecutingAssembly().GetManifestResourceStream(embeddedString)); targetData.RegisterSource(dataProcessorSource); targetData.Pull(); // create serializer. var routingSerializer = new V2RoutingDataSourceLiveEdgeSerializer(true); // serialize/deserialize. byte[] byteArray; using (var stream = new MemoryStream()) { try { routingSerializer.Serialize(stream, original); byteArray = stream.ToArray(); } catch (Exception) { if (Debugger.IsAttached) { Debugger.Break(); } throw; } } IBasicRouterDataSource <LiveEdge> deserializedVersion = routingSerializer.Deserialize(new MemoryStream(byteArray)); Assert.AreEqual(original.TagsIndex.Get(0), deserializedVersion.TagsIndex.Get(0)); // try to do some routing on the deserialized version. var basicRouter = new DykstraRoutingLive(); Router router = Router.CreateLiveFrom(deserializedVersion, basicRouter, interpreter); RouterPoint source = router.Resolve(Vehicle.Car, new GeoCoordinate(51.0578532, 3.7192229)); RouterPoint target = router.Resolve(Vehicle.Car, new GeoCoordinate(51.0576193, 3.7191801)); // calculate the route. Route route = router.Calculate(Vehicle.Car, source, target); Assert.IsNotNull(route); Assert.AreEqual(5, route.Entries.Length); float latitude, longitude; deserializedVersion.GetVertex(20, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[0].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[0].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Start, route.Entries[0].Type); deserializedVersion.GetVertex(21, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[1].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[1].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Along, route.Entries[1].Type); deserializedVersion.GetVertex(16, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[2].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[2].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Along, route.Entries[2].Type); deserializedVersion.GetVertex(22, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[3].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[3].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Along, route.Entries[3].Type); deserializedVersion.GetVertex(23, out latitude, out longitude); Assert.AreEqual(latitude, route.Entries[4].Latitude, 0.00001); Assert.AreEqual(longitude, route.Entries[4].Longitude, 0.00001); Assert.AreEqual(RoutePointEntryType.Stop, route.Entries[4].Type); }
/// <summary> /// Searches the data for a point on an edge closest to the given coordinate. /// </summary> /// <param name="graph"></param> /// <param name="vehicle"></param> /// <param name="coordinate"></param> /// <param name="delta"></param> /// <param name="matcher"></param> /// <param name="pointTags"></param> /// <param name="interpreter"></param> /// <param name="verticesOnly"></param> public SearchClosestResult SearchClosest(IBasicRouterDataSource <TEdgeData> graph, IRoutingInterpreter interpreter, Vehicle vehicle, GeoCoordinate coordinate, float delta, IEdgeMatcher matcher, TagsCollection pointTags, bool verticesOnly) { var closestWithMatch = new SearchClosestResult(double.MaxValue, 0); var closestWithoutMatch = new SearchClosestResult(double.MaxValue, 0); double searchBoxSize = delta; // create the search box. var searchBox = new GeoCoordinateBox(new GeoCoordinate( coordinate.Latitude - searchBoxSize, coordinate.Longitude - searchBoxSize), new GeoCoordinate( coordinate.Latitude + searchBoxSize, coordinate.Longitude + searchBoxSize)); // get the arcs from the data source. KeyValuePair <uint, KeyValuePair <uint, TEdgeData> >[] arcs = graph.GetArcs(searchBox); if (!verticesOnly) { // find both closest arcs and vertices. // loop over all. foreach (KeyValuePair <uint, KeyValuePair <uint, TEdgeData> > arc in arcs) { TagsCollection arcTags = graph.TagsIndex.Get(arc.Value.Value.Tags); bool canBeTraversed = vehicle.CanTraverse(arcTags); if (canBeTraversed) { // the edge can be traversed. // test the two points. float fromLatitude, fromLongitude; float toLatitude, toLongitude; double distance; if (graph.GetVertex(arc.Key, out fromLatitude, out fromLongitude) && graph.GetVertex(arc.Value.Key, out toLatitude, out toLongitude)) { // return the vertex. var fromCoordinates = new GeoCoordinate(fromLatitude, fromLongitude); distance = coordinate.Distance(fromCoordinates); if (distance < 0.00001) { // the distance is smaller than the tolerance value. closestWithoutMatch = new SearchClosestResult( distance, arc.Key); if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, arcTags)) { closestWithMatch = new SearchClosestResult( distance, arc.Key); break; } } if (distance < closestWithoutMatch.Distance) { // the distance is smaller for the without match. closestWithoutMatch = new SearchClosestResult( distance, arc.Key); } if (distance < closestWithMatch.Distance) { // the distance is smaller for the with match. if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, graph.TagsIndex.Get(arc.Value.Value.Tags))) { closestWithMatch = new SearchClosestResult( distance, arc.Key); } } var toCoordinates = new GeoCoordinate(toLatitude, toLongitude); distance = coordinate.Distance(toCoordinates); if (distance < closestWithoutMatch.Distance) { // the distance is smaller for the without match. closestWithoutMatch = new SearchClosestResult( distance, arc.Value.Key); } if (distance < closestWithMatch.Distance) { // the distance is smaller for the with match. if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, arcTags)) { closestWithMatch = new SearchClosestResult( distance, arc.Value.Key); } } // create a line. double distanceTotal = fromCoordinates.Distance(toCoordinates); if (distanceTotal > 0) { // the from/to are not the same location. var line = new GeoCoordinateLine(fromCoordinates, toCoordinates, true, true); distance = line.Distance(coordinate); if (distance < closestWithoutMatch.Distance) { // the distance is smaller. PointF2D projectedPoint = line.ProjectOn(coordinate); // calculate the position. if (projectedPoint != null) { // calculate the distance double distancePoint = fromCoordinates.Distance(projectedPoint); double position = distancePoint / distanceTotal; closestWithoutMatch = new SearchClosestResult( distance, arc.Key, arc.Value.Key, position); } } if (distance < closestWithMatch.Distance) { PointF2D projectedPoint = line.ProjectOn(coordinate); // calculate the position. if (projectedPoint != null) { // calculate the distance double distancePoint = fromCoordinates.Distance(projectedPoint); double position = distancePoint / distanceTotal; if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, arcTags)) { closestWithMatch = new SearchClosestResult( distance, arc.Key, arc.Value.Key, position); } } } } } } } } else { // only find closest vertices. // loop over all. foreach (KeyValuePair <uint, KeyValuePair <uint, TEdgeData> > arc in arcs) { float fromLatitude, fromLongitude; float toLatitude, toLongitude; if (graph.GetVertex(arc.Key, out fromLatitude, out fromLongitude) && graph.GetVertex(arc.Value.Key, out toLatitude, out toLongitude)) { var vertexCoordinate = new GeoCoordinate(fromLatitude, fromLongitude); double distance = coordinate.Distance(vertexCoordinate); if (distance < closestWithoutMatch.Distance) { // the distance found is closer. closestWithoutMatch = new SearchClosestResult( distance, arc.Key); } vertexCoordinate = new GeoCoordinate(toLatitude, toLongitude); distance = coordinate.Distance(vertexCoordinate); if (distance < closestWithoutMatch.Distance) { // the distance found is closer. closestWithoutMatch = new SearchClosestResult( distance, arc.Value.Key); } } } } // return the best result. if (closestWithMatch.Distance < double.MaxValue) { return(closestWithMatch); } return(closestWithoutMatch); }
/// <summary> /// Builds the scene. /// </summary> /// <param name="map"></param> /// <param name="zoomFactor"></param> /// <param name="center"></param> /// <param name="view"></param> private void BuildScene(Map map, float zoomFactor, GeoCoordinate center, View2D view) { // get the indexed object at this zoom. HashSet <ArcId> interpretedObjects; if (!_interpretedObjects.TryGetValue((int)zoomFactor, out interpretedObjects)) { interpretedObjects = new HashSet <ArcId>(); _interpretedObjects.Add((int)zoomFactor, interpretedObjects); } // build the boundingbox. var viewBox = view.OuterBox; var box = new GeoCoordinateBox(map.Projection.ToGeoCoordinates(viewBox.Min[0], viewBox.Min[1]), map.Projection.ToGeoCoordinates(viewBox.Max[0], viewBox.Max[1])); foreach (var requestedBox in _requestedBoxes) { if (requestedBox.Contains(box)) { return; } } _requestedBoxes.Add(box); //// set the scene backcolor. //SimpleColor? color = _styleInterpreter.GetCanvasColor (); //_scene.BackColor = color.HasValue // ? color.Value.Value // : SimpleColor.FromArgb (0, 255, 255, 255).Value; // get data. foreach (var arc in _dataSource.GetEdges(box)) { // translate each object into scene object. var arcId = new ArcId() { Vertex1 = arc.Key, Vertex2 = arc.Value.Key }; if (!interpretedObjects.Contains(arcId)) { interpretedObjects.Add(arcId); // create nodes. float latitude, longitude; _dataSource.GetVertex(arcId.Vertex1, out latitude, out longitude); var node1 = new Node(); node1.Id = arcId.Vertex1; node1.Latitude = latitude; node1.Longitude = longitude; _dataSource.GetVertex(arcId.Vertex2, out latitude, out longitude); var node2 = new Node(); node2.Id = arcId.Vertex2; node2.Latitude = latitude; node2.Longitude = longitude; // create way. var way = CompleteWay.Create(-1); if (arc.Value.Value.Forward) { way.Nodes.Add(node1); way.Nodes.Add(node2); } else { way.Nodes.Add(node2); way.Nodes.Add(node1); } way.Tags.AddOrReplace(_dataSource.TagsIndex.Get(arc.Value.Value.Tags)); _styleInterpreter.Translate(_scene, map.Projection, way); interpretedObjects.Add(arcId); } } }
/// <summary> /// Does dykstra calculation(s) with several options. /// </summary> /// <param name="graph"></param> /// <param name="interpreter"></param> /// <param name="vehicle"></param> /// <param name="sourceList"></param> /// <param name="targetList"></param> /// <param name="weight"></param> /// <param name="stopAtFirst"></param> /// <param name="returnAtWeight"></param> /// <param name="forward"></param> /// <returns></returns> private PathSegment <long>[] DoCalculation(IBasicRouterDataSource <LiveEdge> graph, IRoutingInterpreter interpreter, Vehicle vehicle, PathSegmentVisitList sourceList, PathSegmentVisitList[] targetList, double weight, bool stopAtFirst, bool returnAtWeight, bool forward) { // make copies of the target and source visitlist. PathSegmentVisitList source = sourceList.Clone() as PathSegmentVisitList; PathSegmentVisitList[] targets = new PathSegmentVisitList[targetList.Length]; for (int targetIdx = 0; targetIdx < targetList.Length; targetIdx++) { targets[targetIdx] = targetList[targetIdx].Clone() as PathSegmentVisitList; } // initialize the result data structures. var segmentsAtWeight = new List <PathSegment <long> >(); var segmentsToTarget = new PathSegment <long> [targets.Length]; // the resulting target segments. long foundTargets = 0; // intialize dykstra data structures. IPriorityQueue <PathSegment <long> > heap = new BinairyHeap <PathSegment <long> >(); var chosenVertices = new HashSet <long>(); var labels = new Dictionary <long, IList <RoutingLabel> >(); foreach (long vertex in source.GetVertices()) { labels[vertex] = new List <RoutingLabel>(); PathSegment <long> path = source.GetPathTo(vertex); heap.Push(path, (float)path.Weight); } // set the from node as the current node and put it in the correct data structures. // intialize the source's neighbours. PathSegment <long> current = heap.Pop(); while (current != null && chosenVertices.Contains(current.VertexId)) { // keep dequeuing. current = heap.Pop(); } // test each target for the source. // test each source for any of the targets. var pathsFromSource = new Dictionary <long, PathSegment <long> >(); foreach (long sourceVertex in source.GetVertices()) { // get the path to the vertex. PathSegment <long> sourcePath = source.GetPathTo(sourceVertex); // get the source path. sourcePath = sourcePath.From; while (sourcePath != null) { // add the path to the paths from source. pathsFromSource[sourcePath.VertexId] = sourcePath; sourcePath = sourcePath.From; } } // loop over all targets for (int idx = 0; idx < targets.Length; idx++) { // check for each target if there are paths to the source. foreach (long targetVertex in targets[idx].GetVertices()) { PathSegment <long> targetPath = targets[idx].GetPathTo(targetVertex); // get the target path. targetPath = targetPath.From; while (targetPath != null) { // add the path to the paths from source. PathSegment <long> pathFromSource; if (pathsFromSource.TryGetValue(targetPath.VertexId, out pathFromSource)) { // a path is found. // get the existing path if any. PathSegment <long> existing = segmentsToTarget[idx]; if (existing == null) { // a path did not exist yet! segmentsToTarget[idx] = targetPath.Reverse().ConcatenateAfter(pathFromSource); foundTargets++; } else if (existing.Weight > targetPath.Weight + pathFromSource.Weight) { // a new path is found with a lower weight. segmentsToTarget[idx] = targetPath.Reverse().ConcatenateAfter(pathFromSource); } } targetPath = targetPath.From; } } } if (foundTargets == targets.Length && targets.Length > 0) { // routing is finished! return(segmentsToTarget.ToArray()); } if (stopAtFirst) { // only one entry is needed. if (foundTargets > 0) { // targets found, return the shortest! PathSegment <long> shortest = null; foreach (PathSegment <long> foundTarget in segmentsToTarget) { if (shortest == null) { shortest = foundTarget; } else if (foundTarget != null && shortest.Weight > foundTarget.Weight) { shortest = foundTarget; } } segmentsToTarget = new PathSegment <long> [1]; segmentsToTarget[0] = shortest; return(segmentsToTarget); } else { // not targets found yet! segmentsToTarget = new PathSegment <long> [1]; } } // test for identical start/end point. for (int idx = 0; idx < targets.Length; idx++) { PathSegmentVisitList target = targets[idx]; if (returnAtWeight) { // add all the reached vertices larger than weight to the results. if (current.Weight > weight) { PathSegment <long> toPath = target.GetPathTo(current.VertexId); toPath.Reverse(); toPath = toPath.ConcatenateAfter(current); segmentsAtWeight.Add(toPath); } } else if (target.Contains(current.VertexId)) { // the current is a target! PathSegment <long> toPath = target.GetPathTo(current.VertexId); toPath = toPath.Reverse(); toPath = toPath.ConcatenateAfter(current); if (stopAtFirst) { // stop at the first occurance. segmentsToTarget[0] = toPath; return(segmentsToTarget); } else { // normal one-to-many; add to the result. // check if routing is finished. if (segmentsToTarget[idx] == null) { // make sure only the first route is set. foundTargets++; segmentsToTarget[idx] = toPath; if (foundTargets == targets.Length) { // routing is finished! return(segmentsToTarget.ToArray()); } } else if (segmentsToTarget[idx].Weight > toPath.Weight) { // check if the second, third or later is shorter. segmentsToTarget[idx] = toPath; } } } } // start OsmSharp.Routing. KeyValuePair <uint, LiveEdge>[] arcs = graph.GetArcs( Convert.ToUInt32(current.VertexId)); chosenVertices.Add(current.VertexId); // loop until target is found and the route is the shortest! while (true) { // get the current labels list (if needed). IList <RoutingLabel> currentLabels = null; if (interpreter.Constraints != null) { // there are constraints, get the labels. currentLabels = labels[current.VertexId]; labels.Remove(current.VertexId); } float latitude, longitude; graph.GetVertex(Convert.ToUInt32(current.VertexId), out latitude, out longitude); var currentCoordinates = new GeoCoordinate(latitude, longitude); // update the visited nodes. foreach (KeyValuePair <uint, LiveEdge> neighbour in arcs) { // check the tags against the interpreter. TagsCollection tags = graph.TagsIndex.Get(neighbour.Value.Tags); if (vehicle.CanTraverse(tags)) { // it's ok; the edge can be traversed by the given vehicle. bool?oneWay = vehicle.IsOneWay(tags); bool canBeTraversedOneWay = (!oneWay.HasValue || oneWay.Value == neighbour.Value.Forward); if ((current.From == null || interpreter.CanBeTraversed(current.From.VertexId, current.VertexId, neighbour.Key)) && // test for turning restrictions. canBeTraversedOneWay && !chosenVertices.Contains(neighbour.Key)) { // the neigbour is forward and is not settled yet! // check the labels (if needed). bool constraintsOk = true; if (interpreter.Constraints != null) { // check if the label is ok. RoutingLabel neighbourLabel = interpreter.Constraints.GetLabelFor( graph.TagsIndex.Get(neighbour.Value.Tags)); // only test labels if there is a change. if (currentLabels.Count == 0 || !neighbourLabel.Equals(currentLabels[currentLabels.Count - 1])) { // labels are different, test them! constraintsOk = interpreter.Constraints.ForwardSequenceAllowed(currentLabels, neighbourLabel); if (constraintsOk) { // update the labels. var neighbourLabels = new List <RoutingLabel>(currentLabels); neighbourLabels.Add(neighbourLabel); labels[neighbour.Key] = neighbourLabels; } } else { // set the same label(s). labels[neighbour.Key] = currentLabels; } } if (constraintsOk) { // all constraints are validated or there are none. graph.GetVertex(Convert.ToUInt32(neighbour.Key), out latitude, out longitude); var neighbourCoordinates = new GeoCoordinate(latitude, longitude); // calculate the weight. double weightToNeighbour = vehicle.Weight(tags, currentCoordinates, neighbourCoordinates); // calculate neighbours weight. double totalWeight = current.Weight + weightToNeighbour; // update the visit list; var neighbourRoute = new PathSegment <long>(neighbour.Key, totalWeight, current); heap.Push(neighbourRoute, (float)neighbourRoute.Weight); } } } } // while the visit list is not empty. current = null; if (heap.Count > 0) { // choose the next vertex. current = heap.Pop(); while (current != null && chosenVertices.Contains(current.VertexId)) { // keep dequeuing. current = heap.Pop(); } if (current != null) { chosenVertices.Add(current.VertexId); } } while (current != null && current.Weight > weight) { if (returnAtWeight) { // add all the reached vertices larger than weight to the results. segmentsAtWeight.Add(current); } // choose the next vertex. current = heap.Pop(); while (current != null && chosenVertices.Contains(current.VertexId)) { // keep dequeuing. current = heap.Pop(); } } if (current == null) { // route is not found, there are no vertices left // or the search whent outside of the max bounds. break; } // check target. for (int idx = 0; idx < targets.Length; idx++) { PathSegmentVisitList target = targets[idx]; if (target.Contains(current.VertexId)) { // the current is a target! PathSegment <long> toPath = target.GetPathTo(current.VertexId); toPath = toPath.Reverse(); toPath = toPath.ConcatenateAfter(current); if (stopAtFirst) { // stop at the first occurance. segmentsToTarget[0] = toPath; return(segmentsToTarget); } else { // normal one-to-many; add to the result. // check if routing is finished. if (segmentsToTarget[idx] == null) { // make sure only the first route is set. segmentsToTarget[idx] = toPath; } else if (segmentsToTarget[idx].Weight > toPath.Weight) { // check if the second, third or later is shorter. segmentsToTarget[idx] = toPath; } // remove this vertex from this target's paths. target.Remove(current.VertexId); // if this target is empty it's optimal route has been found. if (target.Count == 0) { // now the shortest route has been found for sure! foundTargets++; if (foundTargets == targets.Length) { // routing is finished! return(segmentsToTarget.ToArray()); } } } } } // get the neigbours of the current node. arcs = graph.GetArcs(Convert.ToUInt32(current.VertexId)); } // return the result. if (!returnAtWeight) { return(segmentsToTarget.ToArray()); } return(segmentsAtWeight.ToArray()); }
/// <summary> /// Searches the data for a point on an edge closest to the given coordinate. /// </summary> /// <param name="graph"></param> /// <param name="vehicle"></param> /// <param name="coordinate"></param> /// <param name="delta"></param> /// <param name="matcher"></param> /// <param name="pointTags"></param> /// <param name="interpreter"></param> /// <param name="verticesOnly"></param> /// <param name="parameters"></param> public SearchClosestResult <TEdgeData> SearchClosest(IBasicRouterDataSource <TEdgeData> graph, IRoutingInterpreter interpreter, Vehicle vehicle, GeoCoordinate coordinate, float delta, IEdgeMatcher matcher, TagsCollectionBase pointTags, bool verticesOnly, Dictionary <string, object> parameters) { Meter distanceEpsilon = .1; // 10cm is the tolerance to distinguish points. var closestWithMatch = new SearchClosestResult <TEdgeData>(double.MaxValue, 0); var closestWithoutMatch = new SearchClosestResult <TEdgeData>(double.MaxValue, 0); double searchBoxSize = delta; // create the search box. var searchBox = new GeoCoordinateBox(new GeoCoordinate( coordinate.Latitude - searchBoxSize, coordinate.Longitude - searchBoxSize), new GeoCoordinate( coordinate.Latitude + searchBoxSize, coordinate.Longitude + searchBoxSize)); // get the arcs from the data source. var arcs = graph.GetEdges(searchBox); if (!verticesOnly) { // find both closest arcs and vertices. // loop over all. while (arcs.MoveNext()) { if (!graph.TagsIndex.Contains(arcs.EdgeData.Tags)) { // skip this edge, no valid tags found. continue; } var arcTags = graph.TagsIndex.Get(arcs.EdgeData.Tags); var canBeTraversed = vehicle.CanTraverse(arcTags); if (canBeTraversed) { // the edge can be traversed. // test the two points. float fromLatitude, fromLongitude; float toLatitude, toLongitude; double distance; if (graph.GetVertex(arcs.Vertex1, out fromLatitude, out fromLongitude) && graph.GetVertex(arcs.Vertex2, out toLatitude, out toLongitude)) { // return the vertex. var fromCoordinates = new GeoCoordinate(fromLatitude, fromLongitude); distance = coordinate.DistanceReal(fromCoordinates).Value; ICoordinateCollection coordinates; ICoordinate[] coordinatesArray = null; if (!graph.GetEdgeShape(arcs.Vertex1, arcs.Vertex2, out coordinates)) { coordinates = null; } if (coordinates != null) { coordinatesArray = coordinates.ToArray(); } if (distance < distanceEpsilon.Value) { // the distance is smaller than the tolerance value. closestWithoutMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1); if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, arcTags)) { closestWithMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1); break; } } if (distance < closestWithoutMatch.Distance) { // the distance is smaller for the without match. closestWithoutMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1); } if (distance < closestWithMatch.Distance) { // the distance is smaller for the with match. if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, graph.TagsIndex.Get(arcs.EdgeData.Tags))) { closestWithMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1); } } var toCoordinates = new GeoCoordinate(toLatitude, toLongitude); distance = coordinate.DistanceReal(toCoordinates).Value; if (distance < closestWithoutMatch.Distance) { // the distance is smaller for the without match. closestWithoutMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex2); } if (distance < closestWithMatch.Distance) { // the distance is smaller for the with match. if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, arcTags)) { closestWithMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex2); } } // search along the line. var distanceTotal = 0.0; var previous = fromCoordinates; var arcValueValueCoordinates = arcs.Intermediates; if (arcValueValueCoordinates != null) { // calculate distance along all coordinates. var arcValueValueCoordinatesArray = arcValueValueCoordinates.ToArray(); for (int idx = 0; idx < arcValueValueCoordinatesArray.Length; idx++) { var current = new GeoCoordinate(arcValueValueCoordinatesArray[idx].Latitude, arcValueValueCoordinatesArray[idx].Longitude); distanceTotal = distanceTotal + current.DistanceReal(previous).Value; previous = current; } } distanceTotal = distanceTotal + toCoordinates.DistanceReal(previous).Value; if (distanceTotal > 0) { // the from/to are not the same location. // loop over all edges that are represented by this arc (counting intermediate coordinates). previous = fromCoordinates; GeoCoordinateLine line; var distanceToSegment = 0.0; if (arcValueValueCoordinates != null) { var arcValueValueCoordinatesArray = arcValueValueCoordinates.ToArray(); for (int idx = 0; idx < arcValueValueCoordinatesArray.Length; idx++) { var current = new GeoCoordinate( arcValueValueCoordinatesArray[idx].Latitude, arcValueValueCoordinatesArray[idx].Longitude); line = new GeoCoordinateLine(previous, current, true, true); distance = line.DistanceReal(coordinate).Value; if (distance < closestWithoutMatch.Distance) { // the distance is smaller. var projectedPoint = line.ProjectOn(coordinate); // calculate the position. if (projectedPoint != null) { // calculate the distance var distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment; var position = distancePoint / distanceTotal; closestWithoutMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1, arcs.Vertex2, position, arcs.EdgeData, coordinatesArray); } } if (distance < closestWithMatch.Distance) { var projectedPoint = line.ProjectOn(coordinate); // calculate the position. if (projectedPoint != null) { // calculate the distance var distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment; var position = distancePoint / distanceTotal; if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, arcTags)) { closestWithMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1, arcs.Vertex2, position, arcs.EdgeData, coordinatesArray); } } } // add current segment distance to distanceToSegment for the next segment. distanceToSegment = distanceToSegment + line.LengthReal.Value; // set previous. previous = current; } } // check the last segment. line = new GeoCoordinateLine(previous, toCoordinates, true, true); distance = line.DistanceReal(coordinate).Value; if (distance < closestWithoutMatch.Distance) { // the distance is smaller. var projectedPoint = line.ProjectOn(coordinate); // calculate the position. if (projectedPoint != null) { // calculate the distance double distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment; double position = distancePoint / distanceTotal; closestWithoutMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1, arcs.Vertex2, position, arcs.EdgeData, coordinatesArray); } } if (distance < closestWithMatch.Distance) { var projectedPoint = line.ProjectOn(coordinate); // calculate the position. if (projectedPoint != null) { // calculate the distance double distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment; double position = distancePoint / distanceTotal; if (matcher == null || (pointTags == null || pointTags.Count == 0) || matcher.MatchWithEdge(vehicle, pointTags, arcTags)) { closestWithMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1, arcs.Vertex2, position, arcs.EdgeData, coordinatesArray); } } } } } } } } else { // only find closest vertices. // loop over all. while (arcs.MoveNext()) { float fromLatitude, fromLongitude; float toLatitude, toLongitude; if (graph.GetVertex(arcs.Vertex1, out fromLatitude, out fromLongitude) && graph.GetVertex(arcs.Vertex2, out toLatitude, out toLongitude)) { var vertexCoordinate = new GeoCoordinate(fromLatitude, fromLongitude); double distance = coordinate.DistanceReal(vertexCoordinate).Value; if (distance < closestWithoutMatch.Distance) { // the distance found is closer. closestWithoutMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1); } vertexCoordinate = new GeoCoordinate(toLatitude, toLongitude); distance = coordinate.DistanceReal(vertexCoordinate).Value; if (distance < closestWithoutMatch.Distance) { // the distance found is closer. closestWithoutMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex2); } var arcValueValueCoordinates = arcs.Intermediates; if (arcValueValueCoordinates != null) { // search over intermediate points. var arcValueValueCoordinatesArray = arcValueValueCoordinates.ToArray(); for (int idx = 0; idx < arcValueValueCoordinatesArray.Length; idx++) { vertexCoordinate = new GeoCoordinate( arcValueValueCoordinatesArray[idx].Latitude, arcValueValueCoordinatesArray[idx].Longitude); distance = coordinate.DistanceReal(vertexCoordinate).Value; if (distance < closestWithoutMatch.Distance) { // the distance found is closer. closestWithoutMatch = new SearchClosestResult <TEdgeData>( distance, arcs.Vertex1, arcs.Vertex2, idx, arcs.EdgeData, arcValueValueCoordinatesArray); } } } } } } // return the best result. if (closestWithMatch.Distance < double.MaxValue) { return(closestWithMatch); } return(closestWithoutMatch); }