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

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. using System;
  17. using System.Collections.Generic;
  18. using System.Collections.ObjectModel;
  19. using System.Text;
  20. using System.Drawing.Imaging;
  21. using System.Drawing;
  22. namespace SharpMap.Layers
  23. {
  24. /// <summary>
  25. /// Web Map Service layer
  26. /// </summary>
  27. /// <remarks>
  28. /// The WmsLayer is currently very basic and doesn't support automatic fetching of the WMS Service Description.
  29. /// Instead you would have to add the nessesary parameters to the URL,
  30. /// and the WmsLayer will set the remaining BoundingBox property and proper requests that changes between the requests.
  31. /// See the example below.
  32. /// </remarks>
  33. /// <example>
  34. /// The following example creates a map with a WMS layer the Demis WMS Server
  35. /// <code lang="C#">
  36. /// myMap = new SharpMap.Map(new System.Drawing.Size(500,250);
  37. /// string wmsUrl = "http://www2.demis.nl/mapserver/request.asp";
  38. /// SharpMap.Layers.WmsLayer myLayer = new SharpMap.Layers.WmsLayer("Demis WMS", myLayer);
  39. /// myLayer.AddLayer("Bathymetry");
  40. /// myLayer.AddLayer("Countries");
  41. /// myLayer.AddLayer("Topography");
  42. /// myLayer.AddLayer("Hillshading");
  43. /// myLayer.SetImageFormat(layWms.OutputFormats[0]);
  44. /// myLayer.SpatialReferenceSystem = "EPSG:4326";
  45.     /// myMap.Layers.Add(myLayer);
  46. /// myMap.Center = new SharpMap.Geometries.Point(0, 0);
  47. /// myMap.Zoom = 360;
  48. /// myMap.MaximumZoom = 360;
  49. /// myMap.MinimumZoom = 0.1;
  50. /// </code>
  51. /// </example>
  52. public class WmsLayer : SharpMap.Layers.Layer
  53. {
  54. private SharpMap.Web.Wms.Client wmsClient;
  55. private string _MimeType = "";
  56. /// <summary>
  57. /// Initializes a new layer, and downloads and parses the service description
  58. /// </summary>
  59. /// <remarks>In and ASP.NET application the service description is automatically cached for 24 hours when not specified</remarks>
  60. /// <param name="layername">Layername</param>
  61. /// <param name="url">Url of WMS server</param>
  62. public WmsLayer(string layername, string url)
  63. : this(layername, url, new TimeSpan(24, 0, 0))
  64. {
  65. }
  66. /// <summary>
  67. /// Initializes a new layer, and downloads and parses the service description
  68. /// </summary>
  69. /// <param name="layername">Layername</param>
  70. /// <param name="url">Url of WMS server</param>
  71. /// <param name="cachetime">Time for caching Service Description (ASP.NET only)</param>
  72. public WmsLayer(string layername, string url, TimeSpan cachetime)
  73. : this(layername, url, cachetime, null)
  74. {
  75. }
  76. /// <summary>
  77. /// Initializes a new layer, and downloads and parses the service description
  78. /// </summary>
  79. /// <remarks>In and ASP.NET application the service description is automatically cached for 24 hours when not specified</remarks>
  80. /// <param name="layername">Layername</param>
  81. /// <param name="url">Url of WMS server</param>
  82. /// <param name="proxy">Proxy</param>
  83. public WmsLayer(string layername, string url, System.Net.WebProxy proxy)
  84. : this(layername, url, new TimeSpan(24,0,0), proxy)
  85. {
  86. }
  87. /// <summary>
  88. /// Initializes a new layer, and downloads and parses the service description
  89. /// </summary>
  90. /// <param name="layername">Layername</param>
  91. /// <param name="url">Url of WMS server</param>
  92. /// <param name="cachetime">Time for caching Service Description (ASP.NET only)</param>
  93. /// <param name="proxy">Proxy</param>
  94. public WmsLayer(string layername, string url, TimeSpan cachetime, System.Net.WebProxy proxy)
  95. {
  96. _Proxy = proxy;
  97. _TimeOut = 10000;
  98. this.LayerName = layername;
  99. _ContinueOnError = true;
  100. if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.Cache["SharpMap_WmsClient_" + url] != null)
  101. {
  102. wmsClient = (SharpMap.Web.Wms.Client)System.Web.HttpContext.Current.Cache["SharpMap_WmsClient_" + url];
  103. }
  104. else
  105. {
  106. wmsClient = new SharpMap.Web.Wms.Client(url, _Proxy);
  107. if (System.Web.HttpContext.Current != null)
  108. System.Web.HttpContext.Current.Cache.Insert("SharpMap_WmsClient_" + url, wmsClient, null,
  109. System.Web.Caching.Cache.NoAbsoluteExpiration, cachetime);
  110. }
  111. //Set default mimetype - We prefer compressed formats
  112. if (OutputFormats.Contains("image/jpeg")) _MimeType = "image/jpeg";
  113. else if (OutputFormats.Contains("image/png")) _MimeType = "image/png";
  114. else if (OutputFormats.Contains("image/gif")) _MimeType = "image/gif";
  115. else //None of the default formats supported - Look for the first supported output format
  116. {
  117. bool formatSupported = false;
  118. foreach (System.Drawing.Imaging.ImageCodecInfo encoder in System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders())
  119. if (OutputFormats.Contains(encoder.MimeType.ToLower()))
  120. {
  121. formatSupported = true;
  122. _MimeType = encoder.MimeType;
  123. break;
  124. }
  125. if (!formatSupported)
  126. throw new ArgumentException("GDI+ doesn't not support any of the mimetypes supported by this WMS service");
  127. }
  128. _LayerList = new Collection<string>();
  129. _StylesList = new Collection<string>();
  130. }
  131. private Collection<string> _LayerList;
  132. /// <summary>
  133. /// Gets the list of enabled layers
  134. /// </summary>
  135. public Collection<string> LayerList
  136. {
  137. get { return _LayerList; }
  138. }
  139. /// <summary>
  140. /// Adds a layer to WMS request
  141. /// </summary>
  142. /// <remarks>Layer names are case sensitive.</remarks>
  143. /// <param name="name">Name of layer</param>
  144. /// <exception cref="System.ArgumentException">Throws an exception is an unknown layer is added</exception>
  145. public void AddLayer(string name)
  146. {
  147. if(!LayerExists(wmsClient.Layer,name))
  148. throw new ArgumentException("Cannot add WMS Layer - Unknown layername");
  149. _LayerList.Add(name);
  150. }
  151. /// <summary>
  152. /// Recursive method for checking whether a layername exists
  153. /// </summary>
  154. /// <param name="layer"></param>
  155. /// <param name="name"></param>
  156. /// <returns></returns>
  157. private bool LayerExists(SharpMap.Web.Wms.Client.WmsServerLayer layer, string name)
  158. {
  159. if(name == layer.Name) return true;
  160. foreach (SharpMap.Web.Wms.Client.WmsServerLayer childlayer in layer.ChildLayers)
  161. if (LayerExists(childlayer,name)) return true;
  162. return false;
  163. }
  164. /// <summary>
  165. /// Removes a layer from the layer list
  166. /// </summary>
  167. /// <param name="name">Name of layer to remove</param>
  168. public void RemoveLayer(string name)
  169. {
  170. _LayerList.Remove(name);
  171. }
  172. /// <summary>
  173. /// Removes the layer at the specified index
  174. /// </summary>
  175. /// <param name="index"></param>
  176. public void RemoveLayerAt(int index)
  177. {
  178. _LayerList.RemoveAt(index);
  179. }
  180. /// <summary>
  181. /// Removes all layers
  182. /// </summary>
  183. public void RemoveAllLayers()
  184. {
  185. _LayerList.Clear();
  186. }
  187. private Collection<string> _StylesList;
  188. /// <summary>
  189. /// Gets the list of enabled styles
  190. /// </summary>
  191. public Collection<string> StylesList
  192. {
  193. get { return _StylesList; }
  194. }
  195. /// <summary>
  196. /// Adds a style to the style collection
  197. /// </summary>
  198. /// <param name="name">Name of style</param>
  199. /// <exception cref="System.ArgumentException">Throws an exception is an unknown layer is added</exception>
  200. public void AddStyle(string name)
  201. {
  202. if (!StyleExists(wmsClient.Layer, name))
  203. throw new ArgumentException("Cannot add WMS Layer - Unknown layername");
  204. _StylesList.Add(name);
  205. }
  206. /// <summary>
  207. /// Recursive method for checking whether a layername exists
  208. /// </summary>
  209. /// <param name="layer">layer</param>
  210. /// <param name="name">name of style</param>
  211. /// <returns>True of style exists</returns>
  212. private bool StyleExists(SharpMap.Web.Wms.Client.WmsServerLayer layer, string name)
  213. {
  214. foreach(SharpMap.Web.Wms.Client.WmsLayerStyle style in layer.Style)
  215. if (name == style.Name) return true;
  216. foreach (SharpMap.Web.Wms.Client.WmsServerLayer childlayer in layer.ChildLayers)
  217. if (StyleExists(childlayer, name)) return true;
  218. return false;
  219. }
  220. /// <summary>
  221. /// Removes a style from the collection
  222. /// </summary>
  223. /// <param name="name">Name of style</param>
  224. public void RemoveStyle(string name)
  225. {
  226. _StylesList.Remove(name);
  227. }
  228. /// <summary>
  229. /// Removes a style at specified index
  230. /// </summary>
  231. /// <param name="index">Index</param>
  232. public void RemoveStyleAt(int index)
  233. {
  234. _StylesList.RemoveAt(index);
  235. }
  236. /// <summary>
  237. /// Removes all styles from the list
  238. /// </summary>
  239. public void RemoveAllStyles()
  240. {
  241. _StylesList.Clear();
  242. }
  243. /// <summary>
  244. /// Sets the image type to use when requesting images from the WMS server
  245. /// </summary>
  246. /// <remarks>
  247. /// <para>See the <see cref="OutputFormats"/> property for a list of available mime types supported by the WMS server</para>
  248. /// </remarks>
  249. /// <exception cref="ArgumentException">Throws an exception if either the mime type isn't offered by the WMS
  250. /// or GDI+ doesn't support this mime type.</exception>
  251. /// <param name="mimeType">Mime type of image format</param>
  252. public void SetImageFormat(string mimeType)
  253. {
  254. if (!OutputFormats.Contains(mimeType))
  255. throw new ArgumentException("WMS service doesn't not offer mimetype '" + mimeType + "'");
  256. //Check whether SharpMap supports the specified mimetype
  257. bool formatSupported = false;
  258. foreach (System.Drawing.Imaging.ImageCodecInfo encoder in System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders())
  259. if (encoder.MimeType.ToLower() == mimeType.ToLower())
  260. {
  261. formatSupported = true;
  262. break;
  263. }
  264. if (!formatSupported)
  265. throw new ArgumentException("GDI+ doesn't not support mimetype '" + mimeType + "'");
  266. _MimeType = mimeType;
  267. }
  268. /// <summary>
  269. /// Gets the hiarchial list of available WMS layers from this service
  270. /// </summary>
  271. public SharpMap.Web.Wms.Client.WmsServerLayer RootLayer
  272. {
  273. get { return wmsClient.Layer; }
  274. }
  275. /// <summary>
  276. /// Gets the list of available formats
  277. /// </summary>
  278. public Collection<string> OutputFormats
  279. {
  280. get { return wmsClient.GetMapOutputFormats; }
  281. }
  282. private string _SpatialReferenceSystem;
  283. /// <summary>
  284. /// Gets or sets the spatial reference used for the WMS server request
  285. /// </summary>
  286. public string SpatialReferenceSystem
  287. {
  288. get { return _SpatialReferenceSystem; }
  289. set { _SpatialReferenceSystem = value; }
  290. }
  291. /// <summary>
  292. /// Gets the service description from this server
  293. /// </summary>
  294. public SharpMap.Web.Wms.Capabilities.WmsServiceDescription ServiceDescription
  295. {
  296. get { return wmsClient.ServiceDescription; }
  297. }
  298. /// <summary>
  299. /// Gets the WMS Server version of this service
  300. /// </summary>
  301. public string Version
  302. {
  303. get { return wmsClient.WmsVersion; }
  304. }
  305. private ImageAttributes _ImageAttributes;
  306. /// <summary>
  307. /// When specified, applies image attributes at image (fx. make WMS layer semi-transparent)
  308. /// </summary>
  309. /// <remarks>
  310. /// <para>You can make the WMS layer semi-transparent by settings a up a ColorMatrix,
  311. /// or scale/translate the colors in any other way you like.</para>
  312. /// <example>
  313. /// Setting the WMS layer to be semi-transparent.
  314. /// <code lang="C#">
  315. /// float[][] colorMatrixElements = { 
  316. /// new float[] {1,  0,  0,  0, 0},
  317. /// new float[] {0,  1,  0,  0, 0},
  318. /// new float[] {0,  0,  1,  0, 0},
  319. /// new float[] {0,  0,  0,  0.5, 0},
  320. /// new float[] {0, 0, 0, 0, 1}};
  321. /// ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
  322. /// ImageAttributes imageAttributes = new ImageAttributes();
  323. /// imageAttributes.SetColorMatrix(
  324. ///     colorMatrix,
  325. ///     ColorMatrixFlag.Default,
  326. ///     ColorAdjustType.Bitmap);
  327. /// myWmsLayer.ImageAttributes = imageAttributes;
  328. /// </code>
  329. /// </example>
  330. /// </remarks>
  331. public ImageAttributes ImageAttributes
  332. {
  333. get { return _ImageAttributes; }
  334. set { _ImageAttributes = value; }
  335. }
  336. #region ILayer Members
  337. /// <summary>
  338. /// Renders the layer
  339. /// </summary>
  340. /// <param name="g">Graphics object reference</param>
  341. /// <param name="map">Map which is rendered</param>
  342. public override void Render(System.Drawing.Graphics g, Map map)
  343. {
  344. SharpMap.Web.Wms.Client.WmsOnlineResource resource = GetPreferredMethod();
  345. Uri myUri = new Uri(GetRequestUrl(map.Envelope,map.Size));
  346. System.Net.WebRequest myWebRequest = System.Net.WebRequest.Create(myUri);
  347. myWebRequest.Method = resource.Type;
  348. myWebRequest.Timeout = _TimeOut;
  349. if (_Credentials != null)
  350. myWebRequest.Credentials = _Credentials;
  351. else
  352. myWebRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
  353. if (_Proxy != null)
  354. myWebRequest.Proxy = _Proxy;
  355. try
  356. {
  357. System.Net.HttpWebResponse myWebResponse = (System.Net.HttpWebResponse)myWebRequest.GetResponse();
  358. System.IO.Stream dataStream = myWebResponse.GetResponseStream();
  359. if (myWebResponse.ContentType.StartsWith("image"))
  360. {
  361. System.Drawing.Image img = System.Drawing.Image.FromStream(myWebResponse.GetResponseStream());
  362. if (_ImageAttributes != null)
  363. g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height), 0, 0,
  364.    img.Width, img.Height, GraphicsUnit.Pixel, this.ImageAttributes);
  365. else
  366. g.DrawImageUnscaled(img, 0, 0,map.Size.Width,map.Size.Height);
  367. }
  368. dataStream.Close();
  369. myWebResponse.Close();
  370. }
  371. catch (System.Net.WebException webEx)
  372. {
  373. if (!_ContinueOnError)
  374. throw (new SharpMap.Rendering.Exceptions.RenderException("There was a problem connecting to the WMS server when rendering layer '" + this.LayerName + "'", webEx));
  375. else
  376. //Write out a trace warning instead of throwing an error to help debugging WMS problems
  377. System.Diagnostics.Trace.Write("There was a problem connecting to the WMS server when rendering layer '" + this.LayerName + "': " + webEx.Message);
  378. }
  379. catch (System.Exception ex)
  380. {
  381. if (!_ContinueOnError)
  382. throw (new SharpMap.Rendering.Exceptions.RenderException("There was a problem rendering layer '" + this.LayerName + "'", ex));
  383. else
  384. //Write out a trace warning instead of throwing an error to help debugging WMS problems
  385. System.Diagnostics.Trace.Write("There was a problem connecting to the WMS server when rendering layer '" + this.LayerName + "': " + ex.Message);
  386. }
  387. base.Render(g, map);
  388. }
  389. /// <summary>
  390. /// Gets the URL for a map request base on current settings, the image size and boundingbox
  391. /// </summary>
  392. /// <param name="box">Area the WMS request should cover</param>
  393. /// <param name="size">Size of image</param>
  394. /// <returns>URL for WMS request</returns>
  395. public string GetRequestUrl(SharpMap.Geometries.BoundingBox box, System.Drawing.Size size)
  396. {
  397. SharpMap.Web.Wms.Client.WmsOnlineResource resource = GetPreferredMethod();
  398. System.Text.StringBuilder strReq = new StringBuilder(resource.OnlineResource);
  399. if(!resource.OnlineResource.Contains("?"))
  400. strReq.Append("?");
  401. if (!strReq.ToString().EndsWith("&") && !strReq.ToString().EndsWith("?"))
  402. strReq.Append("&");
  403. strReq.AppendFormat(SharpMap.Map.numberFormat_EnUS, "REQUEST=GetMap&BBOX={0},{1},{2},{3}",
  404. box.Min.X, box.Min.Y, box.Max.X, box.Max.Y);
  405. strReq.AppendFormat("&WIDTH={0}&Height={1}", size.Width, size.Height);
  406. strReq.Append("&Layers=");
  407. if (_LayerList != null && _LayerList.Count > 0)
  408. {
  409. foreach (string layer in _LayerList)
  410. strReq.AppendFormat("{0},", layer);
  411. strReq.Remove(strReq.Length - 1, 1);
  412. }
  413. strReq.AppendFormat("&FORMAT={0}", _MimeType);
  414. if (_SpatialReferenceSystem == string.Empty)
  415. throw new ApplicationException("Spatial reference system not set");
  416. if(wmsClient.WmsVersion=="1.3.0")
  417. strReq.AppendFormat("&CRS={0}", _SpatialReferenceSystem);
  418. else
  419. strReq.AppendFormat("&SRS={0}", _SpatialReferenceSystem);
  420. strReq.AppendFormat("&VERSION={0}", wmsClient.WmsVersion);
  421. strReq.Append("&Styles=");
  422. if (_StylesList != null && _StylesList.Count > 0)
  423. {
  424. foreach (string style in _StylesList)
  425. strReq.AppendFormat("{0},", style);
  426. strReq.Remove(strReq.Length - 1, 1);
  427. }
  428. return strReq.ToString();
  429. }
  430. /// <summary>
  431. /// Returns the extent of the layer
  432. /// </summary>
  433. /// <returns>Bounding box corresponding to the extent of the features in the layer</returns>
  434. public override SharpMap.Geometries.BoundingBox Envelope
  435. {
  436. get
  437. {
  438. return RootLayer.LatLonBoundingBox;
  439. }
  440. }
  441. private Boolean _ContinueOnError;
  442. /// <summary>
  443. /// Specifies whether to throw an exception if the Wms request failed, or to just skip rendering the layer
  444. /// </summary>
  445. public Boolean ContinueOnError
  446. {
  447. get { return _ContinueOnError; }
  448. set { _ContinueOnError = value; }
  449. }
  450. /// <summary>
  451. /// Returns the type of the layer
  452. /// </summary>
  453. //public override SharpMap.Layers.Layertype LayerType
  454. //{
  455. //    get { return SharpMap.Layers.Layertype.Wms; }
  456. //}
  457. #endregion
  458. private SharpMap.Web.Wms.Client.WmsOnlineResource GetPreferredMethod()
  459. {
  460. //We prefer posting. Seek for supported post method
  461. for (int i = 0; i < wmsClient.GetMapRequests.Length; i++)
  462. if (wmsClient.GetMapRequests[i].Type.ToLower() == "post")
  463. return wmsClient.GetMapRequests[i];
  464. //Next we prefer the 'get' method
  465. for (int i = 0; i < wmsClient.GetMapRequests.Length; i++)
  466. if (wmsClient.GetMapRequests[i].Type.ToLower() == "get")
  467. return wmsClient.GetMapRequests[i];
  468. return wmsClient.GetMapRequests[0];
  469. }
  470. private System.Net.ICredentials _Credentials;
  471. /// <summary>
  472. /// Provides the base authentication interface for retrieving credentials for Web client authentication.
  473. /// </summary>
  474. public System.Net.ICredentials Credentials
  475. {
  476. get { return _Credentials; }
  477. set { _Credentials = value; }
  478. }
  479. private System.Net.WebProxy _Proxy;
  480. /// <summary>
  481. /// Gets or sets the proxy used for requesting a webresource
  482. /// </summary>
  483. public System.Net.WebProxy Proxy
  484. {
  485. get { return _Proxy; }
  486. set { _Proxy = value; }
  487. }
  488. private int _TimeOut;
  489. /// <summary>
  490. /// Timeout of webrequest in milliseconds. Defaults to 10 seconds
  491. /// </summary>
  492. public int TimeOut
  493. {
  494. get { return _TimeOut; }
  495. set { _TimeOut = value; }
  496. }
  497. #region ICloneable Members
  498. /// <summary>
  499. /// Clones the object
  500. /// </summary>
  501. /// <returns></returns>
  502. public override object Clone()
  503. {
  504. throw new NotImplementedException();
  505. }
  506. #endregion
  507. }
  508. }