GeometryToWKB.cs
上传用户:sex100000
上传日期:2013-11-09
资源大小:1377k
文件大小:14k
源码类别:

GIS编程

开发平台:

C#

  1. // Copyright 2005, 2006 - Morten Nielsen (www.iter.dk)
  2. //
  3. // This file is part of SharpMap.
  4. // SharpMap is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. // 
  9. // SharpMap is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU Lesser General Public License for more details.
  13. // You should have received a copy of the GNU Lesser General Public License
  14. // along with SharpMap; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  16. // SOURCECODE IS MODIFIED FROM ANOTHER WORK AND IS ORIGINALLY BASED ON GeoTools.NET:
  17. /*
  18.  *  Copyright (C) 2002 Urban Science Applications, Inc. 
  19.  *
  20.  *  This library is free software; you can redistribute it and/or
  21.  *  modify it under the terms of the GNU Lesser General Public
  22.  *  License as published by the Free Software Foundation; either
  23.  *  version 2.1 of the License, or (at your option) any later version.
  24.  *
  25.  *  This library is distributed in the hope that it will be useful,
  26.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  27.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  28.  *  Lesser General Public License for more details.
  29.  *
  30.  *  You should have received a copy of the GNU Lesser General Public
  31.  *  License along with this library; if not, write to the Free Software
  32.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  33.  *
  34.  */
  35. using System;
  36. using System.IO;
  37. using System.Collections;
  38. using SharpMap.Geometries;
  39. namespace SharpMap.Converters.WellKnownBinary
  40. {
  41. /// <summary>
  42. /// Converts a <see cref="SharpMap.Geometries.Geometry"/> instance to a Well-known Binary string representation.
  43. /// </summary>
  44. /// <remarks>
  45. /// <para>The Well-known Binary Representation for <see cref="SharpMap.Geometries.Geometry"/> (WKBGeometry) provides a portable 
  46. /// representation of a <see cref="SharpMap.Geometries.Geometry"/> value as a contiguous stream of bytes. It permits <see cref="SharpMap.Geometries.Geometry"/> 
  47. /// values to be exchanged between an ODBC client and an SQL database in binary form.</para>
  48. /// <para>The Well-known Binary Representation for <see cref="SharpMap.Geometries.Geometry"/> is obtained by serializing a <see cref="SharpMap.Geometries.Geometry"/>
  49. /// instance as a sequence of numeric types drawn from the set {Unsigned Integer, Double} and
  50. /// then serializing each numeric type as a sequence of bytes using one of two well defined,
  51. /// standard, binary representations for numeric types (NDR, XDR). The specific binary encoding
  52. /// (NDR or XDR) used for a geometry byte stream is described by a one byte tag that precedes
  53. /// the serialized bytes. The only difference between the two encodings of geometry is one of
  54. /// byte order, the XDR encoding is Big Endian, the NDR encoding is Little Endian.</para>
  55. /// </remarks> 
  56. public class GeometryToWKB
  57. {
  58. //private const byte WKBByteOrder = 0;
  59. /// <summary>
  60. /// Writes a geometry to a byte array using little endian byte encoding
  61. /// </summary>
  62. /// <param name="g">The geometry to write</param>
  63. /// <returns>WKB representation of the geometry</returns>
  64. public static byte[] Write(Geometry g)
  65. {
  66. return Write(g, WkbByteOrder.Ndr);
  67. }
  68. /// <summary>
  69. /// Writes a geometry to a byte array using the specified encoding.
  70. /// </summary>
  71. /// <param name="g">The geometry to write</param>
  72. /// <param name="wkbByteOrder">Byte order</param>
  73. /// <returns>WKB representation of the geometry</returns>
  74. public static byte[] Write(Geometry g, WkbByteOrder wkbByteOrder)
  75. {
  76. MemoryStream ms = new MemoryStream();
  77. BinaryWriter bw = new BinaryWriter(ms);
  78. //Write the byteorder format.
  79. bw.Write((byte)wkbByteOrder);
  80. //Write the type of this geometry
  81. WriteType(g, bw, wkbByteOrder);
  82. //Write the geometry
  83. WriteGeometry(g, bw, wkbByteOrder);
  84. return ms.ToArray();
  85. }
  86. #region Methods
  87. /// <summary>
  88. /// Writes the type number for this geometry.
  89. /// </summary>
  90. /// <param name="geometry">The geometry to determine the type of.</param>
  91. /// <param name="bWriter">Binary Writer</param>
  92. /// <param name="byteorder">Byte order</param>
  93. private static void WriteType(Geometry geometry, BinaryWriter bWriter, WkbByteOrder byteorder)
  94. {
  95. //Determine the type of the geometry.
  96. switch (geometry.GetType().FullName)
  97. {
  98. //Points are type 1.
  99. case "SharpMap.Geometries.Point":
  100. WriteUInt32((uint)WKBGeometryType.wkbPoint, bWriter, byteorder);
  101. break;
  102. //Linestrings are type 2.
  103. case "SharpMap.Geometries.LineString":
  104. WriteUInt32((uint)WKBGeometryType.wkbLineString, bWriter, byteorder);
  105. break;
  106. //Polygons are type 3.
  107. case "SharpMap.Geometries.Polygon":
  108. WriteUInt32((uint)WKBGeometryType.wkbPolygon, bWriter, byteorder);
  109. break;
  110. //Mulitpoints are type 4.
  111. case "SharpMap.Geometries.MultiPoint":
  112. WriteUInt32((uint)WKBGeometryType.wkbMultiPoint, bWriter, byteorder);
  113. break;
  114. //Multilinestrings are type 5.
  115. case "SharpMap.Geometries.MultiLineString":
  116. WriteUInt32((uint)WKBGeometryType.wkbMultiLineString, bWriter, byteorder);
  117. break;
  118. //Multipolygons are type 6.
  119. case "SharpMap.Geometries.MultiPolygon":
  120. WriteUInt32((uint)WKBGeometryType.wkbMultiPolygon, bWriter, byteorder);
  121. break;
  122. //Geometrycollections are type 7.
  123. case "SharpMap.Geometries.GeometryCollection":
  124. WriteUInt32((uint)WKBGeometryType.wkbGeometryCollection, bWriter, byteorder);
  125. break;
  126. //If the type is not of the above 7 throw an exception.
  127. default:
  128. throw new ArgumentException("Invalid Geometry Type");
  129. }
  130. }
  131. /// <summary>
  132. /// Writes the geometry to the binary writer.
  133. /// </summary>
  134. /// <param name="geometry">The geometry to be written.</param>
  135. /// <param name="bWriter"></param>
  136. /// <param name="byteorder">Byte order</param>
  137. private static void WriteGeometry(Geometry geometry, BinaryWriter bWriter, WkbByteOrder byteorder)
  138. {
  139. switch (geometry.GetType().FullName)
  140. {
  141. //Write the point.
  142. case "SharpMap.Geometries.Point":
  143. WritePoint((Point)geometry, bWriter, byteorder);
  144. break;
  145. case "SharpMap.Geometries.LineString":
  146. LineString ls = (LineString)geometry;
  147. WriteLineString(ls, bWriter, byteorder);
  148. break;
  149. case "SharpMap.Geometries.Polygon":
  150. WritePolygon((Polygon)geometry, bWriter, byteorder);
  151. break;
  152. //Write the Multipoint.
  153. case "SharpMap.Geometries.MultiPoint":
  154. WriteMultiPoint((MultiPoint)geometry, bWriter,byteorder);
  155. break;
  156. //Write the Multilinestring.
  157. case "SharpMap.Geometries.MultiLineString":
  158. WriteMultiLineString((MultiLineString)geometry, bWriter,byteorder);
  159. break;
  160. //Write the Multipolygon.
  161. case "SharpMap.Geometries.MultiPolygon":
  162. WriteMultiPolygon((MultiPolygon)geometry, bWriter,byteorder);
  163. break;
  164. //Write the Geometrycollection.
  165. case "SharpMap.Geometries.GeometryCollection":
  166. WriteGeometryCollection((GeometryCollection)geometry, bWriter,byteorder);
  167. break;
  168. //If the type is not of the above 7 throw an exception.
  169. default:
  170. throw new ArgumentException("Invalid Geometry Type");
  171. }
  172. }
  173. /// <summary>
  174. /// Writes a point.
  175. /// </summary>
  176. /// <param name="point">The point to be written.</param>
  177. /// <param name="bWriter">Stream to write to.</param>
  178. /// <param name="byteorder">Byte order</param>
  179. private static void WritePoint(Point point, BinaryWriter bWriter, WkbByteOrder byteorder)
  180. {
  181. //Write the x coordinate.
  182. WriteDouble(point.X, bWriter, byteorder);
  183. //Write the y coordinate.
  184. WriteDouble(point.Y, bWriter, byteorder);
  185. }
  186. /// <summary>
  187. /// Writes a linestring.
  188. /// </summary>
  189. /// <param name="ls">The linestring to be written.</param>
  190. /// <param name="bWriter">Stream to write to.</param>
  191. /// <param name="byteorder">Byte order</param>
  192. private static void WriteLineString(LineString ls, BinaryWriter bWriter, WkbByteOrder byteorder)
  193. {
  194. //Write the number of points in this linestring.
  195. WriteUInt32((uint)ls.Vertices.Count,bWriter,byteorder);
  196. //Loop on each vertices.
  197. foreach (Point p in ls.Vertices)
  198. WritePoint(p, bWriter, byteorder);
  199. }
  200. /// <summary>
  201. /// Writes a polygon.
  202. /// </summary>
  203. /// <param name="poly">The polygon to be written.</param>
  204. /// <param name="bWriter">Stream to write to.</param>
  205. /// <param name="byteorder">Byte order</param>
  206. private static void WritePolygon(Polygon poly, BinaryWriter bWriter, WkbByteOrder byteorder)
  207. {
  208. //Get the number of rings in this polygon.
  209. int numRings = poly.InteriorRings.Count + 1;
  210. //Write the number of rings to the stream (add one for the shell)
  211. WriteUInt32((uint)numRings, bWriter, byteorder);
  212. //Write the exterior of this polygon.
  213. WriteLineString((LineString)poly.ExteriorRing, bWriter, byteorder);
  214. //Loop on the number of rings - 1 because we already wrote the shell.
  215. foreach (LinearRing lr in poly.InteriorRings)
  216. //Write the (lineString)LinearRing.
  217. WriteLineString((LineString)lr, bWriter, byteorder);
  218. }
  219. /// <summary>
  220. /// Writes a multipoint.
  221. /// </summary>
  222. /// <param name="mp">The multipoint to be written.</param>
  223. /// <param name="bWriter">Stream to write to.</param>
  224. /// <param name="byteorder">Byte order</param>
  225. private static void WriteMultiPoint(MultiPoint mp, BinaryWriter bWriter, WkbByteOrder byteorder)
  226. {
  227. //Write the number of points.
  228. WriteUInt32((uint)mp.Points.Count, bWriter, byteorder);
  229. //Loop on the number of points.
  230. foreach (Point p in mp.Points)
  231. {
  232. //Write Points Header
  233. bWriter.Write((byte)byteorder);
  234. WriteUInt32((uint)WKBGeometryType.wkbPoint, bWriter, byteorder);
  235. //Write each point.
  236. WritePoint((Point)p, bWriter, byteorder);
  237. }
  238. }
  239. /// <summary>
  240. /// Writes a multilinestring.
  241. /// </summary>
  242. /// <param name="mls">The multilinestring to be written.</param>
  243. /// <param name="bWriter">Stream to write to.</param>
  244. /// <param name="byteorder">Byte order</param>
  245. private static void WriteMultiLineString(MultiLineString mls, BinaryWriter bWriter, WkbByteOrder byteorder)
  246. {
  247. //Write the number of linestrings.
  248. WriteUInt32((uint)mls.LineStrings.Count, bWriter, byteorder);
  249. //Loop on the number of linestrings.
  250. foreach (LineString ls in mls.LineStrings)
  251. {
  252. //Write LineString Header
  253. bWriter.Write((byte)byteorder);
  254. WriteUInt32((uint)WKBGeometryType.wkbLineString, bWriter, byteorder);
  255. //Write each linestring.
  256. WriteLineString(ls, bWriter, byteorder);
  257. }
  258. }
  259. /// <summary>
  260. /// Writes a multipolygon.
  261. /// </summary>
  262. /// <param name="mp">The mulitpolygon to be written.</param>
  263. /// <param name="bWriter">Stream to write to.</param>
  264. /// <param name="byteorder">Byte order</param>
  265. private static void WriteMultiPolygon(MultiPolygon mp, BinaryWriter bWriter, WkbByteOrder byteorder)
  266. {
  267. //Write the number of polygons.
  268. WriteUInt32((uint)mp.Polygons.Count, bWriter, byteorder);
  269. //Loop on the number of polygons.
  270. foreach (Polygon poly in mp.Polygons)
  271. {
  272. //Write polygon header
  273. bWriter.Write((byte)byteorder);
  274. WriteUInt32((uint)WKBGeometryType.wkbPolygon, bWriter, byteorder);
  275. //Write each polygon.
  276. WritePolygon(poly, bWriter, byteorder);
  277. }
  278. }
  279. /// <summary>
  280. /// Writes a geometrycollection.
  281. /// </summary>
  282. /// <param name="gc">The geometrycollection to be written.</param>
  283. /// <param name="bWriter">Stream to write to.</param>
  284. /// <param name="byteorder">Byte order</param>
  285. private static void WriteGeometryCollection(GeometryCollection gc, BinaryWriter bWriter, WkbByteOrder byteorder)
  286. {
  287. //Get the number of geometries in this geometrycollection.
  288. int numGeometries = gc.NumGeometries;
  289. //Write the number of geometries.
  290. WriteUInt32((uint)numGeometries, bWriter, byteorder);
  291. //Loop on the number of geometries.
  292. for (int i = 0; i < numGeometries; i++)
  293. {
  294. //Write the byte-order format of the following geometry.
  295. bWriter.Write((byte)byteorder);
  296. //Write the type of each geometry.
  297. WriteType(gc[i], bWriter, byteorder);
  298. //Write each geometry.
  299. WriteGeometry(gc[i], bWriter, byteorder);
  300. }
  301. }
  302. #endregion
  303. /// <summary>
  304. /// Writes an unsigned integer to the binarywriter using the specified encoding
  305. /// </summary>
  306. /// <param name="value">Value to write</param>
  307. /// <param name="writer">Binary Writer</param>
  308. /// <param name="byteOrder">byteorder</param>
  309. private static void WriteUInt32(UInt32 value, BinaryWriter writer, WkbByteOrder byteOrder)
  310. {
  311. if (byteOrder == WkbByteOrder.Xdr)
  312. {
  313. byte[] bytes = BitConverter.GetBytes(value);
  314. Array.Reverse(bytes);
  315. writer.Write(BitConverter.ToUInt32(bytes, 0));
  316. }
  317. else
  318. writer.Write(value);
  319. }
  320. /// <summary>
  321. /// Writes a double to the binarywriter using the specified encoding
  322. /// </summary>
  323. /// <param name="value">Value to write</param>
  324. /// <param name="writer">Binary Writer</param>
  325. /// <param name="byteOrder">byteorder</param>
  326. private static void WriteDouble(double value, BinaryWriter writer, WkbByteOrder byteOrder)
  327. {
  328. if (byteOrder == WkbByteOrder.Xdr)
  329. {
  330. byte[] bytes = BitConverter.GetBytes(value);
  331. Array.Reverse(bytes);
  332. writer.Write(BitConverter.ToDouble(bytes, 0));
  333. }
  334. else
  335. writer.Write(value);
  336. }
  337. }
  338. }