PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Branches/0.9-GeoJSON/SharpMap/Web/Wms/Handlers/GetMap.cs

#
C# | 251 lines | 207 code | 25 blank | 19 comment | 43 complexity | 10742bb378ad7d4f9a542ed46e9ca5dc MD5 | raw file
Possible License(s): LGPL-2.1
  1. namespace SharpMap.Web.Wms.Handlers
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Drawing;
  6. using System.Drawing.Imaging;
  7. using System.IO;
  8. using System.Linq;
  9. using Data;
  10. using Geometries;
  11. using Layers;
  12. using ProjNet.CoordinateSystems.Transformations;
  13. using Rendering.GeoJSON;
  14. internal class GetMap : AbstractHandler
  15. {
  16. public GetMap(HandlerParams @params) : base(@params) { }
  17. public override void Handle()
  18. {
  19. string queryLayers = this.context.Request.Params["LAYERS"];
  20. string styles = this.context.Request.Params["STYLES"];
  21. string crs = this.context.Request.Params["CRS"];
  22. string queryBBOX = this.context.Request.Params["BBOX"];
  23. string queryWidth = this.context.Request.Params["WIDTH"];
  24. string queryHeight = this.context.Request.Params["HEIGHT"];
  25. string format = this.context.Request.Params["FORMAT"];
  26. string transparent = this.context.Request.Params["TRANSPARENT"];
  27. string background = this.context.Request.Params["BGCOLOR"];
  28. if (queryLayers == null)
  29. {
  30. WmsException.ThrowWmsException("Required parameter LAYERS not specified");
  31. return;
  32. }
  33. if (styles == null)
  34. {
  35. WmsException.ThrowWmsException("Required parameter STYLES not specified");
  36. return;
  37. }
  38. if (crs == null)
  39. {
  40. WmsException.ThrowWmsException("Required parameter CRS not specified");
  41. return;
  42. }
  43. if (!this.Check(String.Format("EPSG:{0}", this.map.Layers[0].SRID), crs))
  44. {
  45. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidCRS, "CRS not supported");
  46. return;
  47. }
  48. if (queryBBOX == null)
  49. {
  50. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue,
  51. "Required parameter BBOX not specified");
  52. return;
  53. }
  54. if (queryWidth == null)
  55. {
  56. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue,
  57. "Required parameter WIDTH not specified");
  58. return;
  59. }
  60. if (queryHeight == null)
  61. {
  62. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue,
  63. "Required parameter HEIGHT not specified");
  64. return;
  65. }
  66. if (format == null)
  67. {
  68. WmsException.ThrowWmsException("Required parameter FORMAT not specified");
  69. return;
  70. }
  71. //Set background color of map
  72. if (!this.Check("TRUE", transparent))
  73. {
  74. if (background != null)
  75. {
  76. try { this.map.BackColor = ColorTranslator.FromHtml(background); }
  77. catch
  78. {
  79. WmsException.ThrowWmsException("Invalid parameter BGCOLOR");
  80. return;
  81. }
  82. }
  83. else this.map.BackColor = Color.White;
  84. }
  85. else this.map.BackColor = Color.Transparent;
  86. //Parse map size
  87. int width;
  88. if (!Int32.TryParse(queryWidth, out width))
  89. {
  90. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue,
  91. "Invalid parameter WIDTH");
  92. return;
  93. }
  94. if (this.description.MaxWidth > 0 && width > this.description.MaxWidth)
  95. {
  96. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported,
  97. "Parameter WIDTH too large");
  98. return;
  99. }
  100. int height;
  101. if (!Int32.TryParse(queryHeight, out height))
  102. {
  103. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue,
  104. "Invalid parameter HEIGHT");
  105. return;
  106. }
  107. if (this.description.MaxHeight > 0 && height > this.description.MaxHeight)
  108. {
  109. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported,
  110. "Parameter HEIGHT too large");
  111. return;
  112. }
  113. this.map.Size = new Size(width, height);
  114. BoundingBox bbox = this.ParseBBOX(queryBBOX);
  115. if (bbox == null)
  116. {
  117. WmsException.ThrowWmsException("Invalid parameter BBOX");
  118. return;
  119. }
  120. this.map.PixelAspectRatio = (width / (double)height) / (bbox.Width / bbox.Height);
  121. this.map.Center = bbox.GetCentroid();
  122. this.map.Zoom = bbox.Width;
  123. //Set layers on/off
  124. if (!String.IsNullOrEmpty(queryLayers))
  125. //If LAYERS is empty, use default layer on/off settings
  126. {
  127. string[] layers = queryLayers.Split(new[] { ',' });
  128. if (this.description.LayerLimit > 0)
  129. {
  130. if (layers.Length == 0 &&
  131. this.map.Layers.Count > this.description.LayerLimit ||
  132. layers.Length > this.description.LayerLimit)
  133. {
  134. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported,
  135. "Too many layers requested");
  136. return;
  137. }
  138. }
  139. foreach (ILayer layer in this.map.Layers)
  140. layer.Enabled = false;
  141. foreach (string layer in layers)
  142. {
  143. ILayer lay = this.map.GetLayerByName(layer);
  144. if (lay == null)
  145. {
  146. WmsException.ThrowWmsException(WmsException.WmsExceptionCode.LayerNotDefined,
  147. String.Format("Unknown layer '{0}'", layer));
  148. return;
  149. }
  150. lay.Enabled = true;
  151. }
  152. }
  153. bool json = this.Check("text/json", format);
  154. if (json)
  155. {
  156. List<GeoJSON> items = new List<GeoJSON>();
  157. //Only queryable data!
  158. IQueryable<ICanQueryLayer> collection = this.map.Layers.AsQueryable()
  159. .OfType<ICanQueryLayer>().Where(l => l.Enabled && l.IsQueryEnabled);
  160. foreach (ICanQueryLayer layer in collection)
  161. {
  162. //Query for data
  163. FeatureDataSet ds = new FeatureDataSet();
  164. layer.ExecuteIntersectionQuery(bbox, ds);
  165. IEnumerable<GeoJSON> data = GeoJSONHelper.GetData(ds);
  166. //Filter only visible items
  167. //double f = bbox.GetArea() / (width * height);
  168. //data = data.Where(i =>
  169. //{
  170. // Geometry g = i.Geometry;
  171. // BoundingBox p = g.GetBoundingBox();
  172. // double area = p.GetArea();
  173. // return area == 0 || area > f;
  174. //});
  175. //Reproject geometries if needed
  176. IMathTransform transform = null;
  177. if (layer is VectorLayer)
  178. {
  179. ICoordinateTransformation transformation = (layer as VectorLayer).CoordinateTransformation;
  180. transform = transformation == null ? null : transformation.MathTransform;
  181. }
  182. if (transform != null)
  183. {
  184. data = data.Select(d =>
  185. {
  186. Geometry converted = GeometryTransform.TransformGeometry(d.Geometry, transform);
  187. d.SetGeometry(converted);
  188. return d;
  189. });
  190. }
  191. items.AddRange(data);
  192. }
  193. StringWriter writer = new StringWriter();
  194. GeoJSONWriter.Write(items, writer);
  195. string buffer = writer.ToString();
  196. this.context.Response.Clear();
  197. this.context.Response.ContentType = "text/json";
  198. this.context.Response.BufferOutput = true;
  199. this.context.Response.Write(buffer);
  200. this.context.Response.End();
  201. }
  202. else
  203. {
  204. //Get the image format requested
  205. ImageCodecInfo imageEncoder = this.GetEncoderInfo(format);
  206. if (imageEncoder == null)
  207. {
  208. WmsException.ThrowWmsException("Invalid MimeType specified in FORMAT parameter");
  209. return;
  210. }
  211. //Render map
  212. Image img = this.map.GetMap();
  213. //Png can't stream directy. Going through a memorystream instead
  214. MemoryStream ms = new MemoryStream();
  215. img.Save(ms, imageEncoder, null);
  216. img.Dispose();
  217. byte[] buffer = ms.ToArray();
  218. this.context.Response.Clear();
  219. this.context.Response.ContentType = imageEncoder.MimeType;
  220. this.context.Response.BufferOutput = true;
  221. this.context.Response.BinaryWrite(buffer);
  222. this.context.Response.End();
  223. }
  224. }
  225. }
  226. }