using System;
using System.Globalization;
using System.IO;
using System.Xml;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Utilities;
namespace GisSharpBlog.NetTopologySuite.IO.GML2
{
///
/// Writes the GML representation of the features of NetTopologySuite model.
/// Uses GML 2.1.1 Geometry.xsd schema for base for features.
///
/// Thanks to rstuven for improvements :)
///
///
public class GMLWriter
{
private const int InitValue = 150;
private const int CoordSize = 200;
///
/// Returns an XmlReader with feature informations.
/// Use XmlDocument.Load(XmlReader) for obtain a XmlDocument to work.
///
///
///
public XmlReader Write(IGeometry geometry)
{
byte[] data = GetBytes(geometry);
using (Stream stream = new MemoryStream(data))
{
Write(geometry, stream);
}
Stream outStream = new MemoryStream(data);
return new XmlTextReader(outStream);
}
///
/// Writes a GML feature into a generic Stream, such a FileStream or other streams.
///
///
///
public void Write(IGeometry geometry, Stream stream)
{
XmlTextWriter writer = new XmlTextWriter(stream, null);
writer.Namespaces = true;
writer.WriteStartElement(GMLElements.gmlPrefix, "GML", GMLElements.gmlNS);
writer.Formatting = Formatting.Indented;
Write(geometry, writer);
writer.WriteEndElement();
writer.Close();
}
///
/// Formatter for double values of coordinates
///
protected static NumberFormatInfo NumberFormatter
{
get
{
return Global.GetNfi();
}
}
///
///
///
///
///
protected void Write(ICoordinate coordinate, XmlTextWriter writer)
{
writer.WriteStartElement(GMLElements.gmlPrefix, "coord", GMLElements.gmlNS);
writer.WriteElementString(GMLElements.gmlPrefix, "X", GMLElements.gmlNS, coordinate.X.ToString("g", NumberFormatter));
writer.WriteElementString(GMLElements.gmlPrefix, "Y", GMLElements.gmlNS, coordinate.Y.ToString("g", NumberFormatter));
writer.WriteEndElement();
}
///
///
///
///
///
protected void Write(ICoordinate[] coordinates, XmlTextWriter writer)
{
foreach (ICoordinate coord in coordinates)
{
Write(coord, writer);
}
}
///
///
///
///
///
protected void Write(IGeometry geometry, XmlTextWriter writer)
{
if (geometry is IPoint)
{
Write(geometry as IPoint, writer);
}
else if (geometry is ILineString)
{
Write(geometry as ILineString, writer);
}
else if (geometry is IPolygon)
{
Write(geometry as IPolygon, writer);
}
else if (geometry is IMultiPoint)
{
Write(geometry as IMultiPoint, writer);
}
else if (geometry is IMultiLineString)
{
Write(geometry as IMultiLineString, writer);
}
else if (geometry is IMultiPolygon)
{
Write(geometry as IMultiPolygon, writer);
}
else if (geometry is IGeometryCollection)
{
Write(geometry as IGeometryCollection, writer);
}
else
{
throw new ArgumentException("Geometry not recognized: " + geometry.ToString());
}
}
///
///
///
///
///
protected void Write(IPoint point, XmlTextWriter writer)
{
writer.WriteStartElement("Point", GMLElements.gmlNS);
Write(point.Coordinate, writer);
writer.WriteEndElement();
}
///
///
///
///
///
protected void Write(ILineString lineString, XmlTextWriter writer)
{
writer.WriteStartElement("LineString", GMLElements.gmlNS);
Write(lineString.Coordinates, writer);
writer.WriteEndElement();
}
///
///
///
///
///
protected void Write(ILinearRing linearRing, XmlTextWriter writer)
{
writer.WriteStartElement("LinearRing", GMLElements.gmlNS);
Write(linearRing.Coordinates, writer);
writer.WriteEndElement();
}
///
///
///
///
///
protected void Write(IPolygon polygon, XmlTextWriter writer)
{
writer.WriteStartElement("Polygon", GMLElements.gmlNS);
writer.WriteStartElement("outerBoundaryIs", GMLElements.gmlNS);
Write(polygon.ExteriorRing as ILinearRing, writer);
writer.WriteEndElement();
for (int i = 0; i < polygon.NumInteriorRings; i++)
{
writer.WriteStartElement("innerBoundaryIs", GMLElements.gmlNS);
Write(polygon.InteriorRings[i] as ILinearRing, writer);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
///
///
///
///
///
protected void Write(IMultiPoint multiPoint, XmlTextWriter writer)
{
writer.WriteStartElement("MultiPoint", GMLElements.gmlNS);
for (int i = 0; i < multiPoint.NumGeometries; i++)
{
writer.WriteStartElement("pointMember", GMLElements.gmlNS);
Write(multiPoint.Geometries[i] as IPoint, writer);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
///
///
///
///
///
protected void Write(IMultiLineString multiLineString, XmlTextWriter writer)
{
writer.WriteStartElement("MultiLineString", GMLElements.gmlNS);
for (int i = 0; i < multiLineString.NumGeometries; i++)
{
writer.WriteStartElement("lineStringMember", GMLElements.gmlNS);
Write(multiLineString.Geometries[i] as ILineString, writer);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
///
///
///
///
///
protected void Write(IMultiPolygon multiPolygon, XmlTextWriter writer)
{
writer.WriteStartElement("MultiPolygon", GMLElements.gmlNS);
for (int i = 0; i < multiPolygon.NumGeometries; i++)
{
writer.WriteStartElement("polygonMember", GMLElements.gmlNS);
Write(multiPolygon.Geometries[i] as IPolygon, writer);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
///
///
///
///
///
protected void Write(IGeometryCollection geometryCollection, XmlTextWriter writer)
{
writer.WriteStartElement("MultiGeometry", GMLElements.gmlNS);
for (int i = 0; i < geometryCollection.NumGeometries; i++)
{
writer.WriteStartElement("geometryMember", GMLElements.gmlNS);
Write(geometryCollection.Geometries[i] as IGeometry, writer);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
///
/// Sets corrent length for Byte Stream.
///
///
///
protected byte[] GetBytes(IGeometry geometry)
{
if (geometry is IPoint)
{
return new byte[SetByteStreamLength(geometry as IPoint)];
}
else if (geometry is ILineString)
{
return new byte[SetByteStreamLength(geometry as ILineString)];
}
else if (geometry is IPolygon)
{
return new byte[SetByteStreamLength(geometry as IPolygon)];
}
else if (geometry is IMultiPoint)
{
return new byte[SetByteStreamLength(geometry as IMultiPoint)];
}
else if (geometry is IMultiLineString)
{
return new byte[SetByteStreamLength(geometry as IMultiLineString)];
}
else if (geometry is IMultiPolygon)
{
return new byte[SetByteStreamLength(geometry as IMultiPolygon)];
}
else if (geometry is IGeometryCollection)
{
return new byte[SetByteStreamLength(geometry as IGeometryCollection)];
}
else
{
throw new ArgumentException("ShouldNeverReachHere");
}
}
///
/// Sets corrent length for Byte Stream.
///
///
///
protected int SetByteStreamLength(IGeometry geometry)
{
if (geometry is IPoint)
{
return SetByteStreamLength(geometry as IPoint);
}
else if (geometry is ILineString)
{
return SetByteStreamLength(geometry as ILineString);
}
else if (geometry is IPolygon)
{
return SetByteStreamLength(geometry as IPolygon);
}
else if (geometry is IMultiPoint)
{
return SetByteStreamLength(geometry as IMultiPoint);
}
else if (geometry is IMultiLineString)
{
return SetByteStreamLength(geometry as IMultiLineString);
}
else if (geometry is IMultiPolygon)
{
return SetByteStreamLength(geometry as IMultiPolygon);
}
else if (geometry is IGeometryCollection)
{
return SetByteStreamLength(geometry as IGeometryCollection);
}
else
{
throw new ArgumentException("ShouldNeverReachHere");
}
}
///
///
///
///
///
protected int SetByteStreamLength(IGeometryCollection geometryCollection)
{
int count = InitValue;
foreach (IGeometry g in geometryCollection.Geometries)
{
count += SetByteStreamLength(g);
}
return count;
}
///
///
///
///
///
protected int SetByteStreamLength(IMultiPolygon multiPolygon)
{
int count = InitValue;
foreach (IPolygon p in multiPolygon.Geometries)
{
count += SetByteStreamLength(p);
}
return count;
}
///
///
///
///
///
protected int SetByteStreamLength(IMultiLineString multiLineString)
{
int count = InitValue;
foreach (ILineString ls in multiLineString.Geometries)
{
count += SetByteStreamLength(ls);
}
return count;
}
///
///
///
///
///
protected int SetByteStreamLength(IMultiPoint multiPoint)
{
int count = InitValue;
foreach (IPoint p in multiPoint.Geometries)
{
count += SetByteStreamLength(p);
}
return count;
}
///
///
///
///
///
protected int SetByteStreamLength(IPolygon polygon)
{
int count = InitValue;
count += polygon.NumPoints*CoordSize;
return count;
}
///
///
///
///
///
protected int SetByteStreamLength(ILineString lineString)
{
int count = InitValue;
count += lineString.NumPoints*CoordSize;
return count;
}
///
///
///
///
///
protected int SetByteStreamLength(IPoint point)
{
return InitValue + CoordSize;
}
}
}