Ejemplo n.º 1
0
 /// <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);
        }
Ejemplo n.º 3
0
        ///// <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
            });
        }
Ejemplo n.º 4
0
        /// <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
            });
        }
Ejemplo n.º 5
0
        /// <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));
        }
Ejemplo n.º 6
0
        /// <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));
                }
            }
        }
Ejemplo n.º 8
0
 /// <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);
         }
     }
 }
Ejemplo n.º 9
0
 /// <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);
         }
     }
 }
Ejemplo n.º 10
0
        /// <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
            });
        }
Ejemplo n.º 11
0
        /// <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.
            }
        }
Ejemplo n.º 12
0
        /// <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[]);
                }
            }
        }
Ejemplo n.º 13
0
        /// <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);
                                }
                            }
                        }
                    }
                }
            }
        }