Merge branch 'master' of github.com:openlayers/ol3 into vector

This commit is contained in:
Tim Schaub
2013-03-05 10:58:27 +01:00
46 changed files with 541 additions and 358 deletions

View File

@@ -168,11 +168,13 @@ ol.control.ScaleLine.prototype.updateElement_ = function(frameState) {
this.toEPSG4326_ = null;
cosLatitude = Math.cos(goog.math.toRadians(center.y));
pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180;
projectionUnits = ol.ProjectionUnits.METERS;
} else if (projectionUnits == ol.ProjectionUnits.METERS &&
} else if ((projectionUnits == ol.ProjectionUnits.FEET ||
projectionUnits == ol.ProjectionUnits.METERS) &&
this.units_ == ol.control.ScaleLineUnits.DEGREES) {
// Convert pointResolution from meters to degrees
// Convert pointResolution from meters or feet to degrees
if (goog.isNull(this.toEPSG4326_)) {
this.toEPSG4326_ = ol.projection.getTransform(
projection, ol.projection.getFromCode('EPSG:4326'));
@@ -180,20 +182,26 @@ ol.control.ScaleLine.prototype.updateElement_ = function(frameState) {
var vertex = [center.x, center.y];
vertex = this.toEPSG4326_(vertex, vertex, 2);
cosLatitude = Math.cos(goog.math.toRadians(vertex[1]));
pointResolution *= 180 / (Math.PI * cosLatitude * ol.sphere.NORMAL.radius);
var radius = ol.sphere.NORMAL.radius;
if (projectionUnits == ol.ProjectionUnits.FEET) {
radius /= 0.3048;
}
pointResolution *= 180 / (Math.PI * cosLatitude * radius);
projectionUnits = ol.ProjectionUnits.DEGREES;
} else {
this.toEPSG4326_ = null;
goog.asserts.assert(
((this.units_ == ol.control.ScaleLineUnits.METRIC ||
this.units_ == ol.control.ScaleLineUnits.IMPERIAL) &&
projectionUnits == ol.ProjectionUnits.METERS) ||
(this.units_ == ol.control.ScaleLineUnits.DEGREES &&
projectionUnits == ol.ProjectionUnits.DEGREES));
}
goog.asserts.assert(
((this.units_ == ol.control.ScaleLineUnits.METRIC ||
this.units_ == ol.control.ScaleLineUnits.IMPERIAL) &&
projectionUnits == ol.ProjectionUnits.METERS) ||
(this.units_ == ol.control.ScaleLineUnits.DEGREES &&
projectionUnits == ol.ProjectionUnits.DEGREES));
var nominalCount = this.minWidth_ * pointResolution;
var suffix = '';
if (this.units_ == ol.control.ScaleLineUnits.DEGREES) {

View File

@@ -1,31 +1,28 @@
goog.provide('ol.ImageUrlFunction');
goog.provide('ol.ImageUrlFunctionType');
goog.require('goog.uri.utils');
goog.require('ol.Extent');
goog.require('ol.Size');
goog.require('ol.source.wms');
/**
* @typedef {function(ol.Extent, ol.Size): (string|undefined)}
* @typedef {function(ol.Extent, ol.Size, ol.Projection): (string|undefined)}
*/
ol.ImageUrlFunctionType;
/**
* @param {string} baseUrl Base URL (may have query data).
* @param {string} axisOrientation Axis orientation.
* @param {Object.<string, string|number>} params WMS parameters.
* @param {string=} opt_version WMS version.
* @return {ol.ImageUrlFunctionType} Image URL function.
*/
ol.ImageUrlFunction.createBboxParam = function(baseUrl, axisOrientation) {
return function(extent, size) {
var bboxValues = axisOrientation.substr(0, 2) == 'ne' ?
[extent.minY, extent.minX, extent.maxY, extent.maxX] :
[extent.minX, extent.minY, extent.maxX, extent.maxY];
return goog.uri.utils.appendParams(baseUrl,
'BBOX', bboxValues.join(','),
'HEIGHT', size.height,
'WIDTH', size.width);
ol.ImageUrlFunction.createWMSParams =
function(baseUrl, params, opt_version) {
return function(extent, size, projection) {
return ol.source.wms.getUrl(
baseUrl, params, extent, size, projection, opt_version);
};
};

View File

@@ -28,6 +28,7 @@ ol.HAVE_PROJ4JS = ol.ENABLE_PROJ4JS && typeof Proj4js == 'object';
*/
ol.ProjectionUnits = {
DEGREES: 'degrees',
FEET: 'ft',
METERS: 'm'
};
@@ -67,6 +68,12 @@ ol.Projection = function(code, units, extent, opt_axisOrientation) {
this.axisOrientation_ = goog.isDef(opt_axisOrientation) ?
opt_axisOrientation : 'enu';
/**
* @private
* @type {ol.tilegrid.TileGrid}
*/
this.defaultTileGrid_ = null;
};
@@ -110,6 +117,22 @@ ol.Projection.prototype.getAxisOrientation = function() {
};
/**
* @return {ol.tilegrid.TileGrid} The default tile grid.
*/
ol.Projection.prototype.getDefaultTileGrid = function() {
return this.defaultTileGrid_;
};
/**
* @param {ol.tilegrid.TileGrid} tileGrid The default tile grid.
*/
ol.Projection.prototype.setDefaultTileGrid = function(tileGrid) {
this.defaultTileGrid_ = tileGrid;
};
/**
* @constructor
@@ -168,7 +191,13 @@ ol.Proj4jsProjection_.prototype.getPointResolution =
var height = ol.sphere.NORMAL.haversineDistance(
new ol.Coordinate(vertices[4], vertices[5]),
new ol.Coordinate(vertices[6], vertices[7]));
return (width + height) / 2;
var pointResolution = (width + height) / 2;
if (this.getUnits() == ol.ProjectionUnits.FEET) {
// The radius of the normal sphere is defined in meters, so we must
// convert back to feet.
pointResolution /= 0.3048;
}
return pointResolution;
}
};

View File

@@ -79,7 +79,8 @@ ol.renderer.canvas.ImageLayer.prototype.renderFrame =
var hints = frameState.viewHints;
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) {
image = imageSource.getImage(frameState.extent, viewResolution);
image = imageSource.getImage(
frameState.extent, viewResolution, view2DState.projection);
if (!goog.isNull(image)) {
var imageState = image.getState();
if (imageState == ol.ImageState.IDLE) {

View File

@@ -1,4 +1,3 @@
// FIXME don't redraw tiles if not needed
// FIXME find correct globalCompositeOperation
// FIXME optimize :-)
@@ -51,6 +50,12 @@ ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) {
*/
this.transform_ = goog.vec.Mat4.createNumber();
/**
* @private
* @type {Array.<ol.Tile|undefined>}
*/
this.renderedTiles_ = null;
};
goog.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.Layer);
@@ -86,20 +91,25 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
function(frameState, layerState) {
var view2DState = frameState.view2DState;
var projection = view2DState.projection;
var tileLayer = this.getTileLayer();
var tileSource = tileLayer.getTileSource();
var tileSourceKey = goog.getUid(tileSource).toString();
var tileGrid = tileSource.getTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = ol.tilegrid.getForProjection(projection);
}
var z = tileGrid.getZForResolution(view2DState.resolution);
var tileSize = tileGrid.getTileSize(z);
var tileResolution = tileGrid.getResolution(z);
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
frameState.extent, tileResolution);
var tileRangeWidth = tileRange.getWidth();
var tileRangeHeight = tileRange.getHeight();
var canvasSize = new ol.Size(
tileSize.width * tileRange.getWidth(),
tileSize.height * tileRange.getHeight());
tileSize.width * tileRangeWidth, tileSize.height * tileRangeHeight);
var canvas, context;
if (goog.isNull(this.canvas_)) {
@@ -111,6 +121,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
this.canvas_ = canvas;
this.canvasSize_ = canvasSize;
this.context_ = context;
this.renderedTiles_ = new Array(tileRangeWidth * tileRangeHeight);
} else {
canvas = this.canvas_;
context = this.context_;
@@ -118,22 +129,21 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
canvas.width = canvasSize.width;
canvas.height = canvasSize.height;
this.canvasSize_ = canvasSize;
this.renderedTiles_ = new Array(tileRangeWidth * tileRangeHeight);
}
}
context.clearRect(0, 0, canvasSize.width, canvasSize.height);
/**
* @type {Object.<number, Object.<string, ol.Tile>>}
*/
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};
var isLoaded = function(tile) {
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED;
};
}, tileSource, tileGrid, projection);
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, isLoaded);
tilesToDrawByZ, getTileIfLoaded);
var allTilesLoaded = true;
var tile, tileCenter, tileCoord, tileState, x, y;
@@ -141,7 +151,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tileCoord = new ol.TileCoord(z, x, y);
tile = tileSource.getTile(tileCoord);
tile = tileSource.getTile(tileCoord, tileGrid, projection);
if (goog.isNull(tile)) {
continue;
}
@@ -169,9 +179,12 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
/** @type {Array.<number>} */
var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number);
goog.array.sort(zs);
var opaque = tileSource.getOpaque();
var origin = tileGrid.getTileCoordExtent(
new ol.TileCoord(z, tileRange.minX, tileRange.maxY)).getTopLeft();
var currentZ, i, scale, tileCoordKey, tileExtent, tilesToDraw;
var currentZ, i, index, scale, tileCoordKey, tileExtent, tilesToDraw;
var ix, iy, interimTileExtent, interimTileRange, maxX, maxY, minX, minY;
var height, width;
for (i = 0; i < zs.length; ++i) {
currentZ = zs[i];
tileSize = tileGrid.getTileSize(currentZ);
@@ -179,28 +192,50 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame =
if (currentZ == z) {
for (tileCoordKey in tilesToDraw) {
tile = tilesToDraw[tileCoordKey];
context.drawImage(
tile.getImage(),
tileSize.width * (tile.tileCoord.x - tileRange.minX),
tileSize.height * (tileRange.maxY - tile.tileCoord.y));
tileCoord = tile.tileCoord;
index = (tileCoord.y - tileRange.minY) * tileRangeWidth +
(tileCoord.x - tileRange.minX);
if (this.renderedTiles_[index] != tile) {
x = tileSize.width * (tile.tileCoord.x - tileRange.minX);
y = tileSize.height * (tileRange.maxY - tile.tileCoord.y);
if (!opaque) {
context.clearRect(x, y, tileSize.width, tileSize.height);
}
context.drawImage(tile.getImage(), x, y);
this.renderedTiles_[index] = tile;
}
}
} else {
scale = tileGrid.getResolution(currentZ) / tileResolution;
for (tileCoordKey in tilesToDraw) {
tile = tilesToDraw[tileCoordKey];
tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord);
context.drawImage(
tile.getImage(),
(tileExtent.minX - origin.x) / tileResolution,
(origin.y - tileExtent.maxY) / tileResolution,
scale * tileSize.width,
scale * tileSize.height);
x = (tileExtent.minX - origin.x) / tileResolution;
y = (origin.y - tileExtent.maxY) / tileResolution;
width = scale * tileSize.width;
height = scale * tileSize.height;
if (!opaque) {
context.clearRect(x, y, width, height);
}
context.drawImage(tile.getImage(), x, y, width, height);
interimTileRange =
tileGrid.getTileRangeForExtentAndZ(tileExtent, z);
minX = Math.max(interimTileRange.minX, tileRange.minX);
maxX = Math.min(interimTileRange.maxX, tileRange.maxX);
minY = Math.max(interimTileRange.minY, tileRange.minY);
maxY = Math.min(interimTileRange.maxY, tileRange.maxY);
for (ix = minX; ix <= maxX; ++ix) {
for (iy = minY; iy <= maxY; ++iy) {
this.renderedTiles_[(iy - tileRange.minY) * tileRangeWidth +
(ix - tileRange.minX)] = undefined;
}
}
}
}
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
tileSource.useLowResolutionTiles(z, frameState.extent);
tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid);
this.scheduleExpireCache(frameState, tileSource);
var transform = this.transform_;

View File

@@ -67,7 +67,8 @@ ol.renderer.dom.ImageLayer.prototype.renderFrame =
var hints = frameState.viewHints;
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) {
var image_ = imageSource.getImage(frameState.extent, viewResolution);
var image_ = imageSource.getImage(
frameState.extent, viewResolution, view2DState.projection);
if (!goog.isNull(image_)) {
var imageState = image_.getState();
if (imageState == ol.ImageState.IDLE) {

View File

@@ -79,11 +79,15 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
}
var view2DState = frameState.view2DState;
var projection = view2DState.projection;
var tileLayer = this.getTileLayer();
var tileSource = tileLayer.getTileSource();
var tileSourceKey = goog.getUid(tileSource).toString();
var tileGrid = tileSource.getTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = ol.tilegrid.getForProjection(projection);
}
var z = tileGrid.getZForResolution(view2DState.resolution);
var tileResolution = tileGrid.getResolution(z);
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
@@ -93,11 +97,11 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};
var isLoaded = function(tile) {
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED;
};
}, tileSource, tileGrid, projection);
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, isLoaded);
tilesToDrawByZ, getTileIfLoaded);
var allTilesLoaded = true;
var tile, tileCenter, tileCoord, tileState, x, y;
@@ -105,7 +109,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tileCoord = new ol.TileCoord(z, x, y);
tile = tileSource.getTile(tileCoord);
tile = tileSource.getTile(tileCoord, tileGrid, projection);
if (goog.isNull(tile)) {
continue;
}
@@ -216,7 +220,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
tileSource.useLowResolutionTiles(z, frameState.extent);
tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid);
this.scheduleExpireCache(frameState, tileSource);
};

View File

@@ -258,3 +258,20 @@ ol.renderer.Layer.prototype.updateWantedTiles =
}
wantedTiles[tileSourceKey][coordKey] = true;
};
/**
* @param {function(ol.Tile): boolean} isLoadedFunction Function to
* determine if the tile is loaded.
* @param {ol.source.TileSource} tileSource Tile source.
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
* @param {ol.Projection} projection Projection.
* @return {function(ol.TileCoord): ol.Tile} Returns a tile if it is loaded.
*/
ol.renderer.Layer.prototype.createGetTileIfLoadedFunction =
function(isLoadedFunction, tileSource, tileGrid, projection) {
return function(tileCoord) {
var tile = tileSource.getTile(tileCoord, tileGrid, projection);
return isLoadedFunction(tile) ? tile : null;
};
};

View File

@@ -160,7 +160,8 @@ ol.renderer.webgl.ImageLayer.prototype.renderFrame =
var hints = frameState.viewHints;
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) {
var image_ = imageSource.getImage(frameState.extent, viewResolution);
var image_ = imageSource.getImage(
frameState.extent, viewResolution, view2DState.projection);
if (!goog.isNull(image_)) {
var imageState = image_.getState();
if (imageState == ol.ImageState.IDLE) {

View File

@@ -281,12 +281,16 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
var gl = mapRenderer.getGL();
var view2DState = frameState.view2DState;
var projection = view2DState.projection;
var center = view2DState.center;
var tileLayer = this.getTileLayer();
var tileSource = tileLayer.getTileSource();
var tileSourceKey = goog.getUid(tileSource).toString();
var tileGrid = tileSource.getTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = ol.tilegrid.getForProjection(projection);
}
var z = tileGrid.getZForResolution(view2DState.resolution);
var tileResolution = tileGrid.getResolution(z);
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
@@ -365,12 +369,12 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};
var isLoaded = function(tile) {
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED &&
mapRenderer.isTileTextureLoaded(tile);
};
}, tileSource, tileGrid, projection);
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, isLoaded);
tilesToDrawByZ, getTileIfLoaded);
var tilesToLoad = new goog.structs.PriorityQueue();
@@ -380,7 +384,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tileCoord = new ol.TileCoord(z, x, y);
tile = tileSource.getTile(tileCoord);
tile = tileSource.getTile(tileCoord, tileGrid, projection);
if (goog.isNull(tile)) {
continue;
}
@@ -459,7 +463,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
tileSource.useLowResolutionTiles(z, frameState.extent);
tileSource.useLowResolutionTiles(z, frameState.extent, tileGrid);
this.scheduleExpireCache(frameState, tileSource);
goog.vec.Mat4.makeIdentity(this.texCoordMatrix_);

View File

@@ -23,6 +23,7 @@ goog.require('ol.tilegrid.XYZ');
ol.source.BingMaps = function(bingMapsOptions) {
goog.base(this, {
opaque: true,
projection: ol.projection.getFromCode('EPSG:3857')
});

View File

@@ -90,6 +90,7 @@ ol.source.DebugTileSource = function(options) {
goog.base(this, {
extent: options.extent,
opaque: false,
projection: options.projection,
tileGrid: options.tileGrid
});

View File

@@ -76,12 +76,13 @@ goog.inherits(ol.source.ImageSource, ol.source.Source);
* @param {ol.Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {ol.Size} size Size.
* @param {ol.Projection} projection Projection.
* @return {ol.Image} Single image.
*/
ol.source.ImageSource.prototype.createImage =
function(extent, resolution, size) {
function(extent, resolution, size, projection) {
var image = null;
var imageUrl = this.imageUrlFunction(extent, size);
var imageUrl = this.imageUrlFunction(extent, size, projection);
if (goog.isDef(imageUrl)) {
image = new ol.Image(
extent, resolution, imageUrl, this.crossOrigin_,
@@ -109,6 +110,7 @@ ol.source.ImageSource.prototype.findNearestResolution =
/**
* @param {ol.Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {ol.Projection} projection Projection.
* @return {ol.Image} Single image.
*/
ol.source.ImageSource.prototype.getImage = goog.abstractMethod;

View File

@@ -7,7 +7,6 @@ goog.require('ol.ImageTile');
goog.require('ol.Projection');
goog.require('ol.Tile');
goog.require('ol.TileCache');
goog.require('ol.TileCoord');
goog.require('ol.TileUrlFunction');
goog.require('ol.TileUrlFunctionType');
goog.require('ol.source.TileSource');
@@ -18,6 +17,7 @@ goog.require('ol.tilegrid.TileGrid');
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* crossOrigin: (null|string|undefined),
* extent: (ol.Extent|undefined),
* opaque: (boolean|undefined),
* projection: (ol.Projection|undefined),
* tileGrid: (ol.tilegrid.TileGrid|undefined),
* tileUrlFunction: (ol.TileUrlFunctionType|undefined)}}
@@ -36,6 +36,7 @@ ol.source.ImageTileSource = function(options) {
goog.base(this, {
attributions: options.attributions,
extent: options.extent,
opaque: options.opaque,
projection: options.projection,
tileGrid: options.tileGrid
});
@@ -84,12 +85,15 @@ ol.source.ImageTileSource.prototype.expireCache = function(usedTiles) {
/**
* @inheritDoc
*/
ol.source.ImageTileSource.prototype.getTile = function(tileCoord) {
ol.source.ImageTileSource.prototype.getTile =
function(tileCoord, tileGrid, projection) {
var key = tileCoord.toString();
if (this.tileCache_.containsKey(key)) {
return /** @type {ol.Tile} */ (this.tileCache_.get(key));
} else {
var tileUrl = this.getTileCoordUrl(tileCoord);
goog.asserts.assert(tileGrid);
goog.asserts.assert(projection);
var tileUrl = this.tileUrlFunction(tileCoord, tileGrid, projection);
var tile;
if (goog.isDef(tileUrl)) {
tile = new ol.ImageTile(tileCoord, tileUrl, this.crossOrigin_);
@@ -102,15 +106,6 @@ ol.source.ImageTileSource.prototype.getTile = function(tileCoord) {
};
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @return {string|undefined} Tile URL.
*/
ol.source.ImageTileSource.prototype.getTileCoordUrl = function(tileCoord) {
return this.tileUrlFunction(tileCoord);
};
/**
* @inheritDoc
*/

View File

@@ -26,6 +26,7 @@ ol.source.MapQuestOSM = function() {
goog.base(this, {
attributions: attributions,
opaque: true,
maxZoom: 28,
url: 'http://otile{1-4}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg'
});
@@ -54,6 +55,7 @@ ol.source.MapQuestOpenAerial = function() {
goog.base(this, {
attributions: attributions,
maxZoom: 18,
opaque: true,
url: 'http://oatile{1-4}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg'
});

View File

@@ -18,6 +18,7 @@ ol.source.OpenStreetMap = function() {
goog.base(this, {
attributions: [attribution],
opaque: true,
maxZoom: 18,
url: 'http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
});

View File

@@ -1,11 +1,9 @@
goog.provide('ol.source.SingleImageWMS');
goog.require('goog.uri.utils');
goog.require('ol.Extent');
goog.require('ol.Image');
goog.require('ol.ImageUrlFunction');
goog.require('ol.Size');
goog.require('ol.projection');
goog.require('ol.source.ImageSource');
@@ -16,45 +14,16 @@ goog.require('ol.source.ImageSource');
* @param {ol.source.SingleImageWMSOptions} options Options.
*/
ol.source.SingleImageWMS = function(options) {
var projection = ol.projection.createProjection(
options.projection, 'EPSG:3857');
var projectionExtent = projection.getExtent();
var extent = goog.isDef(options.extent) ?
options.extent : projectionExtent;
var version = goog.isDef(options.version) ?
options.version : '1.3';
var baseParams = {
'SERVICE': 'WMS',
'VERSION': version,
'REQUEST': 'GetMap',
'STYLES': '',
'FORMAT': 'image/png',
'TRANSPARENT': true
};
baseParams[version >= '1.3' ? 'CRS' : 'SRS'] = projection.getCode();
goog.object.extend(baseParams, options.params);
var axisOrientation = projection.getAxisOrientation();
var imageUrlFunction;
if (options.url) {
var url = goog.uri.utils.appendParamsFromMap(
options.url, baseParams);
imageUrlFunction =
ol.ImageUrlFunction.createBboxParam(url, axisOrientation);
} else {
imageUrlFunction =
ol.ImageUrlFunction.nullImageUrlFunction;
}
var imageUrlFunction = goog.isDef(options.url) ?
ol.ImageUrlFunction.createWMSParams(
options.url, options.params, options.version) :
ol.ImageUrlFunction.nullImageUrlFunction;
goog.base(this, {
attributions: options.attributions,
crossOrigin: options.crossOrigin,
extent: extent,
projection: projection,
extent: options.extent,
projection: options.projection,
resolutions: options.resolutions,
imageUrlFunction: imageUrlFunction
});
@@ -80,7 +49,7 @@ goog.inherits(ol.source.SingleImageWMS, ol.source.ImageSource);
* @inheritDoc
*/
ol.source.SingleImageWMS.prototype.getImage =
function(extent, resolution) {
function(extent, resolution, projection) {
resolution = this.findNearestResolution(resolution);
var image = this.image_;
@@ -97,6 +66,6 @@ ol.source.SingleImageWMS.prototype.getImage =
var height = extent.getHeight() / resolution;
var size = new ol.Size(width, height);
this.image_ = this.createImage(extent, resolution, size);
this.image_ = this.createImage(extent, resolution, size, projection);
return this.image_;
};

View File

@@ -38,7 +38,8 @@ ol.source.Source = function(sourceOptions) {
* @type {ol.Extent}
*/
this.extent_ = goog.isDef(sourceOptions.extent) ?
sourceOptions.extent : sourceOptions.projection.getExtent();
sourceOptions.extent : goog.isDef(sourceOptions.projection) ?
sourceOptions.projection.getExtent() : null;
/**
* @private

View File

@@ -85,6 +85,7 @@ ol.source.Stamen = function(stamenOptions) {
goog.base(this, {
attributions: [attribution],
maxZoom: config.maxZoom,
opaque: false,
url: 'http://{a-d}.tile.stamen.com/' + layer + '/{z}/{x}/{y}.' + config.type
});

View File

@@ -19,6 +19,7 @@ ol.source.StaticImage = function(options) {
var imageExtent = options.imageExtent;
var imageSize = options.imageSize;
var imageResolution = imageExtent.getHeight() / imageSize.height;
var projection = goog.isDef(options.projection) ? options.projection : null;
goog.base(this, {
attributions: options.attributions,
@@ -33,7 +34,8 @@ ol.source.StaticImage = function(options) {
* @private
* @type {ol.Image}
*/
this.image_ = this.createImage(imageExtent, imageResolution, imageSize);
this.image_ = this.createImage(
imageExtent, imageResolution, imageSize, projection);
};
goog.inherits(ol.source.StaticImage, ol.source.ImageSource);
@@ -42,7 +44,8 @@ goog.inherits(ol.source.StaticImage, ol.source.ImageSource);
/**
* @inheritDoc
*/
ol.source.StaticImage.prototype.getImage = function(extent, resolution) {
ol.source.StaticImage.prototype.getImage =
function(extent, resolution, projection) {
if (extent.intersects(this.image_.getExtent())) {
return this.image_;
}
@@ -55,7 +58,7 @@ ol.source.StaticImage.prototype.getImage = function(extent, resolution) {
* @return {ol.ImageUrlFunctionType} Function.
*/
ol.source.StaticImage.createImageFunction = function(url) {
return function(extent, size) {
return function(extent, size, projection) {
return url;
};
};

View File

@@ -4,12 +4,9 @@ goog.provide('ol.source.TiledWMS');
goog.require('goog.array');
goog.require('goog.object');
goog.require('goog.uri.utils');
goog.require('ol.Extent');
goog.require('ol.TileCoord');
goog.require('ol.TileUrlFunction');
goog.require('ol.projection');
goog.require('ol.source.ImageTileSource');
@@ -20,61 +17,40 @@ goog.require('ol.source.ImageTileSource');
* @param {ol.source.TiledWMSOptions} tiledWMSOptions options.
*/
ol.source.TiledWMS = function(tiledWMSOptions) {
var projection = ol.projection.createProjection(
tiledWMSOptions.projection, 'EPSG:3857');
var projectionExtent = projection.getExtent();
var extent = goog.isDef(tiledWMSOptions.extent) ?
tiledWMSOptions.extent : projectionExtent;
var version = goog.isDef(tiledWMSOptions.version) ?
tiledWMSOptions.version : '1.3';
var tileGrid;
if (goog.isDef(tiledWMSOptions.tileGrid)) {
tileGrid = tiledWMSOptions.tileGrid;
} else {
tileGrid = ol.tilegrid.createForProjection(projection,
tiledWMSOptions.maxZoom);
}
var version = tiledWMSOptions.version;
var baseParams = {
'SERVICE': 'WMS',
'VERSION': version,
'REQUEST': 'GetMap',
'STYLES': '',
'FORMAT': 'image/png',
'TRANSPARENT': true
};
baseParams[version >= '1.3' ? 'CRS' : 'SRS'] = projection.getCode();
goog.object.extend(baseParams, tiledWMSOptions.params);
var axisOrientation = projection.getAxisOrientation();
var tileUrlFunction;
if (tiledWMSOptions.urls) {
var tileUrlFunctions = goog.array.map(
tiledWMSOptions.urls, function(url) {
url = goog.uri.utils.appendParamsFromMap(url, baseParams);
return ol.TileUrlFunction.createBboxParam(
url, tileGrid, axisOrientation);
return ol.TileUrlFunction.createWMSParams(
url, tiledWMSOptions.params, version);
});
tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions(
tileUrlFunctions);
} else if (tiledWMSOptions.url) {
var url = goog.uri.utils.appendParamsFromMap(
tiledWMSOptions.url, baseParams);
tileUrlFunction =
ol.TileUrlFunction.createBboxParam(url, tileGrid, axisOrientation);
tileUrlFunction = ol.TileUrlFunction.createWMSParams(
tiledWMSOptions.url, tiledWMSOptions.params, version);
} else {
tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction;
}
var transparent = goog.isDef(tiledWMSOptions.transparent) ?
tiledWMSOptions.transparent : true;
var extent = tiledWMSOptions.extent;
var tileCoordTransform = function(tileCoord) {
var tileCoordTransform = function(tileCoord, tileGrid, projection) {
if (tileGrid.getResolutions().length <= tileCoord.z) {
return null;
}
var x = tileCoord.x;
var tileExtent = tileGrid.getTileCoordExtent(tileCoord);
var projectionExtent = projection.getExtent();
var extent = goog.isDef(tiledWMSOptions.extent) ?
tiledWMSOptions.extent : projectionExtent;
// FIXME do we want a wrapDateLine param? The code below will break maps
// with projections that do not span the whole world width.
if (extent.minX === projectionExtent.minX &&
@@ -96,8 +72,9 @@ ol.source.TiledWMS = function(tiledWMSOptions) {
attributions: tiledWMSOptions.attributions,
crossOrigin: tiledWMSOptions.crossOrigin,
extent: extent,
tileGrid: tileGrid,
projection: projection,
tileGrid: tiledWMSOptions.tileGrid,
opaque: !transparent,
projection: tiledWMSOptions.projection,
tileUrlFunction: ol.TileUrlFunction.withTileCoordTransform(
tileCoordTransform, tileUrlFunction)
});

View File

@@ -15,6 +15,7 @@ goog.require('ol.tilegrid.TileGrid');
/**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* extent: (ol.Extent|undefined),
* opaque: (boolean|undefined),
* projection: (ol.Projection|undefined),
* tileGrid: (ol.tilegrid.TileGrid|undefined)}}
*/
@@ -35,6 +36,13 @@ ol.source.TileSource = function(tileSourceOptions) {
projection: tileSourceOptions.projection
});
/**
* @private
* @type {boolean}
*/
this.opaque_ = goog.isDef(tileSourceOptions.opaque) ?
tileSourceOptions.opaque : false;
/**
* @protected
* @type {ol.tilegrid.TileGrid}
@@ -65,14 +73,14 @@ ol.source.TileSource.prototype.expireCache = goog.abstractMethod;
*
* @param {Object.<number, Object.<string, ol.Tile>>} loadedTilesByZ A lookup of
* loaded tiles by zoom level.
* @param {function(ol.Tile): boolean} isLoaded A function to determine if a
* tile is fully loaded.
* @param {function(ol.TileCoord): ol.Tile} getTileIfLoaded A function that
* returns the tile only if it is fully loaded.
* @param {number} z Zoom level.
* @param {ol.TileRange} tileRange Tile range.
* @return {boolean} The tile range is fully covered with loaded tiles.
*/
ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ,
isLoaded, z, tileRange) {
getTileIfLoaded, z, tileRange) {
// FIXME this could be more efficient about filling partial holes
var fullyCovered = true;
var tile, tileCoord, tileCoordKey, x, y;
@@ -83,8 +91,8 @@ ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ,
if (loadedTilesByZ[z] && loadedTilesByZ[z][tileCoordKey]) {
continue;
}
tile = this.getTile(tileCoord);
if (isLoaded(tile)) {
tile = getTileIfLoaded(tileCoord);
if (!goog.isNull(tile)) {
if (!loadedTilesByZ[z]) {
loadedTilesByZ[z] = {};
}
@@ -98,6 +106,14 @@ ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ,
};
/**
* @return {boolean} Opaque.
*/
ol.source.TileSource.prototype.getOpaque = function() {
return this.opaque_;
};
/**
* @inheritDoc
*/
@@ -108,6 +124,8 @@ ol.source.TileSource.prototype.getResolutions = function() {
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {ol.tilegrid.TileGrid=} opt_tileGrid Tile grid.
* @param {ol.Projection=} opt_projection Projection.
* @return {ol.Tile} Tile.
*/
ol.source.TileSource.prototype.getTile = goog.abstractMethod;
@@ -124,9 +142,10 @@ ol.source.TileSource.prototype.getTileGrid = function() {
/**
* @param {number} z Z.
* @param {ol.Extent} extent Extent.
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
*/
ol.source.TileSource.prototype.useLowResolutionTiles = function(z, extent) {
var tileGrid = this.getTileGrid();
ol.source.TileSource.prototype.useLowResolutionTiles =
function(z, extent, tileGrid) {
var tileRange, x, y, zKey;
// FIXME this should loop up to tileGrid's minZ when implemented
for (; z >= 0; --z) {

37
src/ol/source/wms.js Normal file
View File

@@ -0,0 +1,37 @@
goog.provide('ol.source.wms');
/**
* @param {string} baseUrl WMS base url.
* @param {Object.<string, string|number>} params Request parameters.
* @param {ol.Extent} extent Extent.
* @param {ol.Size} size Size.
* @param {ol.Projection} projection Projection.
* @param {string=} opt_version WMS version. Default is '1.3.0'.
* @return {string} WMS GetMap request URL.
*/
ol.source.wms.getUrl =
function(baseUrl, params, extent, size, projection, opt_version) {
var version = goog.isDef(opt_version) ? opt_version : '1.3.0';
var wms13 = version >= '1.3';
var axisOrientation = projection.getAxisOrientation();
var bboxValues = (wms13 && axisOrientation.substr(0, 2) == 'ne') ?
[extent.minY, extent.minX, extent.maxY, extent.maxX] :
[extent.minX, extent.minY, extent.maxX, extent.maxY];
var baseParams = {
'SERVICE': 'WMS',
'VERSION': version,
'REQUEST': 'GetMap',
'FORMAT': 'image/png',
'TRANSPARENT': true,
'WIDTH': size.width,
'HEIGHT': size.height,
'BBOX': bboxValues.join(',')
};
goog.object.extend(baseParams, params);
baseParams[wms13 ? 'CRS' : 'SRS'] = projection.getCode();
//TODO: Provide our own appendParams function to avoid this empty string hack
var stylesParam = 'STYLES';
baseParams[stylesParam] = params[stylesParam] || new String('');
return goog.uri.utils.appendParamsFromMap(baseUrl, baseParams);
};

View File

@@ -20,6 +20,12 @@ goog.require('ol.array');
ol.DEFAULT_TILE_SIZE = 256;
/**
* @define {number} Default maximum zoom for default tile grids.
*/
ol.DEFAULT_MAX_ZOOM = 42;
/**
* @constructor
@@ -89,8 +95,7 @@ ol.tilegrid.TileGrid = function(tileGridOptions) {
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {function(this: T, number, ol.TileRange): boolean} callback
* Callback.
* @param {function(this: T, number, ol.TileRange): boolean} callback Callback.
* @param {T=} opt_obj Object.
* @template T
*/
@@ -328,7 +333,21 @@ ol.tilegrid.TileGrid.prototype.getZForResolution = function(resolution) {
/**
* @param {ol.Projection} projection Projection.
* @param {number=} opt_maxZoom Maximum zoom level (optional). Default is 18.
* @return {ol.tilegrid.TileGrid} Default tile grid for the passed projection.
*/
ol.tilegrid.getForProjection = function(projection) {
var tileGrid = projection.getDefaultTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = ol.tilegrid.createForProjection(projection);
projection.setDefaultTileGrid(tileGrid);
}
return tileGrid;
};
/**
* @param {ol.Projection} projection Projection.
* @param {number=} opt_maxZoom Maximum zoom level.
* @param {ol.Size=} opt_tileSize Tile size.
* @return {ol.tilegrid.TileGrid} TileGrid instance.
*/
@@ -339,7 +358,7 @@ ol.tilegrid.createForProjection =
projectionExtent.maxX - projectionExtent.minX,
projectionExtent.maxY - projectionExtent.minY);
var maxZoom = goog.isDef(opt_maxZoom) ?
opt_maxZoom : 18;
opt_maxZoom : ol.DEFAULT_MAX_ZOOM;
var tileSize = goog.isDef(opt_tileSize) ?
opt_tileSize : new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE);
var resolutions = new Array(maxZoom + 1);

View File

@@ -3,13 +3,14 @@ goog.provide('ol.TileUrlFunctionType');
goog.require('goog.array');
goog.require('goog.math');
goog.require('goog.uri.utils');
goog.require('ol.TileCoord');
goog.require('ol.source.wms');
goog.require('ol.tilegrid.TileGrid');
/**
* @typedef {function(ol.TileCoord): (string|undefined)}
* @typedef {function(ol.TileCoord, ol.tilegrid.TileGrid, ol.Projection):
* (string|undefined)}
*/
ol.TileUrlFunctionType;
@@ -59,12 +60,12 @@ ol.TileUrlFunction.createFromTemplates = function(templates) {
* @return {ol.TileUrlFunctionType} Tile URL function.
*/
ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) {
return function(tileCoord) {
return function(tileCoord, tileGrid, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {
var index = goog.math.modulo(tileCoord.hash(), tileUrlFunctions.length);
return tileUrlFunctions[index](tileCoord);
return tileUrlFunctions[index](tileCoord, tileGrid, projection);
}
};
};
@@ -72,25 +73,20 @@ ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) {
/**
* @param {string} baseUrl Base URL (may have query data).
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
* @param {string} axisOrientation Axis orientation.
* @param {Object.<string, string|number>} params WMS parameters.
* @param {string=} opt_version WMS version.
* @return {ol.TileUrlFunctionType} Tile URL function.
*/
ol.TileUrlFunction.createBboxParam =
function(baseUrl, tileGrid, axisOrientation) {
return function(tileCoord) {
ol.TileUrlFunction.createWMSParams =
function(baseUrl, params, opt_version) {
return function(tileCoord, tileGrid, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {
var tileExtent = tileGrid.getTileCoordExtent(tileCoord);
var bboxValues = axisOrientation.substr(0, 2) == 'ne' ?
[tileExtent.minY, tileExtent.minX, tileExtent.maxY, tileExtent.maxX] :
[tileExtent.minX, tileExtent.minY, tileExtent.maxX, tileExtent.maxY];
var tileSize = tileGrid.getTileSize(tileCoord.z);
return goog.uri.utils.appendParams(baseUrl,
'BBOX', bboxValues.join(','),
'HEIGHT', tileSize.height,
'WIDTH', tileSize.width);
var size = tileGrid.getTileSize(tileCoord.z);
var extent = tileGrid.getTileCoordExtent(tileCoord);
return ol.source.wms.getUrl(
baseUrl, params, extent, size, projection, opt_version);
}
};
};
@@ -106,18 +102,19 @@ ol.TileUrlFunction.nullTileUrlFunction = function(tileCoord) {
/**
* @param {function(ol.TileCoord): ol.TileCoord} transformFn
* Transform.function.
* @param {function(ol.TileCoord, ol.tilegrid.TileGrid, ol.Projection):
* ol.TileCoord} transformFn Transform.function.
* @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function.
* @return {ol.TileUrlFunctionType} Tile URL function.
*/
ol.TileUrlFunction.withTileCoordTransform =
function(transformFn, tileUrlFunction) {
return function(tileCoord) {
return function(tileCoord, tileGrid, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {
return tileUrlFunction(transformFn(tileCoord));
return tileUrlFunction(
transformFn(tileCoord, tileGrid, projection), tileGrid, projection);
}
};
};