// Copyright 2005, 2006 - Morten Nielsen (www.iter.dk) // // This file is part of SharpMap. // SharpMap is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // SharpMap is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public License // along with SharpMap; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET: /* * Copyright (C) 2002 Urban Science Applications, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ using GeoAPI.Geometries; using GisSharpBlog.NetTopologySuite.IO; namespace SharpMap.Converters.WellKnownBinary { /// /// Converts a instance to a Well-known Binary string representation. /// /// /// The Well-known Binary Representation for (WKBGeometry) provides a portable /// representation of a value as a contiguous stream of bytes. It permits /// values to be exchanged between an ODBC client and an SQL database in binary form. /// The Well-known Binary Representation for is obtained by serializing a /// instance as a sequence of numeric types drawn from the set {Unsigned Integer, Double} and /// then serializing each numeric type as a sequence of bytes using one of two well defined, /// standard, binary representations for numeric types (NDR, XDR). The specific binary encoding /// (NDR or XDR) used for a geometry byte stream is described by a one byte tag that precedes /// the serialized bytes. The only difference between the two encodings of geometry is one of /// byte order, the XDR encoding is Big Endian, the NDR encoding is Little Endian. /// public class GeometryToWKB { //private const byte WKBByteOrder = 0; /// /// Writes a geometry to a byte array using little endian byte encoding /// /// The geometry to write /// WKB representation of the geometry public static byte[] Write(IGeometry geometry) { return Write(geometry, WkbByteOrder.Ndr); } /// /// Writes a geometry to a byte array using the specified encoding. /// /// The geometry to write /// Byte order /// WKB representation of the geometry public static byte[] Write(IGeometry geometry, WkbByteOrder wkbByteOrder) { byte[] result = null; switch (wkbByteOrder) { case WkbByteOrder.Ndr: result = new WKBWriter(ByteOrder.LittleEndian).Write(geometry); break; case WkbByteOrder.Xdr: result = new WKBWriter(ByteOrder.BigEndian).Write(geometry); break; } return result; // MemoryStream ms = new MemoryStream(); // BinaryWriter bw = new BinaryWriter(ms); // // //Write the byteorder format. // bw.Write((byte)wkbByteOrder); // // //Write the type of this geometry // WriteType(g, bw, wkbByteOrder); // // //Write the geometry // WriteGeometry(g, bw, wkbByteOrder); // // return ms.ToArray(); } // // #region Methods // /// // /// Writes the type number for this geometry. // /// // /// The geometry to determine the type of. // /// Binary Writer // /// Byte order // private static void WriteType(Geometry geometry, BinaryWriter bWriter, WkbByteOrder byteorder) // { // //Determine the type of the geometry. // switch (geometry.GetType().FullName) // { // //Points are type 1. // case "SharpMap.Geometries.Point": // WriteUInt32((uint)WKBGeometryType.wkbPoint, bWriter, byteorder); // break; // //Linestrings are type 2. // case "SharpMap.Geometries.LineString": // WriteUInt32((uint)WKBGeometryType.wkbLineString, bWriter, byteorder); // break; // //Polygons are type 3. // case "SharpMap.Geometries.Polygon": // WriteUInt32((uint)WKBGeometryType.wkbPolygon, bWriter, byteorder); // break; // //Mulitpoints are type 4. // case "SharpMap.Geometries.MultiPoint": // WriteUInt32((uint)WKBGeometryType.wkbMultiPoint, bWriter, byteorder); // break; // //Multilinestrings are type 5. // case "SharpMap.Geometries.MultiLineString": // WriteUInt32((uint)WKBGeometryType.wkbMultiLineString, bWriter, byteorder); // break; // //Multipolygons are type 6. // case "SharpMap.Geometries.MultiPolygon": // WriteUInt32((uint)WKBGeometryType.wkbMultiPolygon, bWriter, byteorder); // break; // //Geometrycollections are type 7. // case "SharpMap.Geometries.GeometryCollection": // WriteUInt32((uint)WKBGeometryType.wkbGeometryCollection, bWriter, byteorder); // break; // //If the type is not of the above 7 throw an exception. // default: // throw new ArgumentException("Invalid Geometry Type"); // } // } // // /// // /// Writes the geometry to the binary writer. // /// // /// The geometry to be written. // /// // /// Byte order // private static void WriteGeometry(Geometry geometry, BinaryWriter bWriter, WkbByteOrder byteorder) // { // switch (geometry.GetType().FullName) // { // //Write the point. // case "SharpMap.Geometries.Point": // WritePoint((Point)geometry, bWriter, byteorder); // break; // case "SharpMap.Geometries.LineString": // LineString ls = (LineString)geometry; // WriteLineString(ls, bWriter, byteorder); // break; // case "SharpMap.Geometries.Polygon": // WritePolygon((Polygon)geometry, bWriter, byteorder); // break; // //Write the Multipoint. // case "SharpMap.Geometries.MultiPoint": // WriteMultiPoint((MultiPoint)geometry, bWriter,byteorder); // break; // //Write the Multilinestring. // case "SharpMap.Geometries.MultiLineString": // WriteMultiLineString((MultiLineString)geometry, bWriter,byteorder); // break; // //Write the Multipolygon. // case "SharpMap.Geometries.MultiPolygon": // WriteMultiPolygon((MultiPolygon)geometry, bWriter,byteorder); // break; // //Write the Geometrycollection. // case "SharpMap.Geometries.GeometryCollection": // WriteGeometryCollection((GeometryCollection)geometry, bWriter,byteorder); // break; // //If the type is not of the above 7 throw an exception. // default: // throw new ArgumentException("Invalid Geometry Type"); // } // } // // /// // /// Writes a point. // /// // /// The point to be written. // /// Stream to write to. // /// Byte order // private static void WritePoint(Point point, BinaryWriter bWriter, WkbByteOrder byteorder) // { // //Write the x coordinate. // WriteDouble(point.X, bWriter, byteorder); // //Write the y coordinate. // WriteDouble(point.Y, bWriter, byteorder); // } // // // // /// // /// Writes a linestring. // /// // /// The linestring to be written. // /// Stream to write to. // /// Byte order // private static void WriteLineString(LineString ls, BinaryWriter bWriter, WkbByteOrder byteorder) // { // //Write the number of points in this linestring. // WriteUInt32((uint)ls.Vertices.Count,bWriter,byteorder); // // //Loop on each vertices. // foreach (Point p in ls.Vertices) // WritePoint(p, bWriter, byteorder); // } // // // /// // /// Writes a polygon. // /// // /// The polygon to be written. // /// Stream to write to. // /// Byte order // private static void WritePolygon(Polygon poly, BinaryWriter bWriter, WkbByteOrder byteorder) // { // //Get the number of rings in this polygon. // int numRings = poly.InteriorRings.Count + 1; // // //Write the number of rings to the stream (add one for the shell) // WriteUInt32((uint)numRings, bWriter, byteorder); // // //Write the exterior of this polygon. // WriteLineString((LineString)poly.ExteriorRing, bWriter, byteorder); // // //Loop on the number of rings - 1 because we already wrote the shell. // foreach (LinearRing lr in poly.InteriorRings) // //Write the (lineString)LinearRing. // WriteLineString((LineString)lr, bWriter, byteorder); // } // // /// // /// Writes a multipoint. // /// // /// The multipoint to be written. // /// Stream to write to. // /// Byte order // private static void WriteMultiPoint(MultiPoint mp, BinaryWriter bWriter, WkbByteOrder byteorder) // { // //Write the number of points. // WriteUInt32((uint)mp.Points.Count, bWriter, byteorder); // // //Loop on the number of points. // foreach (Point p in mp.Points) // { // //Write Points Header // bWriter.Write((byte)byteorder); // WriteUInt32((uint)WKBGeometryType.wkbPoint, bWriter, byteorder); // //Write each point. // WritePoint((Point)p, bWriter, byteorder); // } // } // // /// // /// Writes a multilinestring. // /// // /// The multilinestring to be written. // /// Stream to write to. // /// Byte order // private static void WriteMultiLineString(MultiLineString mls, BinaryWriter bWriter, WkbByteOrder byteorder) // { // //Write the number of linestrings. // WriteUInt32((uint)mls.LineStrings.Count, bWriter, byteorder); // // //Loop on the number of linestrings. // foreach (LineString ls in mls.LineStrings) // { // //Write LineString Header // bWriter.Write((byte)byteorder); // WriteUInt32((uint)WKBGeometryType.wkbLineString, bWriter, byteorder); // //Write each linestring. // WriteLineString(ls, bWriter, byteorder); // } // } // // /// // /// Writes a multipolygon. // /// // /// The mulitpolygon to be written. // /// Stream to write to. // /// Byte order // private static void WriteMultiPolygon(MultiPolygon mp, BinaryWriter bWriter, WkbByteOrder byteorder) // { // //Write the number of polygons. // WriteUInt32((uint)mp.Polygons.Count, bWriter, byteorder); // // //Loop on the number of polygons. // foreach (Polygon poly in mp.Polygons) // { // //Write polygon header // bWriter.Write((byte)byteorder); // WriteUInt32((uint)WKBGeometryType.wkbPolygon, bWriter, byteorder); // //Write each polygon. // WritePolygon(poly, bWriter, byteorder); // } // } // // // /// // /// Writes a geometrycollection. // /// // /// The geometrycollection to be written. // /// Stream to write to. // /// Byte order // private static void WriteGeometryCollection(GeometryCollection gc, BinaryWriter bWriter, WkbByteOrder byteorder) // { // //Get the number of geometries in this geometrycollection. // int numGeometries = gc.NumGeometries; // // //Write the number of geometries. // WriteUInt32((uint)numGeometries, bWriter, byteorder); // // //Loop on the number of geometries. // for (int i = 0; i < numGeometries; i++) // { // //Write the byte-order format of the following geometry. // bWriter.Write((byte)byteorder); // //Write the type of each geometry. // WriteType(gc[i], bWriter, byteorder); // //Write each geometry. // WriteGeometry(gc[i], bWriter, byteorder); // } // } // #endregion // // /// // /// Writes an unsigned integer to the binarywriter using the specified encoding // /// // /// Value to write // /// Binary Writer // /// byteorder // private static void WriteUInt32(UInt32 value, BinaryWriter writer, WkbByteOrder byteOrder) // { // if (byteOrder == WkbByteOrder.Xdr) // { // byte[] bytes = BitConverter.GetBytes(value); // Array.Reverse(bytes); // writer.Write(BitConverter.ToUInt32(bytes, 0)); // } // else // writer.Write(value); // } // // /// // /// Writes a double to the binarywriter using the specified encoding // /// // /// Value to write // /// Binary Writer // /// byteorder // private static void WriteDouble(double value, BinaryWriter writer, WkbByteOrder byteOrder) // { // if (byteOrder == WkbByteOrder.Xdr) // { // byte[] bytes = BitConverter.GetBytes(value); // Array.Reverse(bytes); // writer.Write(BitConverter.ToDouble(bytes, 0)); // } // else // writer.Write(value); // } } }