/// <summary>
        /// Generates GeoJson for the given geometry collection.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="geometryCollection"></param>
        internal static void Write(JsonWriter writer, GeometryCollection geometryCollection)
        {
            if (writer == null) { throw new ArgumentNullException("writer"); }
            if (geometryCollection == null) { throw new ArgumentNullException("geometryCollection"); }

            writer.WriteStartObject();
            writer.WritePropertyName("type");
            writer.WriteValue("GeometryCollection");
            writer.WritePropertyName("geometries");
            writer.WriteStartArray();
            foreach (var geometry in geometryCollection)
            {
                GeoJsonConverter.Write(writer, geometry);
            }
            writer.WriteEndArray();
            writer.WriteEndObject();
        }
        /// <summary>
        /// Generates GeoJson for the given geometry.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="geometry"></param>
        /// <returns></returns>
        internal static void Write(JsonWriter writer, Polygon geometry)
        {
            if (writer == null) { throw new ArgumentNullException("writer"); }
            if (geometry == null) { throw new ArgumentNullException("geometry"); }

            writer.WriteStartObject();
            writer.WritePropertyName("type");
            writer.WriteValue("Polygon");
            writer.WritePropertyName("coordinates");
            writer.WriteStartArray();
            writer.WriteStartArray();
            foreach (var coordinate in geometry.Ring.Coordinates)
            {
                writer.WriteStartArray();
                writer.WriteValue(coordinate.Longitude);
                writer.WriteValue(coordinate.Latitude);
                writer.WriteEndArray();
            }
            writer.WriteEndArray();
            foreach(var hole in geometry.Holes)
            {
                writer.WriteStartArray();
                foreach (var coordinate in hole.Coordinates)
                {
                    writer.WriteStartArray();
                    writer.WriteValue(coordinate.Longitude);
                    writer.WriteValue(coordinate.Latitude);
                    writer.WriteEndArray();
                }
                writer.WriteEndArray();
            }
            writer.WriteEndArray();
            writer.WriteEndObject();
        }
        /// <summary>
        /// Generates GeoJson for the given geometry.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="geometry"></param>
        /// <returns></returns>
        internal static void Write(JsonWriter writer, Point geometry)
        {
            if (writer == null) { throw new ArgumentNullException("writer"); }
            if (geometry == null) { throw new ArgumentNullException("geometry"); }

            writer.WriteStartObject();
            writer.WritePropertyName("type");
            writer.WriteValue("Point");
            writer.WritePropertyName("coordinates");
            writer.WriteStartArray();
            writer.WriteValue(geometry.Coordinate.Longitude);
            writer.WriteValue(geometry.Coordinate.Latitude);
            writer.WriteEndArray();
            writer.WriteEndObject();
        }
        /// <summary>
        /// Generates GeoJson for the given geometry collection.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="geometryCollection"></param>
        internal static void Write(JsonWriter writer, MultiLineString geometryCollection)
        {
            if (writer == null) { throw new ArgumentNullException("writer"); }
            if (geometryCollection == null) { throw new ArgumentNullException("geometryCollection"); }

            writer.WriteStartObject();
            writer.WritePropertyName("type");
            writer.WriteValue("MultiLineString");
            writer.WritePropertyName("coordinates");
            writer.WriteStartArray();
            foreach (var geometry in geometryCollection)
            {
                writer.WriteStartArray();
                foreach (var coordinate in geometry.Coordinates)
                {
                    writer.WriteStartArray();
                    writer.WriteValue(coordinate.Longitude);
                    writer.WriteValue(coordinate.Latitude);
                    writer.WriteEndArray();
                }
                writer.WriteEndArray();
            }
            writer.WriteEndArray();
            writer.WriteEndObject();
        }
        /// <summary>
        /// Generates GeoJson for the given attribute collection.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="attributes"></param>
        internal static void Write(JsonWriter writer, GeometryAttributeCollection attributes)
        {
            if (writer == null) { throw new ArgumentNullException("writer"); }
            if (attributes == null) { throw new ArgumentNullException("attributes"); }

            writer.WriteStartObject();
            foreach (var attribute in attributes)
            {
                writer.WritePropertyName(attribute.Key);
                writer.WriteValue(attribute.Value);
            }
            writer.WriteEndObject();
        }
        /// <summary>
        /// Generates GeoJson for the given feature.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="feature"></param>
        internal static void Write(JsonWriter writer, Feature feature)
        {
            if (writer == null) { throw new ArgumentNullException("writer"); }
            if (feature == null) { throw new ArgumentNullException("feature"); }

            writer.WriteStartObject();
            writer.WritePropertyName("type");
            writer.WriteValue("Feature");
            writer.WritePropertyName("properties");
            GeoJsonConverter.Write(writer, feature.Attributes);
            writer.WritePropertyName("geometry");
            GeoJsonConverter.Write(writer, feature.Geometry);
            writer.WriteEndObject();
        }
        /// <summary>
        /// Generates GeoJson for the given feature collection.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="featureCollection"></param>
        internal static void Write(JsonWriter writer, FeatureCollection featureCollection)
        {
            if (writer == null) { throw new ArgumentNullException("writer"); }
            if (featureCollection == null) { throw new ArgumentNullException("featureCollection"); }

            writer.WriteStartObject();
            writer.WritePropertyName("type");
            writer.WriteValue("FeatureCollection");
            writer.WritePropertyName("features");
            writer.WriteStartArray();
            foreach(var feature in featureCollection)
            {
                GeoJsonConverter.Write(writer, feature);
            }
            writer.WriteEndArray();
            writer.WriteEndObject();
        }
        /// <summary>
        /// Generates GeoJson for the given attribute collection.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="attributes"></param>
        internal static void Write(JsonWriter writer, GeometryAttributeCollection attributes)
        {
            if (writer == null) { throw new ArgumentNullException("writer"); }
            if (attributes == null) { throw new ArgumentNullException("attributes"); }

            writer.WriteStartObject();
            var keys = new HashSet<string>();
            foreach (var attribute in attributes)
            {
                if (!keys.Contains(attribute.Key))
                {
                    writer.WritePropertyName(attribute.Key);
                    writer.WriteValue(attribute.Value);
                    keys.Add(attribute.Key);
                }
            }
            writer.WriteEndObject();
        }