/// <summary> /// Processes the given node. /// </summary> /// <param name="node"></param> public override void AddNode(Node node) { if (node.Tags != null) { _tagsIndex.Add(node.Tags); } }
/// <summary> /// Calculates edge data. /// </summary> /// <param name="edgeInterpreter"></param> /// <param name="tagsIndex"></param> /// <param name="tags"></param> /// <param name="directionForward"></param> /// <param name="from"></param> /// <param name="to"></param> /// <returns></returns> protected override CHEdgeData CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsCollectionIndex tagsIndex, TagsCollectionBase tags, bool directionForward, GeoCoordinate from, GeoCoordinate to) { double weight = _vehicle.Weight(tags, from, to); bool? direction = _vehicle.IsOneWay(tags); bool forward = false; bool backward = false; if (!direction.HasValue) { // both directions. forward = true; backward = true; } else { // define back/forward. forward = (directionForward && direction.Value) || (!directionForward && !direction.Value); backward = (directionForward && !direction.Value) || (!directionForward && direction.Value); } // initialize the edge data. CHEdgeData edgeData = new CHEdgeData() { Weight = (float)weight, Tags = tagsIndex.Add( tags), ContractedVertexId = 0 }; edgeData.SetDirection(forward, backward, true); return(edgeData); }
///// <summary> ///// Adds an edge. ///// </summary> ///// <param name="forward"></param> ///// <param name="from"></param> ///// <param name="to"></param> ///// <param name="tags"></param> ///// <param name="intermediates"></param> //protected override void AddRoadEdge(TagsCollectionBase tags, bool forward, uint from, uint to, List<GeoCoordinateSimple> intermediates) //{ // float latitude; // float longitude; // GeoCoordinate fromCoordinate = null; // if (this.DynamicGraph.GetVertex(from, out latitude, out longitude)) // { // // fromCoordinate = new GeoCoordinate(latitude, longitude); // } // GeoCoordinate toCoordinate = null; // if (this.DynamicGraph.GetVertex(to, out latitude, out longitude)) // { // // toCoordinate = new GeoCoordinate(latitude, longitude); // } // if (fromCoordinate != null && toCoordinate != null) // { // calculate the edge data. // var edgeData = this.CalculateEdgeData(this.Interpreter.EdgeInterpreter, this.TagsIndex, tags, forward, fromCoordinate, toCoordinate, intermediates); // ICoordinateCollection intermediatesCollection = null; // if(intermediates != null) // { // intermediatesCollection = new CoordinateArrayCollection<GeoCoordinateSimple>(intermediates.ToArray()); // } // this.DynamicGraph.AddEdge(from, to, edgeData, intermediatesCollection, this.EdgeComparer); // } //} /// <summary> /// Calculates edge data. /// </summary> /// <param name="tagsIndex"></param> /// <param name="tags"></param> /// <param name="directionForward"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="edgeInterpreter"></param> /// <param name="intermediates"></param> /// <returns></returns> protected override LiveEdge CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsCollectionIndex tagsIndex, TagsCollectionBase tags, bool tagsForward, GeoCoordinate from, GeoCoordinate to, List <GeoCoordinateSimple> intermediates) { if (edgeInterpreter == null) { throw new ArgumentNullException("edgeInterpreter"); } if (tagsIndex == null) { throw new ArgumentNullException("tagsIndex"); } if (tags == null) { throw new ArgumentNullException("tags"); } if (from == null) { throw new ArgumentNullException("from"); } if (to == null) { throw new ArgumentNullException("to"); } uint tagsId = tagsIndex.Add(tags); return(new LiveEdge() { Forward = tagsForward, Tags = tagsId, Distance = (float)from.DistanceEstimate(to).Value }); }
/// <summary> /// Calculates edge data. /// </summary> /// <param name="tagsIndex"></param> /// <param name="tags"></param> /// <param name="directionForward"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="edgeInterpreter"></param> /// <returns></returns> protected override LiveEdge CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsCollectionIndex tagsIndex, TagsCollectionBase tags, bool directionForward, GeoCoordinate from, GeoCoordinate to) { if (edgeInterpreter == null) { throw new ArgumentNullException("edgeInterpreter"); } if (tagsIndex == null) { throw new ArgumentNullException("tagsIndex"); } if (tags == null) { throw new ArgumentNullException("tags"); } if (from == null) { throw new ArgumentNullException("from"); } if (to == null) { throw new ArgumentNullException("to"); } uint tagsId = tagsIndex.Add(tags); return(new LiveEdge() { Forward = directionForward, Tags = tagsId }); }
/// <summary> /// Calculates edge data. /// </summary> /// <param name="edgeInterpreter"></param> /// <param name="tagsIndex"></param> /// <param name="tags"></param> /// <param name="tagsForward"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="intermediates"></param> /// <returns></returns> protected override CHEdgeData CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsCollectionIndex tagsIndex, TagsCollectionBase tags, bool tagsForward, GeoCoordinate from, GeoCoordinate to, List <GeoCoordinateSimple> intermediates) { var direction = _vehicle.IsOneWay(tags); var forward = false; var backward = false; if (!direction.HasValue) { // both directions. forward = true; backward = true; } else { // define back/forward. if (tagsForward) { // relatively same direction. forward = direction.Value; backward = !direction.Value; } else { // relatively opposite direction. forward = !direction.Value; backward = direction.Value; } } // add tags. var tagsId = tagsIndex.Add(tags); // calculate weight including intermediates. float weight = 0; var previous = from; if (intermediates != null) { for (int idx = 0; idx < intermediates.Count; idx++) { var current = new GeoCoordinate(intermediates[idx].Latitude, intermediates[idx].Longitude); weight = weight + (float)_vehicle.Weight(tags, previous, current); previous = current; } } weight = weight + (float)_vehicle.Weight(tags, previous, to); // initialize the edge data. return(new CHEdgeData(tagsId, tagsForward, forward, backward, weight)); }
/// <summary> /// Tests the given tags collection index. /// </summary> /// <param name="tagsCollectionIndex"></param> protected void TestTagsCollectionIndex(ITagsCollectionIndex tagsCollectionIndex) { List <KeyValuePair <uint, TagsCollectionBase> > addedTags = new List <KeyValuePair <uint, TagsCollectionBase> >(); for (int i = 0; i < 100; i++) { TagsCollection tagsCollection = new TagsCollection(); int tagCollectionSize = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(3) + 1; for (int idx = 0; idx < tagCollectionSize; idx++) { int tagValue = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(3); tagsCollection.Add( string.Format("key_{0}", tagValue), string.Format("value_{0}", tagValue)); } int addCount = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(2) + 1; for (int idx = 0; idx < addCount; idx++) { uint tagsId = tagsCollectionIndex.Add(tagsCollection); addedTags.Add(new KeyValuePair <uint, TagsCollectionBase>(tagsId, tagsCollection)); TagsCollectionBase indexTags = tagsCollectionIndex.Get(tagsId); Assert.AreEqual(tagsCollection.Count, indexTags.Count); foreach (Tag tag in tagsCollection) { Assert.IsTrue(indexTags.ContainsKeyValue(tag.Key, tag.Value)); } } } // check the index. foreach (KeyValuePair <uint, TagsCollectionBase> pair in addedTags) { TagsCollectionBase indexTags = tagsCollectionIndex.Get(pair.Key); Assert.AreEqual(pair.Value.Count, indexTags.Count); foreach (Tag tag in pair.Value) { Assert.IsTrue(indexTags.ContainsKeyValue(tag.Key, tag.Value)); } foreach (Tag tag in indexTags) { Assert.IsTrue(pair.Value.ContainsKeyValue(tag.Key, tag.Value)); } } }
/// <summary> /// Tests the given tags collection index. /// </summary> /// <param name="tagsCollectionIndex"></param> protected void TestTagsCollectionIndex(ITagsCollectionIndex tagsCollectionIndex) { List<KeyValuePair<uint, TagsCollectionBase>> addedTags = new List<KeyValuePair<uint, TagsCollectionBase>>(); for (int i = 0; i < 100; i++) { TagsCollection tagsCollection = new TagsCollection(); int tagCollectionSize = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(3) + 1; for (int idx = 0; idx < tagCollectionSize; idx++) { int tagValue = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(3); tagsCollection.Add( string.Format("key_{0}", tagValue), string.Format("value_{0}", tagValue)); } int addCount = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(2) + 1; for (int idx = 0; idx < addCount; idx++) { uint tagsId = tagsCollectionIndex.Add(tagsCollection); addedTags.Add(new KeyValuePair<uint, TagsCollectionBase>(tagsId, tagsCollection)); TagsCollectionBase indexTags = tagsCollectionIndex.Get(tagsId); Assert.AreEqual(tagsCollection.Count, indexTags.Count); foreach (Tag tag in tagsCollection) { Assert.IsTrue(indexTags.ContainsKeyValue(tag.Key, tag.Value)); } } } // check the index. foreach (KeyValuePair<uint, TagsCollectionBase> pair in addedTags) { TagsCollectionBase indexTags = tagsCollectionIndex.Get(pair.Key); Assert.AreEqual(pair.Value.Count, indexTags.Count); foreach (Tag tag in pair.Value) { Assert.IsTrue(indexTags.ContainsKeyValue(tag.Key, tag.Value)); } foreach (Tag tag in indexTags) { Assert.IsTrue(pair.Value.ContainsKeyValue(tag.Key, tag.Value)); } } }
/// <summary> /// Tests adding simple tags to the given index. /// </summary> /// <param name="index"></param> /// <param name="collectionCount"></param> public static void FillIndex(ITagsCollectionIndex index, int collectionCount) { for (int i = 0; i < collectionCount; i++) { TagsCollection tagsCollection = new TagsCollection(); int tagCollectionSize = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(3) + 1; for (int idx = 0; idx < tagCollectionSize; idx++) { int tagValue = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(100); tagsCollection.Add( string.Format("key_{0}", tagValue), string.Format("value_{0}", tagValue)); } int addCount = OsmSharp.Math.Random.StaticRandomGenerator.Get().Generate(2) + 1; for (int idx = 0; idx < addCount; idx++) { uint tagsId = index.Add(tagsCollection); } } }
/// <summary> /// Calculates edge data. /// </summary> /// <param name="tagsIndex"></param> /// <param name="tags"></param> /// <param name="directionForward"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="edgeInterpreter"></param> /// <param name="intermediates"></param> /// <returns></returns> protected override LiveEdge CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsCollectionIndex tagsIndex, TagsCollectionBase tags, bool directionForward, GeoCoordinate from, GeoCoordinate to, List <GeoCoordinateSimple> intermediates) { if (edgeInterpreter == null) { throw new ArgumentNullException("edgeInterpreter"); } if (tagsIndex == null) { throw new ArgumentNullException("tagsIndex"); } if (tags == null) { throw new ArgumentNullException("tags"); } if (from == null) { throw new ArgumentNullException("from"); } if (to == null) { throw new ArgumentNullException("to"); } uint tagsId = tagsIndex.Add(tags); GeoCoordinateSimple[] coordinates = null; if (intermediates != null && intermediates.Count > 0) { // only instiate if needed. coordinates = intermediates.ToArray(); } return(new LiveEdge() { Forward = directionForward, Tags = tagsId, Distance = (float)from.DistanceEstimate(to).Value }); }
/// <summary> /// Loads the missing tiles. /// </summary> /// <param name="tile"></param> internal void LoadMissingTile(Tile tile) { if (!_loadedTiles.Contains(tile)) { // the tile was not loaded yet. TileStreamPosition meta; if (_graphTileMetas.TryGetValue(tile, out meta)) { // the meta data is available. V2RoutingDataSourceLiveEdgeSerializer.SerializableGraphTile tileData = _routingDataSourceSerializer.DeserializeTile(_stream, meta.Offset, meta.Length, _compressed); double top = tile.TopLeft.Latitude; double left = tile.TopLeft.Longitude; for (int vertexIdx = 0; vertexIdx < tileData.Ids.Length; vertexIdx++) { // resize. this.Resize(tileData.Ids[vertexIdx] + 1); // create the location and calculate lat/lon. var vertexLocation = new Location(); vertexLocation.Latitude = (float)(top - (((double)tileData.Latitude[vertexIdx] / (double)ushort.MaxValue) * tile.Box.DeltaLat)); vertexLocation.Longitude = (float)((((double)tileData.Longitude[vertexIdx] / (double)ushort.MaxValue) * tile.Box.DeltaLon) + left); _coordinates[(int)tileData.Ids[vertexIdx]] = vertexLocation; // convert the arcs. if (tileData.Arcs[vertexIdx] != null) { var arcs = new KeyValuePair <uint, Osm.Graphs.LiveEdge> [tileData.Arcs[vertexIdx].DestinationId.Length]; for (int idx = 0; idx < tileData.Arcs[vertexIdx].DestinationId.Length; idx++) { // create the tags collection. TagsCollectionBase tagsCollection = new TagsCollection(); for (int tagsIdx = 0; tagsIdx < tileData.Arcs[vertexIdx].Tags[idx].Keys.Length; tagsIdx++) { string key = tileData.StringTable[tileData.Arcs[vertexIdx].Tags[idx].Keys[tagsIdx]]; string value = tileData.StringTable[tileData.Arcs[vertexIdx].Tags[idx].Values[tagsIdx]]; tagsCollection.Add(key, value); } uint tags = _tagsIndex.Add(tagsCollection); // create the liveedge. var edge = new Osm.Graphs.LiveEdge(); edge.Forward = tileData.Arcs[vertexIdx].Forward[idx]; edge.Tags = tags; // convert the arc. arcs[idx] = new KeyValuePair <uint, Osm.Graphs.LiveEdge>( tileData.Arcs[vertexIdx].DestinationId[idx], edge); // store the target tile. var targetTile = new Tile(tileData.Arcs[vertexIdx].TileX[idx], tileData.Arcs[vertexIdx].TileY[idx], _zoom); if (!targetTile.Equals(tile) && !_loadedTiles.Contains(targetTile)) { _tilesPerVertex[tileData.Arcs[vertexIdx].DestinationId[idx]] = targetTile; } } _vertices[(int)tileData.Ids[vertexIdx]] = new Vertex() { Arcs = arcs }; } _vertexIndex.Add(new GeoCoordinate(vertexLocation.Latitude, vertexLocation.Longitude), tileData.Ids[vertexIdx]); } } _loadedTiles.Add(tile); // tile is loaded. } }
/// <summary> /// Deserializes the meta-data. /// </summary> /// <param name="stream"></param> /// <param name="tagsCollectionIndex"></param> /// <param name="size"></param> protected virtual void DeserializeTags(LimitedStream stream, long size, ITagsCollectionIndex tagsCollectionIndex) { RuntimeTypeModel typeModel = RuntimeTypeModel.Create(); typeModel.Add(typeof(SerializableTag), true); // read tags collection-count. var countBytes = new byte[4]; stream.Read(countBytes, 0, 4); int max = BitConverter.ToInt32(countBytes, 0); // serialize tags collections one-by-one. var currentTags = new List <SerializableTag>(); if (max > 0) { // keep reading until max. currentTags.AddRange(typeModel.DeserializeWithSize(stream, null, typeof(SerializableTag[])) as SerializableTag[]); // detect an empty collection at zero. if (currentTags[0].CollectionId == 1) { // no zero, there is an empty collection. tagsCollectionIndex.Add(new TagsCollection()); } while (tagsCollectionIndex.Max < max) { // try and detect an id change. bool idChanged = true; while (currentTags.Count > 0 && idChanged) { // there are tags. idChanged = false; var tagsCollection = new TagsCollection(); int index = 0; uint currentId = currentTags[index].CollectionId; // detect an empty collection in between. if (currentId > tagsCollectionIndex.Max + 1) { // it's possible there was an empty tag collection in there somewhere. tagsCollectionIndex.Add(new TagsCollection()); } tagsCollection.Add(new Tag(currentTags[index].Key, currentTags[index].Value)); index++; while (currentTags.Count > index) { // test for a different id. if (currentTags[index].CollectionId != currentId || currentTags[index].CollectionId == uint.MaxValue) { // yes! an id change was detected. idChanged = true; currentTags.RemoveRange(0, index); if (tagsCollection.Count > 0) { // there are tags. tagsCollectionIndex.AddObject(tagsCollection); } break; } tagsCollection.Add(new Tag(currentTags[index].Key, currentTags[index].Value)); index++; } } // read next block. currentTags.AddRange(typeModel.DeserializeWithSize(stream, null, typeof(SerializableTag[])) as SerializableTag[]); } } }
/// <summary> /// Adds a given way. /// </summary> /// <param name="way"></param> public override void AddWay(Way way) { if (!_preIndexMode && _waysToCache != null && _waysToCache.Contains(way.Id.Value)) { // cache this way? _dataCache.AddWay(way); } // initialize the way interpreter. if (_interpreter.EdgeInterpreter.IsRoutable(way.Tags)) { // the way is a road. if (_preIndexMode) { // index relevant and used nodes. if (way.Nodes != null) { // this way has nodes. // add new routable tags type. var routableWayTags = new TagsCollection(way.Tags); routableWayTags.RemoveAll(x => { return(!_interpreter.IsRelevantRouting(x.Key) && !Vehicle.IsRelevantForOneOrMore(x.Key)); }); _tagsIndex.Add(routableWayTags); int wayNodesCount = way.Nodes.Count; for (int idx = 0; idx < wayNodesCount; idx++) { var node = way.Nodes[idx]; if (_preIndex.Contains(node)) { // node is relevant. _relevantNodes.Add(node); } else { // node is used. _preIndex.Add(node); } } if (wayNodesCount > 0) { // first node is always relevant. _relevantNodes.Add(way.Nodes[0]); if (wayNodesCount > 1) { // last node is always relevant. _relevantNodes.Add(way.Nodes[wayNodesCount - 1]); } } } } else { // add actual edges. if (way.Nodes != null && way.Nodes.Count > 1) { // way has at least two nodes. if (this.CalculateIsTraversable(_interpreter.EdgeInterpreter, _tagsIndex, way.Tags)) { // the edge is traversable, add the edges. uint? from = this.AddRoadNode(way.Nodes[0]); long fromNodeId = way.Nodes[0]; List <long> intermediates = new List <long>(); for (int idx = 1; idx < way.Nodes.Count; idx++) { // the to-node. long currentNodeId = way.Nodes[idx]; if (!_collectIntermediates || _relevantNodes.Contains(currentNodeId) || idx == way.Nodes.Count - 1) { // node is an important node. uint?to = this.AddRoadNode(currentNodeId); long toNodeId = currentNodeId; // add the edge(s). if (from.HasValue && to.HasValue) { // add a road edge. while (from.Value == to.Value) { if (intermediates.Count > 0) { uint?dummy = this.AddRoadNode(intermediates[0]); intermediates.RemoveAt(0); if (dummy.HasValue && from.Value != dummy.Value) { this.AddRoadEdge(way.Tags, from.Value, dummy.Value, null); from = dummy; } } else { // no use to continue. break; } } // build coordinates. var intermediateCoordinates = new List <GeoCoordinateSimple>(intermediates.Count); for (int coordIdx = 0; coordIdx < intermediates.Count; coordIdx++) { ICoordinate coordinate; if (!_coordinates.TryGet(intermediates[coordIdx], out coordinate)) { break; } intermediateCoordinates.Add(new GeoCoordinateSimple() { Latitude = coordinate.Latitude, Longitude = coordinate.Longitude }); } if (intermediateCoordinates.Count == intermediates.Count && from.Value != to.Value) { // all coordinates have been found. this.AddRoadEdge(way.Tags, from.Value, to.Value, intermediateCoordinates); } } // if this way has a restriction save the collapsed nodes information. if (_restricedWays.Contains(way.Id.Value) && to.HasValue && from.HasValue) { // loop over all intermediates and save. var collapsedInfo = new KeyValuePair <KeyValuePair <long, uint>, KeyValuePair <long, uint> >( new KeyValuePair <long, uint>(fromNodeId, from.Value), new KeyValuePair <long, uint>(toNodeId, to.Value)); foreach (var intermedidate in intermediates) { _collapsedNodes[intermedidate] = collapsedInfo; } } from = to; // the to node becomes the from. intermediates.Clear(); } else { // this node is just an intermediate. intermediates.Add(currentNodeId); } } } } } } }