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; } } }