diff --git a/src/layer/BMNGLandsatLayer.js b/src/layer/BMNGLandsatLayer.js index 388a9531b..e3fa665a1 100644 --- a/src/layer/BMNGLandsatLayer.js +++ b/src/layer/BMNGLandsatLayer.js @@ -49,12 +49,9 @@ define([ */ var BMNGLandsatLayer = function () { // This LevelSet configuration captures the Landsat resolution of 1.38889E-04 degrees/pixel - TiledImageLayer.call(this, + TiledImageLayer.call(this, "Blue Marble & Landsat", Sector.FULL_SPHERE, new Location(45, 45), 12, "image/jpeg", "BMNGLandsat256", 256, 256); - this.displayName = "Blue Marble & Landsat"; - this.pickEnabled = false; - this.urlBuilder = new WmsUrlBuilder("https://worldwind25.arc.nasa.gov/wms", "BlueMarble-200405,esat", "", "1.3.0"); }; diff --git a/src/layer/BMNGLayer.js b/src/layer/BMNGLayer.js index 854b3b943..da5f12ab1 100644 --- a/src/layer/BMNGLayer.js +++ b/src/layer/BMNGLayer.js @@ -52,12 +52,9 @@ define([ */ var BMNGLayer = function (layerName) { // This LevelSet configuration captures the Blue Marble resolution of 4.166666667E-03 degrees/pixel - TiledImageLayer.call(this, + TiledImageLayer.call(this, "Blue Marble", Sector.FULL_SPHERE, new Location(45, 45), 7, "image/jpeg", layerName || "BMNG256", 256, 256); - this.displayName = "Blue Marble"; - this.pickEnabled = false; - this.urlBuilder = new WmsUrlBuilder("https://worldwind25.arc.nasa.gov/wms", layerName || "BlueMarble-200405", "", "1.3.0"); }; diff --git a/src/layer/BingTiledImageLayer.js b/src/layer/BingTiledImageLayer.js index 2731c4f40..b9d2b9869 100644 --- a/src/layer/BingTiledImageLayer.js +++ b/src/layer/BingTiledImageLayer.js @@ -29,21 +29,15 @@ * @exports BingTiledImageLayer */ define([ - '../geom/Angle', '../util/Color', - '../geom/Location', - '../util/Offset', '../shapes/ScreenImage', - '../geom/Sector', - '../layer/MercatorTiledImageLayer' + '../layer/MercatorTiledImageLayer', + '../WorldWind' ], - function (Angle, - Color, - Location, - Offset, + function (Color, ScreenImage, - Sector, - MercatorTiledImageLayer) { + MercatorTiledImageLayer, + WorldWind) { "use strict"; /** @@ -58,18 +52,16 @@ define([ * @param {String} displayName This layer's display name. */ var BingTiledImageLayer = function (displayName) { - this.imageSize = 256; - - MercatorTiledImageLayer.call(this, - new Sector(-85.05, 85.05, -180, 180), new Location(85.05, 180), 23, "image/jpeg", displayName, - this.imageSize, this.imageSize); - - this.displayName = displayName; + MercatorTiledImageLayer.call(this, displayName, 23, "image/jpeg", displayName, 256, 1); // TODO: Picking is enabled as a temporary measure for screen credit hyperlinks to work (see Layer.render) this.pickEnabled = true; this.detectBlankImages = true; + + // Set the detail control so the resolution is a close match + // to the resolution on the Bing maps website + this.detailControl = 1.25; }; // Internal use only. Intentionally not documented. @@ -88,16 +80,6 @@ define([ } }; - // Overridden from TiledImageLayer. - BingTiledImageLayer.prototype.createTopLevelTiles = function (dc) { - this.topLevelTiles = []; - - this.topLevelTiles.push(this.createTile(null, this.levels.firstLevel(), 0, 0)); - this.topLevelTiles.push(this.createTile(null, this.levels.firstLevel(), 0, 1)); - this.topLevelTiles.push(this.createTile(null, this.levels.firstLevel(), 1, 0)); - this.topLevelTiles.push(this.createTile(null, this.levels.firstLevel(), 1, 1)); - }; - BingTiledImageLayer.prototype.renderLogo = function (dc) { if (!BingTiledImageLayer.logoImage) { BingTiledImageLayer.logoImage = new ScreenImage(WorldWind.configuration.bingLogoPlacement, @@ -113,10 +95,5 @@ define([ } }; - // Determines the Bing map size for a specified level number. - BingTiledImageLayer.prototype.mapSizeForLevel = function (levelNumber) { - return 256 << (levelNumber + 1); - }; - return BingTiledImageLayer; }); diff --git a/src/layer/DigitalGlobeTiledImageLayer.js b/src/layer/DigitalGlobeTiledImageLayer.js index c5d6b52f9..26b33c148 100644 --- a/src/layer/DigitalGlobeTiledImageLayer.js +++ b/src/layer/DigitalGlobeTiledImageLayer.js @@ -29,20 +29,14 @@ * @exports DigitalGlobeTiledImageLayer */ define([ - '../geom/Angle', '../error/ArgumentError', '../util/Color', - '../geom/Location', '../util/Logger', - '../geom/Sector', '../layer/MercatorTiledImageLayer' ], - function (Angle, - ArgumentError, + function (ArgumentError, Color, - Location, Logger, - Sector, MercatorTiledImageLayer) { "use strict"; @@ -73,12 +67,7 @@ define([ "The access token is null or undefined.")); } - this.imageSize = 256; - displayName = displayName || "Digital Globe"; - - MercatorTiledImageLayer.call(this, - new Sector(-85.05, 85.05, -180, 180), new Location(85.05, 180), 19, "image/jpeg", displayName, - this.imageSize, this.imageSize); + MercatorTiledImageLayer.call(this, displayName || "Digital Globe", 19, "image/jpeg", displayName, 256, 1); /** * The map ID identifying the dataset displayed by this layer. @@ -94,7 +83,6 @@ define([ this.accessToken = accessToken; //"pk.eyJ1IjoiZGlnaXRhbGdsb2JlIiwiYSI6IjljZjQwNmEyMTNhOWUyMWM5NWUzYWIwOGNhYTY2ZDViIn0.Ju3tOUUUc0C_gcCSAVpFIA"; - this.displayName = displayName; // TODO: Picking is enabled as a temporary measure for screen credit hyperlinks to work (see Layer.render) this.pickEnabled = true; @@ -156,21 +144,6 @@ define([ } }; - // Overridden from TiledImageLayer. - DigitalGlobeTiledImageLayer.prototype.createTopLevelTiles = function (dc) { - this.topLevelTiles = []; - - this.topLevelTiles.push(this.createTile(null, this.levels.firstLevel(), 0, 0)); - this.topLevelTiles.push(this.createTile(null, this.levels.firstLevel(), 0, 1)); - this.topLevelTiles.push(this.createTile(null, this.levels.firstLevel(), 1, 0)); - this.topLevelTiles.push(this.createTile(null, this.levels.firstLevel(), 1, 1)); - }; - - // Determines the Bing map size for a specified level number. - DigitalGlobeTiledImageLayer.prototype.mapSizeForLevel = function (levelNumber) { - return 256 << (levelNumber + 1); - }; - return DigitalGlobeTiledImageLayer; } ) diff --git a/src/layer/LandsatRestLayer.js b/src/layer/LandsatRestLayer.js index 8d984558e..163b0b92c 100644 --- a/src/layer/LandsatRestLayer.js +++ b/src/layer/LandsatRestLayer.js @@ -63,10 +63,8 @@ define([ var LandsatRestLayer = function (serverAddress, pathToData, displayName) { var cachePath = WWUtil.urlPath(serverAddress + "/" + pathToData); - TiledImageLayer.call(this, Sector.FULL_SPHERE, new Location(36, 36), 10, "image/png", cachePath, 512, 512); + TiledImageLayer.call(this, displayName, Sector.FULL_SPHERE, new Location(36, 36), 10, "image/png", cachePath, 512, 512); - this.displayName = displayName; - this.pickEnabled = false; this.urlBuilder = new LevelRowColumnUrlBuilder(serverAddress, pathToData); }; diff --git a/src/layer/Layer.js b/src/layer/Layer.js index e5883aceb..acb13ae8b 100644 --- a/src/layer/Layer.js +++ b/src/layer/Layer.js @@ -28,10 +28,7 @@ /** * @exports Layer */ -define([ - '../util/Logger' - ], - function (Logger) { +define([], function () { "use strict"; /** @@ -40,6 +37,7 @@ define([ * @constructor * @classdesc Provides an abstract base class for layer implementations. This class is not meant to be instantiated * directly. + * @param {String} displayName This layer's display name. */ var Layer = function (displayName) { @@ -48,7 +46,7 @@ define([ * @type {String} * @default "Layer" */ - this.displayName = displayName ? displayName : "Layer"; + this.displayName = displayName || "Layer"; /** * Indicates whether to display this layer. diff --git a/src/layer/MercatorTiledImageLayer.js b/src/layer/MercatorTiledImageLayer.js index 7381a99ed..baa6958c4 100644 --- a/src/layer/MercatorTiledImageLayer.js +++ b/src/layer/MercatorTiledImageLayer.js @@ -31,12 +31,14 @@ define([ '../util/Color', '../geom/Sector', + '../geom/Location', '../layer/TiledImageLayer', '../geom/Vec2', '../util/WWMath' ], function (Color, Sector, + Location, TiledImageLayer, Vec2, WWMath) { @@ -49,25 +51,43 @@ define([ * @augments TiledImageLayer * @classdesc Provides an abstract layer to support Mercator layers. * - * @param {Sector} sector The sector this layer covers. - * @param {Location} levelZeroDelta The size in latitude and longitude of level zero (lowest resolution) tiles. + * @param {String} displayName This layer's display name. * @param {Number} numLevels The number of levels to define for the layer. Each level is successively one power * of two higher resolution than the next lower-numbered level. (0 is the lowest resolution level, 1 is twice * that resolution, etc.) * Each level contains four times as many tiles as the next lower-numbered level, each 1/4 the geographic size. * @param {String} imageFormat The mime type of the image format for the layer's tiles, e.g., image/png. * @param {String} cachePath A string uniquely identifying this layer relative to other layers. - * @param {Number} tileWidth The horizontal size of image tiles in pixels. - * @param {Number} tileHeight The vertical size of image tiles in pixels. - * @throws {ArgumentError} If any of the specified sector, level-zero delta, cache path or image format arguments are - * null or undefined, or if the specified number of levels, tile width or tile height is less than 1. + * @param {Number} imageSize The horizontal and vertical size of image tiles in pixels. + * @param {Number} firstLevelOffset The level offset to skip applying one tile over whole globe and start from e.g. 8x8 tiles. + * @throws {ArgumentError} If any of the specified cache path or image format arguments are + * null or undefined, or if the specified number of levels or tile size is less than 1. */ - var MercatorTiledImageLayer = function (sector, levelZeroDelta, numLevels, imageFormat, cachePath, - tileWidth, tileHeight) { - TiledImageLayer.call(this, - sector, levelZeroDelta, numLevels, imageFormat, cachePath, tileWidth, tileHeight); + var MercatorTiledImageLayer = function (displayName, numLevels, imageFormat, cachePath, imageSize, firstLevelOffset) { + + function gudermannian(percent) { + var x = percent * Math.PI; + // var sinh = (Math.exp(x) - Math.exp(-x)) / 2; + var y = Math.exp(x); + var sinh = (y - 1 / y) / 2; + return Math.atan(sinh) * 180 / Math.PI; + } + + function levelZeroDelta(firstLevelOffset) { + var levelZeroDelta = 360 / (1 << firstLevelOffset); + return new Location(levelZeroDelta / 2, levelZeroDelta); + } + + var sector = new Sector( + gudermannian(-1), gudermannian(1), -180, 180 + ); + + TiledImageLayer.call(this, displayName, + sector, levelZeroDelta(firstLevelOffset), numLevels - firstLevelOffset, imageFormat, cachePath, imageSize, imageSize); this.detectBlankImages = false; + this.imageSize = imageSize; + this.firstLevelOffset = firstLevelOffset; // These pixels are tested in retrieved images to determine whether the image is blank. this.testPixels = [ @@ -189,6 +209,36 @@ define([ return true; }; + /** + * Calculates map size in pixels for specified level. + * + * @param {Number} levelNumber The number of level to calculate map size for. + */ + MercatorTiledImageLayer.prototype.mapSizeForLevel = function(levelNumber) { + return this.imageSize << (levelNumber + this.firstLevelOffset); + }; + + // Overridden from TiledImageLayer to add possibility to create simple child layers with URL builder built-in. + MercatorTiledImageLayer.prototype.resourceUrlForTile = function(tile, imageFormat) { + if (this.urlBuilder) { + return this.urlBuilder.urlForTile(tile, imageFormat); + } else { + return this.getImageSourceUrl(tile.column, tile.row, tile.level.levelNumber + this.firstLevelOffset); + } + }; + + /** + * Simple version of URL builder based on commonly used by online maps input parameters x, y and z. + * + * @param {Number} x The X coordinate of tile. + * @param {Number} y The Y coordinate of tile. + * @param {Number} z The zoom level of tile. + */ + MercatorTiledImageLayer.prototype.getImageSourceUrl = function(x, y, z) { + // Intentionally empty. Can be override in child layer and return URL for specified tile instead of builder + return null; + }; + return MercatorTiledImageLayer; } ); \ No newline at end of file diff --git a/src/layer/RestTiledImageLayer.js b/src/layer/RestTiledImageLayer.js index bf3c4b41c..844959916 100644 --- a/src/layer/RestTiledImageLayer.js +++ b/src/layer/RestTiledImageLayer.js @@ -72,7 +72,7 @@ define([ var RestTiledImageLayer = function (serverAddress, pathToData, displayName, configuration) { var cachePath = WWUtil.urlPath(serverAddress + "/" + pathToData); - TiledImageLayer.call(this, + TiledImageLayer.call(this, displayName, (configuration && configuration.sector) || Sector.FULL_SPHERE, (configuration && configuration.levelZeroTileDelta) || new Location(45, 45), (configuration && configuration.numLevels) || 5, @@ -81,8 +81,6 @@ define([ (configuration && configuration.tileWidth) || 256, (configuration && configuration.tileHeight) || 256); - this.displayName = displayName; - this.pickEnabled = false; this.urlBuilder = new LevelRowColumnUrlBuilder(serverAddress, pathToData); }; diff --git a/src/layer/TiledImageLayer.js b/src/layer/TiledImageLayer.js index a7202edb6..332ecd207 100644 --- a/src/layer/TiledImageLayer.js +++ b/src/layer/TiledImageLayer.js @@ -73,6 +73,7 @@ define([ * Layers of this type are by default not pickable. Their pick-enabled flag is initialized to false. * * @augments Layer + * @param {String} displayName This layer's display name. * @param {Sector} sector The sector this layer covers. * @param {Location} levelZeroDelta The size in latitude and longitude of level zero (lowest resolution) tiles. * @param {Number} numLevels The number of levels to define for the layer. Each level is successively one power @@ -87,7 +88,7 @@ define([ * null or undefined, or if the specified number of levels, tile width or tile height is less than 1. * */ - var TiledImageLayer = function (sector, levelZeroDelta, numLevels, imageFormat, cachePath, tileWidth, tileHeight) { + var TiledImageLayer = function (displayName, sector, levelZeroDelta, numLevels, imageFormat, cachePath, tileWidth, tileHeight) { if (!sector) { throw new ArgumentError( Logger.logMessage(Logger.LEVEL_SEVERE, "TiledImageLayer", "constructor", "missingSector")); @@ -123,7 +124,7 @@ define([ "The specified tile width or height is less than one.")); } - Layer.call(this, "Tiled Image Layer"); + Layer.call(this, displayName || "Tiled Image Layer"); this.retrievalImageFormat = imageFormat; this.cachePath = cachePath; diff --git a/src/layer/WmsLayer.js b/src/layer/WmsLayer.js index 650f205dd..1d75f8094 100644 --- a/src/layer/WmsLayer.js +++ b/src/layer/WmsLayer.js @@ -82,12 +82,9 @@ define([ cachePath = cachePath + timeString; } - TiledImageLayer.call(this, config.sector, config.levelZeroDelta, config.numLevels, config.format, + TiledImageLayer.call(this, config.title, config.sector, config.levelZeroDelta, config.numLevels, config.format, cachePath, config.size, config.size); - this.displayName = config.title; - this.pickEnabled = false; - this.urlBuilder = new WmsUrlBuilder(config.service, config.layerNames, config.styleNames, config.version, timeString); if (config.coordinateSystem) { diff --git a/src/layer/heatmap/HeatMapLayer.js b/src/layer/heatmap/HeatMapLayer.js index 30cd7664e..4272482c3 100644 --- a/src/layer/heatmap/HeatMapLayer.js +++ b/src/layer/heatmap/HeatMapLayer.js @@ -69,9 +69,7 @@ define([ this.tileWidth = 256; this.tileHeight = 256; - TiledImageLayer.call(this, new Sector(-90, 90, -180, 180), new Location(45, 45), numLevels || 18, 'image/png', 'HeatMap' + WWUtil.guid(), this.tileWidth, this.tileHeight); - - this.displayName = displayName; + TiledImageLayer.call(this, displayName, new Sector(-90, 90, -180, 180), new Location(45, 45), numLevels || 18, 'image/png', 'HeatMap' + WWUtil.guid(), this.tileWidth, this.tileHeight); var data = {}; for (var lat = -90; lat <= 90; lat++) {