/// <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));
                        });
                        if (_storeTags)
                        {
                            _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);
                                }
                            }
                        }
                    }
                }
            }
        }