// 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 Well-known Binary representations to a instance.
///
///
/// 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 GeometryFromWKB
{
///
/// Creates a from the supplied byte[] containing the Well-known Binary representation.
///
/// byte[] containing the Well-known Binary representation.
/// A bases on the supplied Well-known Binary representation.
public static IGeometry Parse(byte[] bytes)
{
return new WKBReader().Read(bytes);
// // Create a memory stream using the suppiled byte array.
// using (MemoryStream ms = new MemoryStream(bytes))
// {
// // Create a new binary reader using the newly created memorystream.
// using (BinaryReader reader = new BinaryReader(ms))
// {
// // Call the main create function.
// return Parse(reader);
// }
// }
}
///
/// Creates a based on the Well-known binary representation.
///
/// A BinaryReader used to read the Well-known binary representation.
/// A based on the Well-known binary representation.
// public static Geometry Parse(BinaryReader reader)
// {
// // Get the first byte in the array. This specifies if the WKB is in
// // XDR (big-endian) format of NDR (little-endian) format.
// byte byteOrder = reader.ReadByte();
//
// if (!Enum.IsDefined(typeof(WkbByteOrder), byteOrder))
// {
// throw new ArgumentException("Byte order not recognized");
// }
//
// // Get the type of this geometry.
// uint type = (uint)ReadUInt32(reader, (WkbByteOrder)byteOrder);
//
// if (!Enum.IsDefined(typeof(WKBGeometryType), type))
// throw new ArgumentException("Geometry type not recognized");
//
// switch((WKBGeometryType)type)
// {
// case WKBGeometryType.wkbPoint:
// return CreateWKBPoint(reader, (WkbByteOrder)byteOrder);
//
// case WKBGeometryType.wkbLineString:
// return CreateWKBLineString(reader, (WkbByteOrder)byteOrder);
//
// case WKBGeometryType.wkbPolygon:
// return CreateWKBPolygon(reader, (WkbByteOrder)byteOrder);
//
// case WKBGeometryType.wkbMultiPoint:
// return CreateWKBMultiPoint(reader, (WkbByteOrder)byteOrder);
//
// case WKBGeometryType.wkbMultiLineString:
// return CreateWKBMultiLineString(reader, (WkbByteOrder)byteOrder);
//
// case WKBGeometryType.wkbMultiPolygon:
// return CreateWKBMultiPolygon(reader, (WkbByteOrder)byteOrder);
//
// case WKBGeometryType.wkbGeometryCollection:
// return CreateWKBGeometryCollection(reader, (WkbByteOrder)byteOrder);
//
// default:
// throw new NotSupportedException("Geometry type '" + type.ToString() + "' not supported");
// }
// }
//
// private static Point CreateWKBPoint(BinaryReader reader, WkbByteOrder byteOrder)
// {
// // Create and return the point.
// return new Point(ReadDouble(reader, byteOrder), ReadDouble(reader, byteOrder));
// }
//
// private static Point[] ReadCoordinates(BinaryReader reader, WkbByteOrder byteOrder)
// {
// // Get the number of points in this linestring.
// int numPoints = (int)ReadUInt32(reader, byteOrder);
//
// // Create a new array of coordinates.
// Point[] coords = new Point[numPoints];
//
// // Loop on the number of points in the ring.
// for (int i = 0; i < numPoints; i++)
// {
// // Add the coordinate.
// coords[i] = new Point(ReadDouble(reader, byteOrder), ReadDouble(reader, byteOrder));
// }
// return coords;
// }
//
// private static LineString CreateWKBLineString(BinaryReader reader, WkbByteOrder byteOrder)
// {
// SharpMap.Geometries.LineString l = new SharpMap.Geometries.LineString();
// //l.Vertices.AddRange(ReadCoordinates(reader, byteOrder));
// Point[] arrPoint = ReadCoordinates(reader, byteOrder);
// for (int i = 0; i < arrPoint.Length; i++)
// l.Vertices.Add(arrPoint[i]);
//
// return l;
//
//
// }
//
// private static LinearRing CreateWKBLinearRing(BinaryReader reader, WkbByteOrder byteOrder)
// {
// SharpMap.Geometries.LinearRing l = new SharpMap.Geometries.LinearRing();
// //l.Vertices.AddRange(ReadCoordinates(reader, byteOrder));
// Point[] arrPoint = ReadCoordinates(reader, byteOrder);
// for (int i = 0; i < arrPoint.Length; i++)
// l.Vertices.Add(arrPoint[i]);
//
// //if polygon isn't closed, add the first point to the end (this shouldn't occur for correct WKB data)
// if (l.Vertices[0].X != l.Vertices[l.Vertices.Count - 1].X || l.Vertices[0].Y != l.Vertices[l.Vertices.Count - 1].Y)
// l.Vertices.Add(new Point(l.Vertices[0].X, l.Vertices[0].Y));
// return l;
// }
//
// private static Polygon CreateWKBPolygon(BinaryReader reader, WkbByteOrder byteOrder)
// {
// // Get the Number of rings in this Polygon.
// int numRings = (int)ReadUInt32(reader, byteOrder);
//
// Debug.Assert(numRings >= 1, "Number of rings in polygon must be 1 or more.");
//
// Polygon shell = new Polygon(CreateWKBLinearRing(reader, byteOrder));
//
// // Create a new array of linearrings for the interior rings.
// for (int i = 0; i < (numRings - 1); i++)
// shell.InteriorRings.Add(CreateWKBLinearRing(reader, byteOrder));
//
// // Create and return the Poylgon.
// return shell;
// }
//
// private static MultiPoint CreateWKBMultiPoint(BinaryReader reader, WkbByteOrder byteOrder)
// {
// // Get the number of points in this multipoint.
// int numPoints = (int)ReadUInt32(reader, byteOrder);
//
// // Create a new array for the points.
// MultiPoint points = new MultiPoint();
//
// // Loop on the number of points.
// for (int i = 0; i < numPoints; i++)
// {
// // Read point header
// reader.ReadByte();
// ReadUInt32(reader, byteOrder);
//
// // TODO: Validate type
//
// // Create the next point and add it to the point array.
// points.Points.Add(CreateWKBPoint(reader, byteOrder));
// }
// return points;
// }
//
// private static MultiLineString CreateWKBMultiLineString(BinaryReader reader, WkbByteOrder byteOrder)
// {
// // Get the number of linestrings in this multilinestring.
// int numLineStrings = (int)ReadUInt32(reader, byteOrder);
//
// // Create a new array for the linestrings .
// MultiLineString mline = new MultiLineString();
//
// // Loop on the number of linestrings.
// for (int i = 0; i < numLineStrings; i++)
// {
// // Read linestring header
// reader.ReadByte();
// ReadUInt32(reader, byteOrder);
//
// // Create the next linestring and add it to the array.
// mline.LineStrings.Add(CreateWKBLineString(reader, byteOrder));
// }
//
// // Create and return the MultiLineString.
// return mline;
// }
//
// private static MultiPolygon CreateWKBMultiPolygon(BinaryReader reader, WkbByteOrder byteOrder)
// {
// // Get the number of Polygons.
// int numPolygons = (int)ReadUInt32(reader, byteOrder);
//
// // Create a new array for the Polygons.
// MultiPolygon polygons = new MultiPolygon();
//
// // Loop on the number of polygons.
// for (int i = 0; i < numPolygons; i++)
// {
// // read polygon header
// reader.ReadByte();
// ReadUInt32(reader, byteOrder);
//
// // TODO: Validate type
//
// // Create the next polygon and add it to the array.
// polygons.Polygons.Add(CreateWKBPolygon(reader, byteOrder));
// }
//
// //Create and return the MultiPolygon.
// return polygons;
// }
//
// private static Geometry CreateWKBGeometryCollection(BinaryReader reader, WkbByteOrder byteOrder)
// {
// // The next byte in the array tells the number of geometries in this collection.
// int numGeometries = (int)ReadUInt32(reader, byteOrder);
//
// // Create a new array for the geometries.
// GeometryCollection geometries = new GeometryCollection();
//
// // Loop on the number of geometries.
// for (int i = 0; i < numGeometries; i++)
// {
// // Call the main create function with the next geometry.
// geometries.Collection.Add(Parse(reader));
// }
//
// // Create and return the next geometry.
// return geometries;
// }
//
// //NOT USED
// //private static int ReadInt32(BinaryReader reader, WKBByteOrder byteOrder)
// //{
// // if (byteOrder == WKBByteOrder.Xdr)
// // {
// // byte[] bytes = BitConverter.GetBytes(reader.ReadInt32());
// // Array.Reverse(bytes);
// // return BitConverter.ToInt32(bytes, 0);
// // }
// // else
// // return reader.ReadInt32();
// //}
//
// private static uint ReadUInt32(BinaryReader reader, WkbByteOrder byteOrder)
// {
// if (byteOrder == WkbByteOrder.Xdr)
// {
// byte[] bytes = BitConverter.GetBytes(reader.ReadUInt32());
// Array.Reverse(bytes);
// return BitConverter.ToUInt32(bytes, 0);
// }
// else
// return reader.ReadUInt32();
// }
//
// private static double ReadDouble(BinaryReader reader, WkbByteOrder byteOrder)
// {
// if (byteOrder == WkbByteOrder.Xdr)
// {
// byte[] bytes = BitConverter.GetBytes(reader.ReadDouble());
// Array.Reverse(bytes);
// return BitConverter.ToDouble(bytes, 0);
// }
// else
// return reader.ReadDouble();
// }
}
}