Refactor ol.source.ImageWMS URL logic

* Always request images of integer WIDTH and HEIGHT
* Match BBOX to requested size
* Handle integer-only DPIs in GeoServer
This commit is contained in:
Tom Payne
2014-01-08 21:19:52 +01:00
parent 95f1871ac4
commit e9d8401786

View File

@@ -1,43 +1,48 @@
// FIXME factor out v13 calculation
goog.provide('ol.source.ImageWMS');
goog.require('goog.asserts');
goog.require('goog.object');
goog.require('goog.string');
goog.require('goog.uri.utils');
goog.require('ol.Image');
goog.require('ol.ImageUrlFunction');
goog.require('ol.extent');
goog.require('ol.source.Image');
goog.require('ol.source.wms');
goog.require('ol.source.wms.ServerType');
/**
* @constructor
* @extends {ol.source.Image}
* @param {olx.source.ImageWMSOptions} options Options.
* @param {olx.source.ImageWMSOptions=} opt_options Options.
* @todo stability experimental
*/
ol.source.ImageWMS = function(options) {
ol.source.ImageWMS = function(opt_options) {
/**
* @private
* @type {Object}
*/
this.params_ = options.params;
var imageUrlFunction = goog.isDef(options.url) ?
ol.ImageUrlFunction.createFromParamsFunction(
options.url, this.params_, ol.source.wms.getUrl) :
ol.ImageUrlFunction.nullImageUrlFunction;
var options = goog.isDef(opt_options) ? opt_options : {};
goog.base(this, {
attributions: options.attributions,
crossOrigin: options.crossOrigin,
extent: options.extent,
projection: options.projection,
resolutions: options.resolutions,
imageUrlFunction: imageUrlFunction
resolutions: options.resolutions
});
/**
* @private
* @type {string|undefined}
*/
this.url_ = options.url;
/**
* @private
* @type {Object}
*/
this.params_ = options.params;
/**
* @private
* @type {ol.source.wms.ServerType|undefined}
@@ -81,8 +86,16 @@ ol.source.ImageWMS.prototype.getParams = function() {
*/
ol.source.ImageWMS.prototype.getImage =
function(extent, resolution, pixelRatio, projection) {
if (!goog.isDef(this.url_)) {
return null;
}
resolution = this.findNearestResolution(resolution);
pixelRatio = this.hidpi_ ? pixelRatio : 1;
if (pixelRatio != 1 && (!this.hidpi_ || !goog.isDef(this.serverType_))) {
pixelRatio = 1;
}
var image = this.image_;
if (!goog.isNull(image) &&
@@ -92,20 +105,83 @@ ol.source.ImageWMS.prototype.getImage =
return image;
}
extent = extent.slice();
ol.extent.scaleFromCenter(extent, this.ratio_);
var width = (extent[2] - extent[0]) / resolution;
var height = (extent[3] - extent[1]) / resolution;
var size = [width * pixelRatio, height * pixelRatio];
var params = {
'SERVICE': 'WMS',
'VERSION': '1.3.0',
'REQUEST': 'GetMap',
'FORMAT': 'image/png',
'TRANSPARENT': true
};
goog.object.extend(params, this.params_);
if (goog.isDef(this.serverType_) && pixelRatio > 1) {
var param = ol.source.wms.getDpiParam(this.serverType_, pixelRatio);
goog.object.extend(this.params_, param);
var v13 = goog.string.compareVersions(
goog.object.get(params, 'VERSION'), '1.3') >= 0;
params[v13 ? 'CRS' : 'SRS'] = projection.getCode();
if (!('STYLES' in this.params_)) {
goog.object.set(params, 'STYLES', new String(''));
}
this.image_ = this.createImage(
extent, resolution, pixelRatio, size, projection);
if (pixelRatio != 1) {
switch (this.serverType_) {
case ol.source.wms.ServerType.GEOSERVER:
var dpi = (90 * pixelRatio + 0.5) | 0;
goog.object.set(params, 'FORMAT_OPTIONS', 'dpi:' + dpi);
break;
case ol.source.wms.ServerType.MAPSERVER:
goog.object.set(params, 'MAP_RESOLUTION', 90 * pixelRatio);
break;
case ol.source.wms.ServerType.QGIS:
goog.object.set(params, 'DPI', 90 * pixelRatio);
break;
default:
goog.asserts.fail();
break;
}
}
extent = extent.slice();
var centerX = (extent[0] + extent[2]) / 2;
var centerY = (extent[1] + extent[3]) / 2;
if (this.ratio_ != 1) {
var halfWidth = this.ratio_ * (extent[2] - extent[0]) / 2;
var halfHeight = this.ratio_ * (extent[3] - extent[1]) / 2;
extent[0] = centerX - halfWidth;
extent[1] = centerY - halfHeight;
extent[2] = centerX + halfWidth;
extent[3] = centerY + halfHeight;
}
var imageResolution = resolution / pixelRatio;
// Compute an integer width and height.
var width = Math.ceil((extent[2] - extent[0]) / imageResolution);
goog.object.set(params, 'WIDTH', width);
var height = Math.ceil((extent[3] - extent[1]) / imageResolution);
goog.object.set(params, 'HEIGHT', height);
// Modify the extent to match the integer width and height.
extent[0] = centerX - imageResolution * width / 2;
extent[2] = centerX + imageResolution * width / 2;
extent[1] = centerY - imageResolution * height / 2;
extent[3] = centerY + imageResolution * height / 2;
var axisOrientation = projection.getAxisOrientation();
var bbox;
if (v13 && axisOrientation.substr(0, 2) == 'ne') {
bbox = [extent[1], extent[0], extent[3], extent[2]];
} else {
bbox = extent;
}
goog.object.set(params, 'BBOX', bbox.join(','));
var url = goog.uri.utils.appendParamsFromMap(this.url_, params);
this.image_ = new ol.Image(extent, resolution, pixelRatio, url,
this.crossOrigin, this.getAttributions());
return this.image_;
};