diff --git a/CHANGES.md b/CHANGES.md index b428377b4264..5ebeb5ff1481 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ Change Log * Fixed a bug that could cause a "readyImagery is not actually ready" exception when quickly zooming past the maximum available imagery level of an imagery layer near the poles. * Fixed a bug that caused all models to use the same highlight color. [#4798] (https://github.com/AnalyticalGraphicsInc/cesium/pull/4798) * Fixed KML for when color is an empty string [#4826](https://github.com/AnalyticalGraphicsInc/cesium/pull/4826) +* Added support for WMS version 1.3 by using CRS vice SRS query string parameter to request projection. SRS is still used for older versions. ### 1.29 - 2017-01-02 * Improved 3D Models diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e931bf2557cd..3f937c955db8 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -119,3 +119,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu * [Brad Hover](https://github.com/tekhaus) * [Hüseyin Ateş](https://github.com/ateshuseyin) * [Zsolt Simon](https://github.com/szsolt) +* [Chris Grant](https://github.com/cwgrant) diff --git a/Source/Scene/WebMapServiceImageryProvider.js b/Source/Scene/WebMapServiceImageryProvider.js index f7882cbb021d..9de05226af25 100644 --- a/Source/Scene/WebMapServiceImageryProvider.js +++ b/Source/Scene/WebMapServiceImageryProvider.js @@ -132,7 +132,19 @@ define([ } setParameter('layers', options.layers); - setParameter('srs', options.tilingScheme instanceof WebMercatorTilingScheme ? 'EPSG:3857' : 'EPSG:4326'); + + // Use SRS or CRS based on the WMS version. + if (parseFloat(parameters.version) >= 1.3) { + // Use CRS with 1.3.0 and going forward. + // For GeographicTilingScheme, use CRS:84 vice EPSG:4326 to specify lon, lat (x, y) ordering for + // bbox requests. + setParameter('crs', options.tilingScheme instanceof WebMercatorTilingScheme ? 'EPSG:3857' : 'CRS:84'); + } + else { + // SRS for WMS 1.1.0 or 1.1.1. + setParameter('srs', options.tilingScheme instanceof WebMercatorTilingScheme ? 'EPSG:3857' : 'EPSG:4326'); + } + setParameter('bbox', '{westProjected},{southProjected},{eastProjected},{northProjected}'); setParameter('width', '{width}'); setParameter('height', '{height}'); diff --git a/Specs/Scene/WebMapServiceImageryProviderSpec.js b/Specs/Scene/WebMapServiceImageryProviderSpec.js index 462499999dbc..d55572ed361e 100644 --- a/Specs/Scene/WebMapServiceImageryProviderSpec.js +++ b/Specs/Scene/WebMapServiceImageryProviderSpec.js @@ -114,7 +114,8 @@ defineSuite([ layers : 'someLayer', parameters : { something : 'foo', - another : false + another : false, + version: '1.3.0' } }); @@ -126,6 +127,10 @@ defineSuite([ var params = queryToObject(uri.query); expect(params.something).toEqual('foo'); expect(params.another).toEqual('false'); + expect(params.version).toEqual('1.3.0'); + + // Don't need to actually load image, but satisfy the request. + deferred.resolve(true); }); provider.requestImage(0, 0, 0); @@ -172,6 +177,9 @@ defineSuite([ spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { var questionMarkCount = url.match(/\?/g).length; expect(questionMarkCount).toEqual(1); + + // Don't need to actually load image, but satisfy the request. + deferred.resolve(true); }); provider.requestImage(0, 0, 0); @@ -194,6 +202,9 @@ defineSuite([ expect(questionMarkCount).toEqual(1); expect(url).not.toContain('&&'); + + // Don't need to actually load image, but satisfy the request. + deferred.resolve(true); }); provider.requestImage(0, 0, 0); @@ -218,6 +229,35 @@ defineSuite([ var uri = new Uri(url); var params = queryToObject(uri.query); expect(params.foo).toEqual('bar'); + + // Don't need to actually load image, but satisfy the request. + deferred.resolve(true); + }); + + provider.requestImage(0, 0, 0); + + expect(loadImage.createImage).toHaveBeenCalled(); + }); + }); + + it('defaults WMS version to 1.1.1', function() { + + var provider = new WebMapServiceImageryProvider({ + url : 'made/up/wms/server?foo=bar', + layers : 'someLayer' + }); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + + var uri = new Uri(url); + var params = queryToObject(uri.query); + expect(params.version).toEqual('1.1.1'); + + // Don't need to actually load image, but satisfy the request. + deferred.resolve(true); }); provider.requestImage(0, 0, 0); @@ -256,7 +296,7 @@ defineSuite([ }); }); - it('requestImage requests tiles with SRS EPSG:3857 when tiling scheme is WebMercatorTilingScheme', function() { + it('requestImage requests tiles with SRS EPSG:3857 when tiling scheme is WebMercatorTilingScheme, WMS 1.1.1', function() { var tilingScheme = new WebMercatorTilingScheme(); var provider = new WebMapServiceImageryProvider({ url : 'made/up/wms/server', @@ -281,6 +321,219 @@ defineSuite([ var params = queryToObject(uri.query); expect(params.srs).toEqual('EPSG:3857'); + expect(params.version).toEqual('1.1.1'); + + var rect = tilingScheme.tileXYToNativeRectangle(0, 0, 0); + expect(params.bbox).toEqual(rect.west + ',' + rect.south + ',' + rect.east + ',' + rect.north); + + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('requestImage requests tiles with CRS EPSG:3857 when tiling scheme is WebMercatorTilingScheme, WMS 1.3.0', function() { + var tilingScheme = new WebMercatorTilingScheme(); + var provider = new WebMapServiceImageryProvider({ + url : 'made/up/wms/server', + layers : 'someLayer', + tilingScheme : tilingScheme, + parameters: { + version: '1.3.0' + } + }); + + expect(provider.url).toEqual('made/up/wms/server'); + expect(provider.layers).toEqual('someLayer'); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(provider.tileWidth).toEqual(256); + expect(provider.tileHeight).toEqual(256); + expect(provider.maximumLevel).toBeUndefined(); + expect(provider.tilingScheme).toBeInstanceOf(WebMercatorTilingScheme); + expect(provider.rectangle).toEqual(new WebMercatorTilingScheme().rectangle); + + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + var uri = new Uri(url); + var params = queryToObject(uri.query); + + expect(params.crs).toEqual('EPSG:3857'); + expect(params.version).toEqual('1.3.0'); + + var rect = tilingScheme.tileXYToNativeRectangle(0, 0, 0); + expect(params.bbox).toEqual(rect.west + ',' + rect.south + ',' + rect.east + ',' + rect.north); + + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('requestImage requests tiles with SRS EPSG:4326 when tiling scheme is GeographicTilingScheme, WMS 1.1.1', function() { + var tilingScheme = new GeographicTilingScheme(); + var provider = new WebMapServiceImageryProvider({ + url : 'made/up/wms/server', + layers : 'someLayer', + tilingScheme : tilingScheme + }); + + expect(provider.url).toEqual('made/up/wms/server'); + expect(provider.layers).toEqual('someLayer'); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(provider.tileWidth).toEqual(256); + expect(provider.tileHeight).toEqual(256); + expect(provider.maximumLevel).toBeUndefined(); + expect(provider.tilingScheme).toBeInstanceOf(GeographicTilingScheme); + expect(provider.rectangle).toEqual(new GeographicTilingScheme().rectangle); + + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + var uri = new Uri(url); + var params = queryToObject(uri.query); + + expect(params.srs).toEqual('EPSG:4326'); + expect(params.version).toEqual('1.1.1'); + + var rect = tilingScheme.tileXYToNativeRectangle(0, 0, 0); + expect(params.bbox).toEqual(rect.west + ',' + rect.south + ',' + rect.east + ',' + rect.north); + + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('requestImage requests tiles with SRS EPSG:4326 when tiling scheme is GeographicTilingScheme, WMS 1.1.0', function() { + var tilingScheme = new GeographicTilingScheme(); + var provider = new WebMapServiceImageryProvider({ + url : 'made/up/wms/server', + layers : 'someLayer', + tilingScheme : tilingScheme, + parameters: { + version: '1.1.0' + } + }); + + expect(provider.url).toEqual('made/up/wms/server'); + expect(provider.layers).toEqual('someLayer'); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(provider.tileWidth).toEqual(256); + expect(provider.tileHeight).toEqual(256); + expect(provider.maximumLevel).toBeUndefined(); + expect(provider.tilingScheme).toBeInstanceOf(GeographicTilingScheme); + expect(provider.rectangle).toEqual(new GeographicTilingScheme().rectangle); + + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + var uri = new Uri(url); + var params = queryToObject(uri.query); + + expect(params.srs).toEqual('EPSG:4326'); + expect(params.version).toEqual('1.1.0'); + + var rect = tilingScheme.tileXYToNativeRectangle(0, 0, 0); + expect(params.bbox).toEqual(rect.west + ',' + rect.south + ',' + rect.east + ',' + rect.north); + + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('requestImage requests tiles with CRS CRS:84 when tiling scheme is GeographicTilingScheme, WMS 1.3.0', function() { + var tilingScheme = new GeographicTilingScheme(); + var provider = new WebMapServiceImageryProvider({ + url : 'made/up/wms/server', + layers : 'someLayer', + tilingScheme : tilingScheme, + parameters: { + version: '1.3.0' + } + }); + + expect(provider.url).toEqual('made/up/wms/server'); + expect(provider.layers).toEqual('someLayer'); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(provider.tileWidth).toEqual(256); + expect(provider.tileHeight).toEqual(256); + expect(provider.maximumLevel).toBeUndefined(); + expect(provider.tilingScheme).toBeInstanceOf(GeographicTilingScheme); + expect(provider.rectangle).toEqual(new GeographicTilingScheme().rectangle); + + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + var uri = new Uri(url); + var params = queryToObject(uri.query); + + expect(params.crs).toEqual('CRS:84'); + expect(params.version).toEqual('1.3.0'); + + var rect = tilingScheme.tileXYToNativeRectangle(0, 0, 0); + expect(params.bbox).toEqual(rect.west + ',' + rect.south + ',' + rect.east + ',' + rect.north); + + loadImage.defaultCreateImage('Data/Images/Red16x16.png', crossOrigin, deferred); + }); + + return provider.requestImage(0, 0, 0).then(function(image) { + expect(loadImage.createImage).toHaveBeenCalled(); + expect(image).toBeInstanceOf(Image); + }); + }); + }); + + it('requestImage requests tiles with CRS CRS:84 when tiling scheme is GeographicTilingScheme, WMS 1.3.1', function() { + var tilingScheme = new GeographicTilingScheme(); + var provider = new WebMapServiceImageryProvider({ + url : 'made/up/wms/server', + layers : 'someLayer', + tilingScheme : tilingScheme, + parameters: { + version: '1.3.1' + } + }); + + expect(provider.url).toEqual('made/up/wms/server'); + expect(provider.layers).toEqual('someLayer'); + + return pollToPromise(function() { + return provider.ready; + }).then(function() { + expect(provider.tileWidth).toEqual(256); + expect(provider.tileHeight).toEqual(256); + expect(provider.maximumLevel).toBeUndefined(); + expect(provider.tilingScheme).toBeInstanceOf(GeographicTilingScheme); + expect(provider.rectangle).toEqual(new GeographicTilingScheme().rectangle); + + spyOn(loadImage, 'createImage').and.callFake(function(url, crossOrigin, deferred) { + var uri = new Uri(url); + var params = queryToObject(uri.query); + + expect(params.crs).toEqual('CRS:84'); + expect(params.version).toEqual('1.3.1'); var rect = tilingScheme.tileXYToNativeRectangle(0, 0, 0); expect(params.bbox).toEqual(rect.west + ',' + rect.south + ',' + rect.east + ',' + rect.north); @@ -669,6 +922,8 @@ defineSuite([ enablePickFeatures : false }); + expect(provider.enablePickFeatures).toBe(false); + return pollToPromise(function() { return provider.ready; }).then(function() { @@ -684,6 +939,7 @@ defineSuite([ }); provider.enablePickFeatures = false; + expect(provider.enablePickFeatures).toBe(false); return pollToPromise(function() { return provider.ready; @@ -700,6 +956,7 @@ defineSuite([ }); provider.enablePickFeatures = true; + expect(provider.enablePickFeatures).toBe(true); return pollToPromise(function() { return provider.ready;