Index: Core/Components/src/Core.Components.DotSpatial/Layer/BruTile/BruTileLayer.cs =================================================================== diff -u -rfa3b352bc1b1c01fc73a9a45268c5573807a6381 -r81b98edbc30c61ae33c2e4925e365d5175147ef2 --- Core/Components/src/Core.Components.DotSpatial/Layer/BruTile/BruTileLayer.cs (.../BruTileLayer.cs) (revision fa3b352bc1b1c01fc73a9a45268c5573807a6381) +++ Core/Components/src/Core.Components.DotSpatial/Layer/BruTile/BruTileLayer.cs (.../BruTileLayer.cs) (revision 81b98edbc30c61ae33c2e4925e365d5175147ef2) @@ -107,6 +107,7 @@ private float transparency; private string level; + private static readonly ProjectionInfo defaultProjection = new ProjectionInfo(); /// /// Creates an instance of this class using some tile source configuration. @@ -335,23 +336,16 @@ private static ProjectionInfo GetTileSourceProjectionInfo(string spatialReferenceSystemString) { ProjectionInfo projectionInfo; - // For WMTS, 'spatialReferenceSystemString' might be some crude value (urn-string): - string authorityCode = ToAuthorityCode(spatialReferenceSystemString); - if (!string.IsNullOrWhiteSpace(authorityCode)) + if (!TryParseProjectionEsri(spatialReferenceSystemString, out projectionInfo)) { - projectionInfo = AuthorityCodeHandler.Instance[authorityCode]; - } - else - { - ProjectionInfo p; - if (!TryParseProjectionEsri(spatialReferenceSystemString, out p)) + if (!TryParseProjectionProj4(spatialReferenceSystemString, out projectionInfo)) { - if (!TryParseProjectionProj4(spatialReferenceSystemString, out p)) - { - p = null; - } + // For WMTS, 'spatialReferenceSystemString' might be some crude value (urn-string): + string authorityCode = ToAuthorityCode(spatialReferenceSystemString); + projectionInfo = !string.IsNullOrWhiteSpace(authorityCode) ? + AuthorityCodeHandler.Instance[authorityCode] : + null; } - projectionInfo = p; } if (projectionInfo == null) @@ -360,7 +354,7 @@ } // WebMercator: set datum to WGS1984 for better accuracy - if (spatialReferenceSystemString == webMercatorEpsgIdentifier) + if (projectionInfo.Name == webMercatorEpsgIdentifier) { projectionInfo.GeographicInfo.Datum = KnownCoordinateSystems.Geographic.World.WGS1984.GeographicInfo.Datum; } @@ -378,6 +372,14 @@ { projectionInfo = null; } + + // Compensate for ProjectionInfo.FromProj4String returning a default constructed + // ProjectionInfo instance if parsing failed: + if (defaultProjection.Equals(projectionInfo)) + { + projectionInfo = null; + } + return projectionInfo != null; } @@ -427,7 +429,7 @@ return srs; } - // More than 1 colon => assume urn:ogc:def:crs:EPSG:6.18.3:3857 + // More than 1 colon => assume format urn:ogc:def:crs:EPSG:6.18.3:3857 if (srsParts.Length > 4) { return $"{srsParts[4]}:{srsParts.Last()}"; Index: Core/Components/test/Core.Components.DotSpatial.Test/Core.Components.DotSpatial.Test.csproj =================================================================== diff -u -r1834682a9baa164ed89f7225ce6ec8b00264952f -r81b98edbc30c61ae33c2e4925e365d5175147ef2 --- Core/Components/test/Core.Components.DotSpatial.Test/Core.Components.DotSpatial.Test.csproj (.../Core.Components.DotSpatial.Test.csproj) (revision 1834682a9baa164ed89f7225ce6ec8b00264952f) +++ Core/Components/test/Core.Components.DotSpatial.Test/Core.Components.DotSpatial.Test.csproj (.../Core.Components.DotSpatial.Test.csproj) (revision 81b98edbc30c61ae33c2e4925e365d5175147ef2) @@ -105,6 +105,7 @@ + Index: Core/Components/test/Core.Components.DotSpatial.Test/Layer/BruTile/BruTileLayerTest.cs =================================================================== diff -u --- Core/Components/test/Core.Components.DotSpatial.Test/Layer/BruTile/BruTileLayerTest.cs (revision 0) +++ Core/Components/test/Core.Components.DotSpatial.Test/Layer/BruTile/BruTileLayerTest.cs (revision 81b98edbc30c61ae33c2e4925e365d5175147ef2) @@ -0,0 +1,316 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets 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 3 of the License, or +// (at your option) any later version. +// +// This program 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 program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using BruTile; +using Core.Components.DotSpatial.Layer.BruTile; +using Core.Components.DotSpatial.Layer.BruTile.Configurations; +using Core.Components.DotSpatial.Layer.BruTile.TileFetching; +using DotSpatial.Controls; +using DotSpatial.Projections; +using DotSpatial.Projections.AuthorityCodes; +using DotSpatial.Symbology; +using NUnit.Framework; +using Rhino.Mocks; +using DotSpatialLayer = DotSpatial.Symbology.Layer; +using DotSpatialExtent = DotSpatial.Data.Extent; + +namespace Core.Components.DotSpatial.Test.Layer.BruTile +{ + [TestFixture] + public class BruTileLayerTest + { + [Test] + public void Constructor_ConfigurationNull_ThrowArgumentNullException() + { + // Call + TestDelegate call = () => new BruTileLayer(null); + + // Assert + string paramName = Assert.Throws(call).ParamName; + Assert.AreEqual("configuration", paramName); + } + + [Test] + public void Constructor_ValidArguments_ExpectedValues() + { + // Setup + var mocks = new MockRepository(); + var provider = mocks.Stub(); + using (var tileFetcher = new AsyncTileFetcher(provider, 50, 200)) + { + var schema = mocks.Stub(); + const string authorityCode = "EPSG:28992"; + schema.Stub(s => s.Srs).Return(authorityCode); + var extent = new Extent(10000, 123456, 987654321, 321654); + schema.Stub(s => s.Extent).Return(extent); + + var tileSource = mocks.Stub(); + tileSource.Stub(ts => ts.Schema).Return(schema); + + string legendText = ""; + var configuration = mocks.Stub(); + configuration.Stub(c => c.Initialized).Return(true); + configuration.Stub(c => c.TileSource).Return(tileSource); + configuration.Stub(c => c.LegendText).Return(legendText); + configuration.Stub(c => c.TileFetcher).Return(tileFetcher); + mocks.ReplayAll(); + + // Call + using (var layer = new BruTileLayer(configuration)) + { + // Assert + Assert.IsInstanceOf(layer); + Assert.IsInstanceOf(layer); + + Assert.AreEqual(AuthorityCodeHandler.Instance[authorityCode], layer.Projection); + Assert.AreEqual(new DotSpatialExtent(extent.MinX, extent.MinY, extent.MaxX, extent.MaxY), layer.Extent); + + Assert.AreEqual(legendText, layer.LegendText); + Assert.IsTrue(layer.LegendItemVisible); + Assert.AreEqual(SymbolMode.Symbol, layer.LegendSymbolMode); + Assert.AreEqual(LegendType.Custom, layer.LegendType); + + Assert.IsTrue(layer.IsVisible); + Assert.IsTrue(layer.Checked); + + Assert.AreEqual(0, layer.Transparency); + } + } + mocks.VerifyAll(); + } + + [Test] + public void Constructor_ConfigurationNotInitialized_InitializeConfigurationBeforeUsingIt() + { + // Setup + var mocks = new MockRepository(); + var provider = mocks.Stub(); + using (var tileFetcher = new AsyncTileFetcher(provider, 50, 200)) + { + var schema = mocks.Stub(); + const string authorityCode = "EPSG:28992"; + schema.Stub(s => s.Srs).Return(authorityCode); + var extent = new Extent(10000, 123456, 987654321, 321654); + schema.Stub(s => s.Extent).Return(extent); + + var tileSource = mocks.Stub(); + tileSource.Stub(ts => ts.Schema).Return(schema); + + string legendText = ""; + var configuration = mocks.StrictMock(); + using (mocks.Ordered()) + { + configuration.Stub(c => c.Initialized).Return(false); + configuration.Expect(c => c.Initialize()); + configuration.Stub(c => c.TileSource).Return(tileSource); + configuration.Stub(c => c.LegendText).Return(legendText); + configuration.Stub(c => c.TileFetcher).Return(tileFetcher); + } + mocks.ReplayAll(); + + // Call + using (new BruTileLayer(configuration)) + { + // Only constructor call is relevant for unit test + } + } + // Assert + mocks.VerifyAll(); // Asserts method call in proper order + } + + [Test] + public void Constructor_SrsOnlyNumber_ProjectionSet() + { + // Setup + var mocks = new MockRepository(); + var provider = mocks.Stub(); + using (var tileFetcher = new AsyncTileFetcher(provider, 50, 200)) + { + const string authorityNumber = "28991"; + var schema = mocks.Stub(); + schema.Stub(s => s.Srs).Return(authorityNumber); + schema.Stub(s => s.Extent).Return(new Extent()); + + var tileSource = mocks.Stub(); + tileSource.Stub(ts => ts.Schema).Return(schema); + + var configuration = mocks.StrictMock(); + configuration.Stub(c => c.Initialized).Return(true); + configuration.Stub(c => c.TileSource).Return(tileSource); + configuration.Stub(c => c.LegendText).Return("A"); + configuration.Stub(c => c.TileFetcher).Return(tileFetcher); + mocks.ReplayAll(); + + // Call + using (var layer = new BruTileLayer(configuration)) + { + // Assert + Assert.AreEqual(AuthorityCodeHandler.Instance[$"EPSG:{authorityNumber}"], layer.Projection); + } + } + mocks.VerifyAll(); + } + + [Test] + public void Constructor_SrsAsEsriProjectionString_ProjectionSet() + { + // Setup + var mocks = new MockRepository(); + var provider = mocks.Stub(); + using (var tileFetcher = new AsyncTileFetcher(provider, 50, 200)) + { + string esriProjectionString = AuthorityCodeHandler.Instance["EPSG:2000"].ToEsriString(); + var schema = mocks.Stub(); + schema.Stub(s => s.Srs).Return(esriProjectionString); + schema.Stub(s => s.Extent).Return(new Extent()); + + var tileSource = mocks.Stub(); + tileSource.Stub(ts => ts.Schema).Return(schema); + + var configuration = mocks.StrictMock(); + configuration.Stub(c => c.Initialized).Return(true); + configuration.Stub(c => c.TileSource).Return(tileSource); + configuration.Stub(c => c.LegendText).Return("A"); + configuration.Stub(c => c.TileFetcher).Return(tileFetcher); + mocks.ReplayAll(); + + // Call + using (var layer = new BruTileLayer(configuration)) + { + // Assert + var expectedProjection = ProjectionInfo.FromEsriString(esriProjectionString); + Assert.IsTrue(expectedProjection.Equals(layer.Projection)); + } + } + mocks.VerifyAll(); + } + + [Test] + public void Constructor_SrsAsProj4String_ProjectionSet() + { + // Setup + var mocks = new MockRepository(); + var provider = mocks.Stub(); + using (var tileFetcher = new AsyncTileFetcher(provider, 50, 200)) + { + string proj4String = AuthorityCodeHandler.Instance["EPSG:2222"].ToProj4String(); + var schema = mocks.Stub(); + schema.Stub(s => s.Srs).Return(proj4String); + schema.Stub(s => s.Extent).Return(new Extent()); + + var tileSource = mocks.Stub(); + tileSource.Stub(ts => ts.Schema).Return(schema); + + var configuration = mocks.StrictMock(); + configuration.Stub(c => c.Initialized).Return(true); + configuration.Stub(c => c.TileSource).Return(tileSource); + configuration.Stub(c => c.LegendText).Return("A"); + configuration.Stub(c => c.TileFetcher).Return(tileFetcher); + mocks.ReplayAll(); + + // Call + using (var layer = new BruTileLayer(configuration)) + { + // Assert + var expectedProjection = ProjectionInfo.FromProj4String(proj4String); + Assert.IsTrue(expectedProjection.Equals(layer.Projection)); + } + } + mocks.VerifyAll(); + } + + [Test] + public void Constructor_UnknownProjectionSpecification_ProjectionSetToCorrectedWgs84() + { + // Setup + var mocks = new MockRepository(); + var provider = mocks.Stub(); + using (var tileFetcher = new AsyncTileFetcher(provider, 50, 200)) + { + const string authorityCode = "im not a projection spec"; + var schema = mocks.Stub(); + schema.Stub(s => s.Srs).Return(authorityCode); + schema.Stub(s => s.Extent).Return(new Extent()); + + var tileSource = mocks.Stub(); + tileSource.Stub(ts => ts.Schema).Return(schema); + + var configuration = mocks.StrictMock(); + configuration.Stub(c => c.Initialized).Return(true); + configuration.Stub(c => c.TileSource).Return(tileSource); + configuration.Stub(c => c.LegendText).Return("A"); + configuration.Stub(c => c.TileFetcher).Return(tileFetcher); + mocks.ReplayAll(); + + // Call + using (var layer = new BruTileLayer(configuration)) + { + // Assert + ProjectionInfo wgs84 = GetCorrectedWgs84Projection(); + Assert.IsTrue(wgs84.Equals(layer.Projection)); + } + } + mocks.VerifyAll(); + } + + [Test] + public void Constructor_SrsAsUrnFormattedString_ProjectionSet() + { + // Setup + var mocks = new MockRepository(); + var provider = mocks.Stub(); + using (var tileFetcher = new AsyncTileFetcher(provider, 50, 200)) + { + string urnCode = "urn:ogc:def:crs:EPSG:6.18.3:3857"; + var schema = mocks.Stub(); + schema.Stub(s => s.Srs).Return(urnCode); + schema.Stub(s => s.Extent).Return(new Extent()); + + var tileSource = mocks.Stub(); + tileSource.Stub(ts => ts.Schema).Return(schema); + + var configuration = mocks.StrictMock(); + configuration.Stub(c => c.Initialized).Return(true); + configuration.Stub(c => c.TileSource).Return(tileSource); + configuration.Stub(c => c.LegendText).Return("A"); + configuration.Stub(c => c.TileFetcher).Return(tileFetcher); + mocks.ReplayAll(); + + // Call + using (var layer = new BruTileLayer(configuration)) + { + // Assert + var expectedProjection = AuthorityCodeHandler.Instance["EPSG:3857"]; + Assert.IsTrue(expectedProjection.Equals(layer.Projection)); + } + } + mocks.VerifyAll(); + } + + private static ProjectionInfo GetCorrectedWgs84Projection() + { + ProjectionInfo wgs84 = AuthorityCodeHandler.Instance["EPSG:3857"]; + wgs84.GeographicInfo.Datum = KnownCoordinateSystems.Geographic.World.WGS1984.GeographicInfo.Datum; + return wgs84; + } + } +} \ No newline at end of file