using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Net; using BruTile; using BruTile.Cache; using BruTile.Extensions; using BruTile.Predefined; using BruTile.Web; using BruTile.Wms; using BruTile.Wmsc; using Core.Common.Utils; using Core.GIS.GeoApi.CoordinateSystems.Transformations; using Core.GIS.GeoApi.Geometries; using Core.GIS.NetTopologySuite.Geometries; using Core.GIS.SharpMap.Api.Layers; using Core.GIS.SharpMap.Layers; using Layer = BruTile.Wms.Layer; namespace Core.GIS.SharpMap.Extensions.Layers { /// /// TODO: incomplete /// public class WmscLayer : AsyncTileLayer { private static bool makeLayerVisible; private static ICoordinateTransformation geo2webTransformation; private ITileCache cache; private ITileSchema tileSchema; private IEnvelope schemaEnvelope; public WmscLayer() { TransparentColor = Color.White; } public virtual string Url { get; set; } public virtual string CacheLocation { get { var path = SettingsHelper.GetApplicationLocalUserSettingsDirectory(); return Path.Combine(path, "cache_wms_" + Url.Replace(':', '_').Replace('/', '_').Replace('&', '_').Replace('?', '_') + WmsLayer); } } public virtual string WmsLayer { get; set; } public static ILayer CreateWmsLayersFromUrl(string url) { url += "REQUEST=GetCapabilities&SERVICE=WMS"; var webRequest = (HttpWebRequest) WebRequest.Create(url); using (var webResponse = webRequest.GetSyncResponse(10000)) { if (webResponse == null) { throw (new WebException("An error occurred while fetching tile", null)); } using (var responseStream = webResponse.GetResponseStream()) { var capabilities = new WmsCapabilities(responseStream); makeLayerVisible = true; return capabilities.Capability.Layer.ChildLayers.Count > 0 ? CreateChildLayers(url, capabilities.Capability.Layer.ChildLayers, new GroupLayer { Name = GetWmsLayerName(capabilities.Capability.Layer), ReadOnly = true }) : CreateWmsLayer(url, capabilities.Capability.Layer); } } } public override object Clone() { var clone = (WmscLayer) base.Clone(); clone.schemaEnvelope = (IEnvelope) schemaEnvelope.Clone(); clone.WmsLayer = WmsLayer; clone.Url = Url; return clone; } protected override ITileCache GetOrCreateCache() { if (cache == null) { //no cache so mem if (CacheLocation == null) { cache = new MemoryCache(1000, 100000); } else { cache = new FileCache(CacheLocation, "jpg"); } } return cache; } protected override ITileSchema CreateTileSchema() { if (tileSchema == null) { tileSchema = new GlobalSphericalMercator { Extent = new Extent(schemaEnvelope.MinX, schemaEnvelope.MinY, schemaEnvelope.MaxX, schemaEnvelope.MaxY) }; } return tileSchema; } protected override IRequest CreateRequest() { return new WmscRequest(new Uri(Url), tileSchema, new List(new[] { WmsLayer }), null, null, "1.3.0"); } private static ICoordinateTransformation Geo2webTransformation { get { if (geo2webTransformation == null) { var srcSrs = SharpMap.Map.Map.CoordinateSystemFactory.CreateFromEPSG(4326); var dstSrs = SharpMap.Map.Map.CoordinateSystemFactory.CreateFromEPSG(3857); geo2webTransformation = SharpMap.Map.Map.CoordinateSystemFactory.CreateTransformation(srcSrs, dstSrs); } return geo2webTransformation; } } private static ILayer CreateChildLayers(string url, IEnumerable childLayers, IGroupLayer parent) { foreach (var childWmsLayer in childLayers) { parent.Layers.Add(childWmsLayer.ChildLayers.Count > 0 ? CreateChildLayers(url, childWmsLayer.ChildLayers, new GroupLayer { Name = GetWmsLayerName(childWmsLayer), ReadOnly = true }) : CreateWmsLayer(url, childWmsLayer)); } return parent; } private static WmscLayer CreateWmsLayer(string url, Layer wmsLayer) { var layer = new WmscLayer { Name = GetWmsLayerName(wmsLayer), Url = url, WmsLayer = wmsLayer.Name, Visible = makeLayerVisible, ReadOnly = true, schemaEnvelope = CreateEnvelope(wmsLayer) }; if (makeLayerVisible) { makeLayerVisible = false; } return layer; } private static IEnvelope CreateEnvelope(Layer wmsLayer) { var minX = wmsLayer.ExGeographicBoundingBox.WestBoundLongitude; var maxX = wmsLayer.ExGeographicBoundingBox.EastBoundLongitude; var minY = wmsLayer.ExGeographicBoundingBox.SouthBoundLatitude; var maxY = wmsLayer.ExGeographicBoundingBox.NorthBoundLatitude; var pointsGeo = new List { new[] { minX, minY }, new[] { maxX, minY }, new[] { maxX, maxY }, new[] { minX, maxY } }; var pointsWeb = Geo2webTransformation.MathTransform.TransformList(pointsGeo); var envelope = new Envelope(); envelope.ExpandToInclude(pointsWeb[0][0], pointsWeb[0][1]); envelope.ExpandToInclude(pointsWeb[1][0], pointsWeb[1][1]); envelope.ExpandToInclude(pointsWeb[2][0], pointsWeb[2][1]); envelope.ExpandToInclude(pointsWeb[3][0], pointsWeb[3][1]); return envelope; } private static string GetWmsLayerName(Layer layer) { return string.IsNullOrEmpty(layer.Name) ? layer.Title : layer.Name; } } }