Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve and simplify Mercator layers management #847

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/layer/BMNGLandsatLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
};
Expand Down
5 changes: 1 addition & 4 deletions src/layer/BMNGLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
};
Expand Down
43 changes: 10 additions & 33 deletions src/layer/BingTiledImageLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/**
Expand All @@ -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.
Expand All @@ -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,
Expand All @@ -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;
});
31 changes: 2 additions & 29 deletions src/layer/DigitalGlobeTiledImageLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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.
Expand All @@ -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;

Expand Down Expand Up @@ -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;
}
)
Expand Down
4 changes: 1 addition & 3 deletions src/layer/LandsatRestLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand Down
8 changes: 3 additions & 5 deletions src/layer/Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@
/**
* @exports Layer
*/
define([
'../util/Logger'
],
function (Logger) {
define([], function () {
"use strict";

/**
Expand All @@ -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) {

Expand All @@ -48,7 +46,7 @@ define([
* @type {String}
* @default "Layer"
*/
this.displayName = displayName ? displayName : "Layer";
this.displayName = displayName || "Layer";

/**
* Indicates whether to display this layer.
Expand Down
70 changes: 60 additions & 10 deletions src/layer/MercatorTiledImageLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@
define([
'../util/Color',
'../geom/Sector',
'../geom/Location',
'../layer/TiledImageLayer',
'../geom/Vec2',
'../util/WWMath'
],
function (Color,
Sector,
Location,
TiledImageLayer,
Vec2,
WWMath) {
Expand All @@ -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., <em>image/png</em>.
* @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 = [
Expand Down Expand Up @@ -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;
}
);
4 changes: 1 addition & 3 deletions src/layer/RestTiledImageLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
};

Expand Down
5 changes: 3 additions & 2 deletions src/layer/TiledImageLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"));
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 1 addition & 4 deletions src/layer/WmsLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 1 addition & 3 deletions src/layer/heatmap/HeatMapLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down