/// <summary>
 /// Generates an immidiate turn.
 /// </summary>
 /// <param name="instruction"></param>
 /// <param name="firstStreetCountTo"></param>
 /// <param name="firstStreetTo"></param>
 /// <param name="firstDirection"></param>
 /// <param name="secondStreetTo"></param>
 /// <param name="secondDirection"></param>
 /// <returns></returns>
 public Instruction GenerateImmidiateTurn(Instruction instruction, 
     int firstStreetCountTo, 
     List<KeyValuePair<string, string>> firstStreetTo, 
     OsmSharp.Tools.Math.Geo.Meta.RelativeDirection firstDirection, 
     List<KeyValuePair<string, string>> secondStreetTo, 
     RelativeDirection secondDirection)
 {
     instruction.Text = string.Format("GenerateImmidiateTurn:{0}_{1}_{2}_{3}",
                                      firstStreetCountTo, firstDirection,
                                      firstDirection.ToString(),
                                      secondDirection.ToString());
     return instruction;
 }
        /// <summary>
        /// Generates an immidiate turn.
        /// </summary>
        /// <param name="instruction"></param>
        /// <param name="firstStreetCountTo"></param>
        /// <param name="firstStreetTo"></param>
        /// <param name="firstDirection"></param>
        /// <param name="secondStreetTo"></param>
        /// <param name="secondDirection"></param>
        /// <returns></returns>
        public Instruction GenerateImmidiateTurn(Instruction instruction,
            int firstStreetCountTo,
            TagsCollection firstStreetTo,
            OsmSharp.Math.Geo.Meta.RelativeDirection firstDirection,
            TagsCollection secondStreetTo,
            RelativeDirection secondDirection)
        {
            instruction.Text = string.Format("GenerateImmidiateTurn:{0}_{1}_{2}_{3}",
                                             firstStreetCountTo, firstDirection,
                                             firstDirection.ToString(),
                                             secondDirection.ToString());

            instruction.Extras = new Dictionary<string, object>();
            instruction.Extras.Add("firstStreetCountTo", firstStreetCountTo);
            instruction.Extras.Add("firstStreetTo", firstStreetTo);
            instruction.Extras.Add("firstDirection", firstDirection);
            instruction.Extras.Add("secondStreetTo", secondStreetTo);
            instruction.Extras.Add("secondDirection", secondDirection);

            return instruction;
        }
        /// <summary>
        /// Converts the given OsmSharp feature into an NTS feature.
        /// </summary>
        /// <param name="feature"></param>
        /// <returns></returns>
        public static Feature Convert(OsmSharp.Geo.Features.Feature feature)
        {
            if (feature == null) { throw new ArgumentNullException("feature"); }

            var geometryFactory = new NetTopologySuite.Geometries.GeometryFactory();
            if(feature.Geometry is OsmSharp.Geo.Geometries.Polygon)
            { // a polygon.
                var polygon = (feature.Geometry as OsmSharp.Geo.Geometries.Polygon);
                var holes = polygon.Holes.Select((hole) => {
                    return (ILinearRing)geometryFactory.CreateLinearRing(hole.Coordinates.Select((coordinate) => {
                        return new Coordinate(coordinate.Longitude, coordinate.Latitude);
                    }).ToArray());
                }).ToArray();
                var shell = geometryFactory.CreateLinearRing(polygon.Ring.Coordinates.Select((coordinate) => {
                    return new Coordinate(coordinate.Longitude, coordinate.Latitude);
                }).ToArray());
                return new Feature(geometryFactory.CreatePolygon(shell, holes),
                    OsmSharpToNTSFeatureConvertor.Convert(feature.Attributes));
            }
            else if (feature.Geometry is OsmSharp.Geo.Geometries.LineairRing)
            { // a lineair ring.
                var lineairRing = (feature.Geometry as OsmSharp.Geo.Geometries.LineairRing);
                var coordinates = lineairRing.Coordinates.Select((coordinate) => {
                    return new Coordinate(coordinate.Longitude, coordinate.Latitude);
                });
                return new Feature(geometryFactory.CreateLinearRing(coordinates.ToArray()),
                    OsmSharpToNTSFeatureConvertor.Convert(feature.Attributes));
            }
            else if (feature.Geometry is OsmSharp.Geo.Geometries.LineString)
            { // a line string.
                var lineString = (feature.Geometry as OsmSharp.Geo.Geometries.LineString);
                var coordinates = lineString.Coordinates.Select((coordinate) =>
                {
                    return new Coordinate(coordinate.Longitude, coordinate.Latitude);
                });
                return new Feature(geometryFactory.CreateLineString(coordinates.ToArray()),
                    OsmSharpToNTSFeatureConvertor.Convert(feature.Attributes));
            }
            else if (feature.Geometry is OsmSharp.Geo.Geometries.Point)
            { // a point.
                var point = (feature.Geometry as OsmSharp.Geo.Geometries.Point);
                return new Feature(geometryFactory.CreatePoint(new Coordinate(point.Coordinate.Longitude, point.Coordinate.Latitude)),
                    OsmSharpToNTSFeatureConvertor.Convert(feature.Attributes));
            }
            else if (feature.Geometry is OsmSharp.Geo.Geometries.MultiLineString)
            { // a multi line string.
                throw new NotSupportedException("A MultiLineString is not supported.");
            }
            else if (feature.Geometry is OsmSharp.Geo.Geometries.MultiPoint)
            { // a multi point.
                throw new NotSupportedException("A MultiPoint is not supported.");
            }
            else if (feature.Geometry is OsmSharp.Geo.Geometries.MultiPolygon)
            { // a multi polygon.
                throw new NotSupportedException("A MultiPolygon is not supported.");
            }
            throw new ArgumentOutOfRangeException("Geometry not recognized: {0}", feature.ToString());
        }